У меня есть модель, Director
с двумя полями DateFields и двумя подклассами (код ниже). Я пытаюсь создать страницу администратора для каждого директора, которая показывает соответствующий экземпляр подкласса, а не экземпляр Director
; эта часть в основном проста (я создаю встроенный файл для каждого подкласса, даю основному ModelAdmin форму со всеми исключенными полями, а основной ModelAdmin запрашивает только наборы форм из встроенных, имеющих соответствующий экземпляр - код; существует нерешенная проблема с этим подходом, который я отмечаю ниже, но не в центре внимания этого вопроса).
Проблема, с которой я столкнулся, заключается в том, что я хочу помассировать значения, отображаемые пользователю, одно из которых отображается в поле только для чтения, а другое - нет. Обработка заключается в том, что я хочу изменить магическое значение (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
и DirectorsIndividualInline
; это потому, что я тестирую экземпляр с DirectorsIndividual
экземпляром. Приведенный выше код относится к полям модели, не показанным в моделях, поскольку они не являются существенными для выпуска дат; должно быть возможно сделать их несущественными для ложной ошибки, не изменяя эти поля (хотя я понимаю, что это менее полезно для этой проблемы, я хочу, чтобы этот вопрос был сосредоточен в основном на одной проблеме). EnhancedAdmin
- это подкласс ModelAdmin
с некоторыми незначительными изменениями, которые не должны иметь последствий. Дополнительный код может быть показан по обоснованному запросу, но я не хочу путать с нерелевантным кодом.
Для полноты: я использую django 1.3.1 на python 2.7.2.