3

假设以下模型

# models.py
class Person(models.Model):
    name = models.CharField(max_length=40)
    birthdate = models.DateField()
    age = models.CharField(max_length=3) # dont mind the type, this is just an example :)

期望的行为是age在用户创建新Person对象时隐藏该字段,并在用户提交表单时评估其值。此外,age当在 admin 中查看对象实例时,该字段应该是可见的。

为了实现这一点,我创建了ModelAdmin一个自定义ModelForm如下

# admin.py
from django.contrib import admin
from django import forms
from .models import Person
from dateutil.relativedelta import relativedelta
import datetime

class PersonForm(forms.ModelForm):
    def clean(self):
        cleaned_data = super(PersonForm, self).clean()
        birthdate = cleaned_data.get('birthdate')
        cleaned_data['age'] = relativedelta(datetime.date.today(), birthdate).years
        return cleaned_data

class PersonAdmin(admin.ModelAdmin):
    form = PersonForm
    exclude = ('age',)

admin.site.register(Person, PersonAdmin)

但是,提交表单后,该age字段不会被填充,可能是因为它被排除在外。如果我删除exclude它,那么它可以工作,但表单会显示age不是所需行为的字段。

4

2 回答 2

2

ModelAdmin您可以使用'ssave_model方法代替自定义表单:

 class PersonAdmin(admin.ModelAdmin):

    def save_model(self, request, obj, form, change):
        birthdate = form.cleaned_data.get('birthdate')
        age = relativedelta(datetime.date.today(), birthdate).years 
        obj.age = age
        super().save_model(request, obj, form, change)

    def get_exclude(self, request, obj=None):
        if not obj:
            return ('age',)
        return self.exclude  

您也可以使用readonly_fields

 class PersonAdmin(admin.ModelAdmin):
    readonly_fields = ('age',)

    def save_model(self, request, obj, form, change):
        birthdate = form.cleaned_data.get('birthdate')
        age = relativedelta(datetime.date.today(), birthdate).years 
        obj.age = age
        super().save_model(request, obj, form, change)
于 2018-05-31T09:04:41.513 回答
1

或者您可以隐藏表单中的输入。

# admin.py
from django.contrib import admin
from django import forms
from .models import Person
from dateutil.relativedelta import relativedelta
import datetime

class PersonForm(forms.ModelForm):
    age = forms.CharField(widget=forms.HiddenInput, required=False)
    def clean(self):
        cleaned_data = super(PersonForm, self).clean()
        birthdate = cleaned_data.get('birthdate')
        cleaned_data['age'] = relativedelta(datetime.date.today(), birthdate).years
        return cleaned_data

只有当对象为无时(创建案例),您才能使用该表单。

class PersonAdmin(admin.ModelAdmin):
    def get_form(self, request, obj=None, **kwargs):
        if not obj:
            kwargs['form'] = PersonForm
        return super().get_form(request, obj, **kwargs)

admin.site.register(Person, PersonAdmin)
于 2018-05-31T09:14:25.590 回答