128

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

我怎样才能做到这一点?

我正在从符号构建数学或字符串表达式。用户选择符号(这些是不属于模型的自定义字段),当他们单击保存时,我从符号列表中创建一个字符串表达式表示并将其存储在数据库中。我不希望符号成为模型和数据库的一部分,只是最终表达式。

4

6 回答 6

174

无论是在你的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并设置表单属性以引用您在上面创建的表单。
  2. 在您的字段或字段集声明中包含您的新字段。

像这样:

class YourModelAdmin(admin.ModelAdmin):

    form = YourModelForm

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

更新:

在 Django 1.8 中,您需要添加fields = '__all__'YourModelForm.

于 2014-04-28T09:12:38.047 回答
46

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

然后在管理员中,您可以将其添加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()

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

def save(self, *args, **kwargs):
    self.field3 = self.combined_fields()
    super(MyModel, self).save(*args, **kwargs)
于 2013-07-30T13:35:46.970 回答
10

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__"
于 2018-09-21T18:41:00.457 回答
4

您始终可以创建新的管理模板,并在您的admin_view(覆盖管理员添加 URL 到您的admin_view)中执行您需要的操作:

url(r'^admin/mymodel/mymodel/add/$','admin_views.add_my_special_model')
于 2014-08-21T08:38:23.277 回答
3

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

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

于 2013-07-30T14:26:58.897 回答
0

您可能会从我的回答中获得帮助: 我之前在 multicheckchoice 自定义字段上的回复

您还可以扩展具有不同自定义字段的多个表单,然后将它们分配给您的内联类,如stackedinline 或tabularinline:

表格 =

通过这种方式,您可以避免需要从多个模型添加多个自定义字段的表单集复杂性。

所以你的模型管理员看起来像:

内联 = [form1inline,form2inline,...]

在我之前对此处链接的回复中,您将找到 init 和 save 方法。

init 将在您查看页面时加载并保存将其发送到数据库。

在这两种方法中,您可以执行逻辑来添加字符串,然后保存,然后在 Django admin change_form 或 change_list 中查看它,具体取决于您想要的位置。list_display 将在 change_list 上显示您的字段。让我知道它是否有帮助......

class CohortDetailInline3(admin.StackedInline):
    model = CohortDetails
    form =  DisabilityTypesForm
...

class CohortDetailInline2(admin.StackedInline):
    model = CohortDetails
    form =  StudentRPLForm

……

@admin.register(Cohort)
class CohortAdmin(admin.ModelAdmin):         
        form = CityInlineForm
        inlines = [uploadInline,   cohortDetailInline1,
        CohortDetailInline2, CohortDetailInline3]
    
        list_select_related = True
    
        list_display = ['rto_student_code', 'first_name', 'family_name',]

...

于 2021-10-29T05:51:01.293 回答