django admin-添加不属于模型的自定义表单字段


106

我在管理站点中注册了一个模型。它的字段之一是长字符串表达式。我想将自定义表单字段添加到管理中此模型的添加/更新页面,基于这些字段值,我将构建长字符串表达式并将其保存在相关的模型字段中。

我怎样才能做到这一点?

更新:基本上我正在做的是从符号中构建数学表达式或字符串表达式,用户选择符号(这些是自定义字段,不属于模型的一部分),然后单击“保存”,然后从符号列表并将其存储在数据库中。我不希望符号是模型和数据库的一部分,而只是最终表达式。

Answers:


156

您可以在admin.py或单独的forms.py中添加一个ModelForm类,然后像往常一样在其中声明额外的字段。我还给出了一个示例,说明如何在form.save()中使用这些值:

from django import forms
from yourapp.models import YourModel


class YourModelForm(forms.ModelForm):

    extra_field = forms.CharField()

    def save(self, commit=True):
        extra_field = self.cleaned_data.get('extra_field', None)
        # ...do something with extra_field here...
        return super(YourModelForm, self).save(commit=commit)

    class Meta:
        model = YourModel

要使其他字段仅出现在管理员中:

  1. 编辑您的admin.py并设置form属性以引用您在上面创建的表单
  2. 将新字段包括在字段或字段集声明中

像这样:

class YourModelAdmin(admin.ModelAdmin):

    form = YourModelForm

    fieldsets = (
        (None, {
            'fields': ('name', 'description', 'extra_field',),
        }),
    )

更新:在django 1.8中,您需要添加fields = '__all__'到YourModelForm的元类。


2
是的,我真的很想知道原因
Vishnu 2014年

13
您应该添加fields = '__all__'您的Meta课程,否则django会抱怨:Creating a ModelForm without either the 'fields' attribute or the 'exclude' attribute is deprecated
IsaacKleiner

1
@sthzg,因为它不正确。它给了我错误:YourModelAdmin.list_display[0], 'extra_field' is not a callable or an attribute of 'YourModelAdmin' or found in the model 'YourModel'.
Cerin

7
如果由于某种原因得到AttributeError: Unable to lookup "extra_field"...,请尝试labelextra_field定义中添加。看来django会通过查看ModelModelAdmin定义此类属性定义来尝试“猜测”标签。
alxs 17-4-12

1
如果extra_field是CharField(),这可以很好地工作。但是,如果它是hiddenField(在Django 1.11中),则会生成错误Unknown field(s) (extra_field) specified for YourModel. Check fields/fieldsets/exclude attributes of class YourModelAdmin.。解决方法是extra_field = forms.CharField(widget=forms.HiddenInput())
kakoma

35

可以在管理中执行操作,但是没有非常简单的方法。另外,我也建议您在模型中保留大多数业务逻辑,这样您就不必依赖Django Admin。

如果模型上有两个单独的字段,可能会更容易(甚至更好)。然后在模型上添加一个将它们组合在一起的方法。

例如:

class MyModel(models.model):

    field1 = models.CharField(max_length=10)
    field2 = models.CharField(max_length=10)

    def combined_fields(self):
        return '{} {}'.format(self.field1, self.field2)

然后,您可以在admin中将combined_fields()as 添加为只读字段:

class MyModelAdmin(models.ModelAdmin):

    list_display = ('field1', 'field2', 'combined_fields')
    readonly_fields = ('combined_fields',)

    def combined_fields(self, obj):
        return obj.combined_fields()

如果要将s存储combined_fields在数据库中,也可以在保存模型时将其保存:

def save(self, *args, **kwargs):
    self.field3 = self.combined_fields()
    super(MyModel, self).save(*args, **kwargs)

4
感谢您的回答,但这不是我想要的。我不希望将自定义字段保存在数据库中,只保存计算出的字符串。基本上,我正在做的是从符号中构建数学表达式或字符串表达式,用户选择符号(这些是自定义字段,不属于模型),然后单击“保存”,然后从列表中创建字符串表达式表示形式。符号并将其存储在数据库中。
michalv82

@ michalv82您也可以使用模型的save()方法将其保存到数据库,检查我的答案的更新。
gitaarik 2013年

1
再次感谢,但是问题是我不想存储结合了最后一个字段(即符号)的字段,我只想保存最后一个字符串
michalv82

保存2个字段是否有问题?如果您想知道组合字段是如何生成的,也许可以派上用场。
gitaarik

6
再次感谢,但不是2个领域,可能还会更多。同样,我不想将它们存储在数据库中,因此该解决方案对我而言不起作用。
michalv82 2013年

5

Django 2.1.1主要答案使我无法回答问题。它并没有帮助我将结果保存到实际模型中的字段中。在我的情况下,我希望用户可以在其中输入数据的文本字段,然后在进行保存时处理数据,并将结果放入模型的字段中并保存。虽然原始答案显示了如何从额外字段中获取值,但至少在Django 2.1.1中并未显示如何将其保存回模型中。

这将从一个未绑定的自定义字段中获取值,进行处理,并将其保存到我的真实描述字段中:

class WidgetForm(forms.ModelForm):
    extra_field = forms.CharField(required=False)

    def processData(self, input):
        # example of error handling
        if False:
            raise forms.ValidationError('Processing failed!')

        return input + " has been processed"

    def save(self, commit=True):
        extra_field = self.cleaned_data.get('extra_field', None)

        # self.description = "my result" note that this does not work

        # Get the form instance so I can write to its fields
        instance = super(WidgetForm, self).save(commit=commit)

        # this writes the processed data to the description field
        instance.description = self.processData(extra_field)

        if commit:
            instance.save()

        return instance

    class Meta:
        model = Widget
        fields = "__all__"

4

您可以随时创建新的管理模板,并在admin_view中执行所需的操作(将admin添加网址覆盖到admin_view中):

 url(r'^admin/mymodel/mymodel/add/$' , 'admin_views.add_my_special_model')

3

如果您绝对只想将组合字段存储在模型上而不是两个单独的字段,则可以执行以下操作:

我从来没有做过这样的事情,所以我不太确定它会如何工作。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.