Django ModelChoiceField没有加号按钮

igetnqfo  于 2022-12-14  发布在  Go
关注(0)|答案(5)|浏览(134)

我正在制作一个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教程中创建选项时添加投票一样。根据to this question,如果我没有权限更改模型,我可能看不到绿色加号。但我是以超级用户的身份登录的,有所有权限。知道我做错了什么吗?

6ljaweal

6ljaweal1#

You need to set a RelatedFieldWidgetWrapper wrapper in your model form:
The RelatedFieldWidgetWrapper (found in django.contrib.admin.widgets) is used in the Admin pages to include the capability on a Foreign Key control to add a new related record. (In English: puts the little green plus sign to the right of the control.)

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)

I could make a mistake in the example code, so see these posts and examples:

pnwntuvh

pnwntuvh2#

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

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上运行良好。

5hcedyr0

5hcedyr03#

Google在搜索如何在具有外键关系的自定义表单中的字段旁边获得“+”图标时向我指出了这个页面,所以我想我应该添加。
对我来说,使用django-autocomplete-light很好地完成了这个任务,使用了“添加另一个”功能。

w9apscun

w9apscun4#

你甚至不需要走那么远,此外,这些答案可能是过时的,因为他们没有为我工作的任何能力。
我解决这个问题的方法是,只要您的模型中已经有了ForeignKey字段,那么您就可以创建自定义ModelChoiceField:

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

接下来的关键是NOT为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)
z31licg0

z31licg05#

替代方法:使用**.remote_field**代替rel

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

def __init__(self, *args, **kwargs):
    super(CustomerAdminForm, self).__init__(*args, **kwargs)
    self.add_related_field_wrapper(self, 'offer')
    self.add_related_field_wrapper(self, 'package')

谢谢你,

相关问题