我有一个模型,Director
有两个 DateFields 和两个子类(代码如下)。我正在尝试为每个主管创建一个管理页面,其中显示相应的子类实例,而不是Director
实例;这部分很简单(我为每个子类创建一个内联,给主 ModelAdmin 一个排除所有字段的表单,并且让主 ModelAdmin 仅从具有相应实例的内联请求表单集 - 代码;有一个未解决的问题使用这种方法,我在下面指出,但不是这个问题的重点)。
我遇到的问题是我想修改向用户显示的值,其中之一显示在只读字段中,其中之一则没有。处理是我想改变一个magic值(date(1,1,1)
) 到字符串"On incorporation"
.
只读字段中的日期不会以非常易于解析的格式呈现,并且我希望减少对 javascript 的不必要依赖,因此我非常喜欢服务器端解决方案。
下面的代码显示了我想要的表单,除了日期值根本没有被修改,并且在保存时,有一个虚假的“请更正下面的错误”消息,即使没有错误,并且所有字段都被保存正确。
我的问题是:如何拦截要在页面上呈现的值(在只读字段和表单字段中),并更改它们以显示我选择的字符串?
模型(就材料而言):
class Director(models.Model, Specializable):
date_of_appointment = models.DateField()
date_ceased_to_act = models.DateField(blank=True,null=True)
class DirectorsIndividual(Director):
pass
class DirectorsCorporate(Director):
pass
管理代码:
class DirectorAdmin(EnhancedAdmin):
fields = ()
## def formfield_for_dbfield(self, db_field, **kwargs):
## return None
def queryset(self, request):
""" Directors for all companies which are incorporated by the current user's organisation """
individual = Individual.for_user(request.user)
return Director.objects.filter(company__incorporation_ticket__ordered_by__in = Organisation.all_organisations_for_which_individual_authorised_to_incorporate(individual))
class form(forms.ModelForm):
# have this return no html - that way only inlines are shown
class Meta:
fields = ()
pass
def is_valid(self):
self._errors = {}
return True
class DirectorsIndividualInline(admin.StackedInline):
model = DirectorsIndividual
fk_name = 'director_ptr'
extra = 0
readonly_fields = ('deferred_on','company','date_of_appointment',)
can_delete = False
def get_readonly_fields(self, request, obj=None):
if obj and obj.company and not obj.company.is_submitted(): return self.readonly_fields # allow editing of fields listed in else
else:
return itertools.chain(self.readonly_fields, ('individual', 'is_secretary'))
def has_delete_permission(self, request, obj=None):
return obj and ((obj.company and not obj.company.is_submitted()) or not obj.company)
class form(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(forms.ModelForm, self).__init__(*args, **kwargs)
self.fields['surrogate_for'].required = False
self.fields['representative_for'].required = False
if self.instance:
obj = self.instance
for field in (f for f in type(obj)._meta.fields if type(f) == fields.DateField):
val = field.value_from_object(obj)
assert (type(val) in (datetime.date, type(None),))
# assert field.name != 'date_of_appointment'
if val == inc_consts.EARLIEST_DATE:
self.initial[field.name] = "On incorporation"
def is_valid(self):
self._errors = {}
return True
class DirectorsCorporateInline(admin.StackedInline):
model = DirectorsCorporate
fk_name = 'director_ptr'
extra = 0
can_delete = False
class form(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(forms.ModelForm, self).__init__(*args, **kwargs)
if True:
for k in self.fields:
self.fields[k].required = False
def is_valid(self):
self._errors = {}
return True
inlines = (DirectorsIndividualInline,DirectorsCorporateInline)
def get_inlines(self, request, obj=None):
return (inline for inline in (self.inline_instances)
if inline.model.objects.filter(**{(inline.fk_name or self.model._meta.object_name.lower()) : obj }))
def get_formsets(self, request, obj=None):
""" only return formset for inlines for which there exists an object """
return (inline.get_formset(request, obj) for inline in self.get_inlines(request, obj))
我意识到两者之间存在不对称性DirectorsCorporateInline
and DirectorsIndividualInline
;那是因为我正在使用一个实例进行测试DirectorsIndividual
实例。上面的代码引用了模型中未显示的模型字段,因为它们对日期问题并不重要;应该可以在不改变这些字段的情况下使它们对于虚假错误问题变得无关紧要(尽管我意识到这对这个问题没有多大帮助,但我想让这个问题主要集中在一个问题上)。EnhancedAdmin
is a ModelAdmin
子类进行了一些小改动,这些改动不应该产生任何后果。可以根据合理的请求显示额外的代码,但我不想与不相关的代码混淆。
为了完整起见:我在 python 2.7.2 上使用 django 1.3.1。