【问题标题】:django admin overriding change_view with foreignkey filterdjango admin 使用外键过滤器覆盖 change_view
【发布时间】:2012-06-27 10:14:48
【问题描述】:

在我的 django ModelAdmin 中,我想根据当前用户组过滤外键选择,并且我想以添加和更改形式实现它。我使用以下代码在添加视图中实现了它。

add_view

def add_view(self, request, form_url = '', extra_context = None):
    service_sector = common.getServiceSector(request.user)
    ModelForm = self.get_form(request)
    if request.POST:
        form = ModelForm(request.POST, request.FILES)
    else:
        form = ModelForm()
    if service_sector:
        qs = form['member'].field.queryset
        qs = qs.filter(service_sector = service_sector)
        form['member'].field.queryset = qs
    adminForm = helpers.AdminForm(form, list(self.get_fieldsets(request)),
    self.prepopulated_fields, self.get_readonly_fields(request),
    model_admin=self)
    context = {
    'adminform': adminForm,
    'is_popup': "_popup" in request.REQUEST,
    'show_delete': False,
    'root_path': self.admin_site.root_path,
    }
    context.update(extra_context or {})
    return self.render_change_form(request, context, form_url=form_url, add=True)

在这里它工作正常。在这个模型中,我有一个独特的字段 Email,这导致了 change_view 中的问题。我在下面给出了我的 change_view 代码。

change_view

def change_view(self, request, object_id, form_url = '', extra_context = None):
    qs = self.model._default_manager.get_query_set()

    service_sector = common.getServiceSector(request.user)
    bene_object = Beneficiary.objects.get(pk=object_id)
    ModelForm = self.get_form(request, bene_object)
    if request.POST:
        form = ModelForm(request.POST, request.FILES)
    else:                     

        form = ModelForm(instance=bene_object)            
    if service_sector:
        qs = form['member'].field.queryset
        qs = qs.filter(service_sector = service_sector)
        form['member'].field.queryset = qs
    adminForm = helpers.AdminForm(form, list(self.get_fieldsets(request)),
    self.prepopulated_fields, self.get_readonly_fields(request),
    model_admin=self)
    context = {
    'adminform': adminForm,
    'is_popup': "_popup" in request.REQUEST,
    'show_delete': False,
    'root_path': self.admin_site.root_path,
    }
    context.update(extra_context or {})
    return self.render_change_form(request, context, form_url = form_url, change = True)

即使我在我的 change_view 返回中给出了change = True,它仍在尝试将对象另存为新对象。所以我收到一个错误Email already exists,因为电子邮件字段是唯一值字段。或者是否可以使用正常的change_view返回如下:

return super(ModelAdmin, self).change_view(request, form_url, extra_context)

如果是这样,我如何过滤外键选择。或者如何使用render_change_form 来实现这一点?提前致谢。

【问题讨论】:

    标签: django django-admin


    【解决方案1】:

    我已解决此问题并在此处发布答案,这可能对其他人有所帮助。问题here 帮助我解决了这个问题。使用以下代码,我已经完成了基于用户组的外键过滤器,用于在 django admin 中添加和更改表单,其中包含内联表单集。我在下面给出代码:

    def render_change_form(self, request, context, *args, **kwargs):
        model = self.model
        opts = model._meta
        formsets = []
    
        #Change view
        if 'change' in kwargs.keys():
            object_id   = kwargs['obj'].id  #To get object id
            object      = Modelobjects.get(pk=object_id)
            ModelForm   = self.get_form(request, object)
            qs          = self.model._default_manager.get_query_set()
            if request.POST:
                form = ModelForm(request.POST, request.FILES)
            else:
                form = ModelForm(instance = object)
            service_sector = common.getServiceSector(request.user)
            if service_sector:
                #To filter foreignkey
                qs = form['member'].field.queryset
                qs = qs.filter(service_sector = service_sector)
                form['member'].field.queryset = qs
            adminForm = helpers.AdminForm(form, list(self.get_fieldsets(request)),
            self.prepopulated_fields, self.get_readonly_fields(request),
            model_admin=self)
            media = self.media + adminForm.media
    
            #To get inline formsets used
            prefixes = {}
            for FormSet, inline in zip(self.get_formsets(request),
                                       self.inline_instances):
                prefix = FormSet.get_default_prefix()
                prefixes[prefix] = prefixes.get(prefix, 0) + 1
                if prefixes[prefix] != 1:
                    prefix = "%s-%s" % (prefix, prefixes[prefix])
                formset = FormSet(instance=object, prefix=prefix,
                                  queryset=inline.queryset(request))
                formsets.append(formset)
    
            inline_admin_formsets = []
            for inline, formset in zip(self.inline_instances, formsets):
                fieldsets = list(inline.get_fieldsets(request))
                readonly = list(inline.get_readonly_fields(request))
                inline_admin_formset = helpers.InlineAdminFormSet(inline, formset,
                    fieldsets, readonly, model_admin=self)
                inline_admin_formsets.append(inline_admin_formset)
                media = media + inline_admin_formset.media
    
        else:
            #Add view
            ModelForm   = self.get_form(request)
            qs          = self.model._default_manager.get_query_set()
            if request.POST:
                form = ModelForm(request.POST, request.FILES)
            else:
                form = ModelForm()
            service_sector = common.getServiceSector(request.user)
            if service_sector:
                qs = form['member'].field.queryset
                qs = qs.filter(service_sector = service_sector)
                form['member'].field.queryset = qs
            adminForm = helpers.AdminForm(form, list(self.get_fieldsets(request)),
            self.prepopulated_fields, self.get_readonly_fields(request),
            model_admin=self)
            media = self.media + adminForm.media
    
            prefixes = {}
            for FormSet, inline in zip(self.get_formsets(request),
                                       self.inline_instances):
                prefix = FormSet.get_default_prefix()
                prefixes[prefix] = prefixes.get(prefix, 0) + 1
                if prefixes[prefix] != 1:
                    prefix = "%s-%s" % (prefix, prefixes[prefix])
                formset = FormSet(instance=self.model(), prefix=prefix,
                                  queryset=inline.queryset(request))
                formsets.append(formset)
    
            inline_admin_formsets = []
            for inline, formset in zip(self.inline_instances, formsets):
                fieldsets = list(inline.get_fieldsets(request))
                readonly = list(inline.get_readonly_fields(request))
                inline_admin_formset = helpers.InlineAdminFormSet(inline, formset,
                    fieldsets, readonly, model_admin=self)
                inline_admin_formsets.append(inline_admin_formset)
                media = media + inline_admin_formset.media
    
        context = {
        'adminform': adminForm,
        'title': _('Add %s') % force_unicode(opts.verbose_name),
        'is_popup': "_popup" in request.REQUEST,
        'show_delete': False,
        'media': mark_safe(media),
        'inline_admin_formsets': inline_admin_formsets,
        'root_path': self.admin_site.root_path,
        }
        return super(ModelAdmin, self).render_change_form(request, context, args, kwargs)
    

    这里的object id是从kwargs['obj'].id获取的,foreignkey被过滤了

    qs = form['member'].field.queryset
    qs = qs.filter(service_sector = service_sector)
    form['member'].field.queryset = qs
    

    这里的common.getServiceSector 是我用于外键过滤条件的自定义方法。您可以根据自己的要求定义自己的方法。希望这对其他人有帮助。谢谢。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-23
      • 2012-04-28
      • 2019-07-02
      • 2015-10-10
      • 1970-01-01
      • 2014-01-30
      • 2019-02-12
      • 2017-05-26
      相关资源
      最近更新 更多