在Django Admin中将ForeignKey设为可选? [英] Make ForeignKey optional in Django Admin?

查看:108
本文介绍了在Django Admin中将ForeignKey设为可选?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个自定义的django管理页面,我想在管理界面中将两个ForeignKey字段设置为可选。我不想更改基础模型。

I have a custom django admin page, and I would like to make the two ForeignKey fields optional in the admin interface. I do not want to change the underlying model.

这是模型:

class IncorporationTicket(models.Model, AdminURL):
    ordered_by = models.ForeignKey('Organisation', # organisation which ordered this
                                   null = True,
                                   blank = False, # i.e. can only be null as a result of delete
                                   on_delete = models.SET_NULL)
    ordered_by_individual = models.ForeignKey('Individual', # individual at organisation which ordered this
                                               null = True,
                                               blank = False, # i.e. can only be null as a result of delete
                                               on_delete = models.SET_NULL)

(AdminURL是提供get_absolute_url的mixin)

(AdminURL is a mixin which provides get_absolute_url)

这是ModelAdmin:

This is the ModelAdmin:

class TicketAdmin(admin.ModelAdmin):
    readonly_fields = ('ordered', 'charge', 'amount_paid', 'submitted_on')

    formfield_overrides = {
        models.ForeignKey: {'required': False},
        }


    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        pk = resolve(request.path).args[0] # the request url should only have one arg, the pk
        instance = self.get_object(request, pk) 
        user = request.user
        kwargs['required'] = False # will be passed to every field

        if db_field.name == "ordered_by_individual":
            # queryset should be a union of (a) individual already set on object (b) individual for current user
            ## None option is provided by admin interface - just need to let field be optional.
            if instance.ordered_by_individual:
                kwargs["queryset"] = (
                    Individual.objects.filter(pk = instance.ordered_by_individual.pk) |
                    user.individual_set.all())
            else: kwargs["queryset"] = user.individual_set.all()
        elif db_field.name == "ordered_by":
            # queryset should be a union of (a) organisation already set (b) any organisations for which user is authorised

           try:
               individual = user.individual_set.all()[0]
               all_orgs = Organisation.all_organisations_for_which_individual_authorised_to_incorporate(individual)
           except:
               all_orgs = Organisation.objects.none()
           if instance.ordered_by:
               kwargs["queryset"] = (
                   Organisation.objects.filter(pk = instance.ordered_by.pk) |
                   all_orgs)
           else: kwargs["queryset"] = all_orgs

        return super(type(self), self).formfield_for_foreignkey(db_field, request, **kwargs)

如您所见,我尝试同时使用 formfield_overrides formfield_for_foreignkey 来在FormField上设置 required = False ,但没有达到所需的效果:尝试通过管理员保存时界面未设置(即,将字段保留为原始空白状态),管理界面会显示错误此字段为必填字段。

As you can see, I have tried to use both formfield_overrides, and formfield_for_foreignkey to set required = False on the FormField, but it is not having the required effect: when attempting to save through the admin interface without setting (that is, leaving the field in its original blank state), the admin interface shows the error 'This field is required.'

因此,我的问题是:如何防止基础表单要求某些字段,同时仍在 formfield_for_foreignkey 中设置选择?

So, my question is: how does one prevent the underlying form from requiring certain fields, while still also setting the choices in formfield_for_foreignkey?

推荐答案

虽然我不确定为什么 kwargs ['required'] 不会工作时,您始终可以使用自己的表单来覆盖管理表单。

While I'm not sure why kwargs['required'] wouldn't work, you could always override the admin form with your own form. It hasn't failed me with magical django admin behavior so it's a pretty good bet.

class MyForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(MyForm, self).__init__(*args, **kwargs)
        self.fields['my_fk_field'].required = False

    class Meta:
         model = MyModel

class MyAdmin(admin.ModelAdmin):
    form = MyForm

这仍然允许您通过<$ c修改 QuerySet $ c> formfield_for_foo 方法。

This would still allow you to modify the QuerySet via the formfield_for_foo methods.

这篇关于在Django Admin中将ForeignKey设为可选?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆