Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Django限制基于选定FK的多个查询集_Django_Django Admin - Fatal编程技术网

Django限制基于选定FK的多个查询集

Django限制基于选定FK的多个查询集,django,django-admin,Django,Django Admin,我有一个这样的模型: class Invite(models.Model): user = models.ForeignKey(User) event = models.ForeignKey(Event) roles = models.ManyToManyField(Role, blank=True, null=True) sent = models.BooleanField("Invite Sent", default=False, editable=Fals

我有一个这样的模型:

class Invite(models.Model):
    user = models.ForeignKey(User)
    event = models.ForeignKey(Event)
    roles = models.ManyToManyField(Role, blank=True, null=True)
    sent =  models.BooleanField("Invite Sent", default=False, editable=False)
    created = models.DateTimeField(auto_now_add=True)

    def __unicode__(self):
        return u"%s" % self.user

    class Meta:
        unique_together =(('user','event'),)


class Role(models.Model):
    """
    This associates a user's role to an event
    """
    event = models.ForeignKey(Event, related_name="roles")
    roletype = models.ForeignKey(RoleType)
    profiles = models.ManyToManyField(Profile, related_name="roles",
            blank=True, null=True)
    modified = models.DateTimeField(auto_now=True)
    created = models.DateTimeField(auto_now_add=True)

因此,每当创建一个新事件时,都会创建一组角色。在Invite模型中,如何在Django Admin中仅显示与我在更改表单中选择的事件相关联的角色,而不显示角色模型中的所有条目?

您需要在管理类中为模型提供自定义方法

这个示例(来自我链接的文档)应该让您开始:

class MyModelAdmin(admin.ModelAdmin):
    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == "car":
            kwargs["queryset"] = Car.objects.filter(owner=request.user)
        return super(MyModelAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)

您希望动态筛选
角色的选择
选择
,因此需要
ajax
来执行此任务

下面是你如何使这项工作成功的方法

1:
一旦更改
事件
,通过
ajax
事件id
发送到您的自定义
视图

2:根据从
ajax
请求获得的
事件id
角色
模型
过滤器
,并通过
序列化
JSON
返回过滤后的
角色

3:清除现有的
角色
并通过
JSON
响应解析重新填充

例如: 这是一个
jquery
getJSON
示例

javascript:

$("#event").change(function (){         
 var event_id = $(this).val();              
    $.getJSON("/my-app/my-roles-filter-view/"+ event_id +"/",function(data){
        var roles_dd = $("#roles");
        $('#event >option').remove();
        $.each(data, function(index,value) {
        roles_dd.append($("<option />").val(value).text(value));
    });                 
})(django.jquery);

这只是一个使用
jquery
的示例,您可以使用任何类型的
ajax
来实现这一点。

您可能需要以下内容:

class InviteAdmin(admin.ModelAdmin):
    def get_form(self, request, obj=None, **kwargs):
        self.instance = obj # Capture instance before the form gets generated   
        return super(InviteAdmin, self).get_form(request, obj=obj, **kwargs)

    def formfield_for_manytomany(self, db_field, request=None, **kwargs):
        if db_field.name == 'role' and self.instance:
            # restrict role queryset to those related to this instance:         
            kwargs['queryset'] = self.instance.event.roles.all()
        return super(InviteAdmin, self).formfield_for_manytomany(
            db_field, request=request, **kwargs)

我认为有两种方法可以解决这个问题:

  • @Pannu描述的ajax方法

  • 非ajax方法,可通过将
    事件
    字段移动到更改表单之外(这意味着将有另一个表单更改
    事件
    )并基于当前
    事件
    过滤
    角色
    来实现。最近,我不得不解决类似的问题,根据对象对特定站点的归属限制可用选项。以下是说明和代码,如果您感兴趣:


  • 这将在加载时完成,并且不是动态的。我相信
    选择
    必须动态地
    过滤
    。这就是问题所在。@Pannu:不,这实际上接近正确的解决方案,但要解决这个特定问题,您需要访问相关的Invite实例。问题清楚地表明“如何在更改表单中仅显示与我选择的事件相关联的角色”,这是肯定要做的(ajax)。您的解决方案是静态的。啊,我错过了这个细节,谢谢。我不一定把它称为静态解决方案,因为它根据加载的对象和数据库中选择的事件而变化,但我认为您是对的,这并不能解决实际出现的问题:)解决方案需要java脚本,因为当他在表单中选择
    事件时,角色必须动态过滤(无需按下按钮,提交整个表单,然后返回过滤后的选项),因此
    ajax
    是一种方法。是的,如果您希望在更改小部件中的选定事件时在浏览器中更改它,那么您当然需要使用Javascript。对不起,我看错了。
    def my_view(request,event_id):
        qs = Role.objects.filter(event=event_id).values_list('id')
        return HttpResponse(simplejson.dumps(qs),mimetype='application/javascript')
    
    class InviteAdmin(admin.ModelAdmin):
        def get_form(self, request, obj=None, **kwargs):
            self.instance = obj # Capture instance before the form gets generated   
            return super(InviteAdmin, self).get_form(request, obj=obj, **kwargs)
    
        def formfield_for_manytomany(self, db_field, request=None, **kwargs):
            if db_field.name == 'role' and self.instance:
                # restrict role queryset to those related to this instance:         
                kwargs['queryset'] = self.instance.event.roles.all()
            return super(InviteAdmin, self).formfield_for_manytomany(
                db_field, request=request, **kwargs)