Django ModelChoiceField 没有加号按钮

Posted

技术标签:

【中文标题】Django ModelChoiceField 没有加号按钮【英文标题】:Django ModelChoiceField has no plus button 【发布时间】:2013-09-07 07:04:39 【问题描述】:

我正在制作一个带有自定义用户的 Django 应用程序。我在下面概述了我的问题的关键组成部分,缺少的代码用“...”表示。我的自定义用户模型有如下外键关系:

class MyCustomUser(models.AbstractBaseUser, models.PermissionsMixin)
    ...
    location = models.ForeignKey(Location)

class Location(models.Model)
    name = models.CharField(max_length=50, blank=True, null=True)

我编写了一个包含该字段的自定义用户表单,如下所示:

class MyCustomUserCreationForm(models.ModelForm)
    ...
    location = forms.ModelChoiceField(Location.objects.all())

这一切似乎工作正常,但是,位置选择字段的右侧没有加号按钮。我希望能够在创建用户时添加位置,就像在 Django tutorial 中创建选项时添加投票一样。根据to this question,如果我没有更改模型的权限,我可能看不到绿色加号,但我以具有所有权限的超级用户身份登录。知道我做错了什么吗?

【问题讨论】:

【参考方案1】:

您需要在模型表单中设置RelatedFieldWidgetWrapper 包装器:

RelatedFieldWidgetWrapper(在 django.contrib.admin.widgets 中找到) 在管理页面中用于包含外键的功能 控件以添加新的相关记录。 (英文:将绿色的小加号放在控件的右侧。)

class MyCustomUserCreationForm(models.ModelForm)
    ...
    location = forms.ModelChoiceField(queryset=Location.objects.all())

    def __init__(self, *args, **kwargs):
        super(MyCustomUserCreationForm, self).__init__(*args, **kwargs)
        rel = ManyToOneRel(self.instance.location.model, 'id') 
        self.fields['location'].widget = RelatedFieldWidgetWrapper(self.fields['location'].widget, rel, self.admin_site)

我可能会在示例代码中出错,请参阅这些帖子和示例:

RelatedFieldWidgetWrapper More RelatedFieldWidgetWrapper – My Very Own Popup Django admin - How can I add the green plus sign for Many-to-many Field in custom admin form How can I manually use RelatedFieldWidgetWrapper around a custom widget? Django: override RelatedFieldWidgetWrapper

【讨论】:

您为我指明了正确的方向,感谢所有链接。我使用了您的代码,但我不得不对其进行一些修改。我必须在 ModelAdmin 中添加几行以将管理站点传递给表单,并将 rel 定义为 MyCustomUser._meta.get_fields('location').rel @EmeraldOwl:小错误 -- MyCustomUser._meta.get_field('location').rel. 'ForeignKey' 对象在我使用 yCustomUser._meta.get_field('my_field').rel 时没有属性 'rel' 我使用的是 Django 3 并且“rel”属性未在 get field 方法的返回类型中定义,将“remote_field”属性改为“rel” 你能帮忙解决这个问题吗***.com/questions/69289560/…【参考方案2】:

我根据上面的答案创建了方法:

def add_related_field_wrapper(form, col_name):
    rel_model = form.Meta.model
    rel = rel_model._meta.get_field(col_name).rel
    form.fields[col_name].widget = 
    RelatedFieldWidgetWrapper(form.fields[col_name].widget, rel, 
    admin.site, can_add_related=True, can_change_related=True)

然后从我的表单中调用这个方法:

class FeatureForm(forms.ModelForm):
    offer = forms.ModelChoiceField(queryset=Offer.objects.all(), required=False)
    package = forms.ModelChoiceField(queryset=Package.objects.all(), required=False)
    def __init__(self, *args, **kwargs):
        super(FeatureForm, self).__init__(*args, **kwargs)
        add_related_field_wrapper(self, 'offer')
        add_related_field_wrapper(self, 'package')

这在 Django 1.8.2 上运行良好。

【讨论】:

我要加class Meta\n\tmodel = ModeName\n\tfields = ('offer', 'package')【参考方案3】:

Google 在搜索如何在具有 ForeignKey 关系的自定义表单中的字段旁边获取“+”图标时将我指向此页面,所以我想我会添加。

对我来说,使用 django-autocomplete-light 做得很好,使用“添加另一个”功能。

【讨论】:

【参考方案4】:

您甚至不需要走那么远,此外,这些答案可能已经过时,因为它们中没有一个对我有用。

我为解决这个问题所做的是,只要您的模型中已经有 ForeignKey 字段,那么您就可以创建您的自定义 ModelChoiceField:

class LocationModelChoiceField(forms.ModelChoiceField):
    def label_from_instance(self, obj):
        return "%" % (obj.name)

接下来的关键是在您的 ModelForm 中为 ModelChoiceField 创建一个自定义字段(即 location = forms.ModelChoiceField(Location.objects.all())

换句话说,把它去掉,在你的 ModelForm 中有这样的东西:

class UserAdminForm(forms.ModelForm):

    class Meta:
        model = User
        fields = '__all__'

最后,在您的 ModelAdmin 中:

class UserAdmin(admin.ModelAdmin):
    model = User
    form = UserAdminForm

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == 'location':
        return LocationModelChoiceField(queryset=Location.objects.order_by('name')) # if you want to alphabetize your query
    return super().formfield_for_foreignkey(db_field, request, **kwargs)

【讨论】:

以上是关于Django ModelChoiceField 没有加号按钮的主要内容,如果未能解决你的问题,请参考以下文章

表单 ModelChoiceField 查询集 + 额外选择字段 django 表单

Django - ModelChoiceField 查询集如何工作?

Django ModelChoiceField 的问题

Django:让 ModelChoiceField 在运行时评估查询集

Django 表单不使用 ModelChoiceField 保存 - ForeignKey

带有modelchoicefield的Django多个表单->查询太多