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

mic*_*v82 90 django admin

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

我怎样才能做到这一点?

更新:基本上我正在做的是从符号构建数学或字符串表达式,用户选择符号(这些是不属于模型的自定义字段),当他点击保存时,我创建一个字符串表达式表示符号列表并将其存储在DB中.我不希望符号是模型和DB的一部分,只是最终表达式.

Vis*_*hnu 146

在您的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
Run Code Online (Sandbox Code Playgroud)

要在管理员中显示额外的字段,请执行以下操作:

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

像这样:

class YourModelAdmin(admin.ModelAdmin):

    form = YourModelForm

    fieldsets = (
        (None, {
            'fields': ('name', 'description', 'extra_field',),
        }),
    )
Run Code Online (Sandbox Code Playgroud)

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

  • 你应该在你的`Meta`类中添加`fields ='__ all __'`,否则django抱怨:`不建议使用'fields'属性或'exclude'属性的ModelForm. (11认同)
  • 如果由于某种原因,你得到一个`AttributeError:无法查找"extra_field"...`,尝试在`extra_field`定义中添加`label`.似乎django试图通过查看"Model"和"ModelAdmin"来为这样的属性定义"猜测"它的标签. (7认同)
  • 有没有理由不接受这个答案? (4认同)
  • 是的,我真的想知道原因 (2认同)
  • @sthzg,因为它不正确。它给了我错误:`YourModelAdmin.list_display[0],'extra_field'不是'YourModelAdmin'的可调用或属性,也不是在模型'YourModel'中找到的。` (2认同)

git*_*rik 31

它可以在管理员中完成,但没有一种非常简单的方法.另外,我想建议将大多数业务逻辑保留在模型中,这样您就不会依赖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)
Run Code Online (Sandbox Code Playgroud)

然后在管理员中,您可以将其添加combined_fields()为只读字段:

class MyModelAdmin(models.ModelAdmin):

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

    def combined_fields(self, obj):
        return obj.combined_fields()
Run Code Online (Sandbox Code Playgroud)

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

def save(self, *args, **kwargs):
    self.field3 = self.combined_fields()
    super(MyModel, self).save(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)

  • 再次感谢,但它不是2个领域,它可能会更多.同样,我不想将它们存储在DB中,因此这个解决方案对我来说不起作用. (6认同)
  • 谢谢你的回答,但这不是我想要的.我不希望自定义字段保存在DB中,只保存计算的字符串.基本上我正在做的是从符号构建数学或字符串表达式,用户选择符号(这些是不属于模型的自定义字段),当他点击保存时,我从列表中创建一个字符串表达式表示符号并将其存储在DB中. (3认同)

Man*_*ssi 9

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__"
Run Code Online (Sandbox Code Playgroud)