Tengo un modelo, Director
con dos DateFields y dos subclases (código a continuación). Estoy intentando crear una página de administrador para cada Director que muestra la instancia de subclase correspondiente, y no la instancia Director
; esta parte es en su mayoría fácil (creo un en línea para cada subclase, le doy a ModelAdmin principal un formulario con todos los campos excluidos, y el ModelAdmin principal solo solicita conjuntos a partir de las líneas que tienen una instancia correspondiente - el código; hay un problema sin resolver con este enfoque, que menciono a continuación, pero no es el foco de esta pregunta).administrador de Django: ¿cómo formatear campos de solo lectura?
El problema que tengo es que quiero dar masajes a los valores mostrados al usuario, uno de los cuales se muestra en un campo de solo lectura, uno de los cuales no lo es. El procesamiento es que quiero cambiar un valor mágico (date(1,1,1)
) a la cadena "On incorporation"
.
Las fechas en los campos de solo lectura no se muestran en un formato muy amigable para el análisis, y me gustaría reducir la dependencia innecesaria de javascript, por lo que preferiría una solución del lado del servidor.
El código siguiente muestra los formularios como los quiero, excepto que los valores de fecha no se masajean en absoluto, y cuando se guardan, aparece un mensaje falso "Corrija el error a continuación", aunque no haya errores, y todos los campos se guardan correctamente
Mi pregunta es: ¿cómo puedo interceptar los valores que se mostrarán en la página, tanto en campos de solo lectura como en campos de formularios, y modificarlos para mostrar una cadena de mi elección?
Los modelos (hasta ahora como materiales):
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
La clave de administrador:
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))
Soy consciente de que hay una asimetría entre DirectorsCorporateInline
y DirectorsIndividualInline
; eso es porque estoy probando en una instancia con una instancia DirectorsIndividual
. El código anterior se refiere a los campos modelo que no se muestran en los modelos, porque no son importantes para el problema de las fechas; debería ser posible volverlos inmateriales para el problema del error espurio sin alterar esos campos (aunque me doy cuenta de que es menos útil para ese tema, quiero que esta cuestión se centre principalmente en un tema). EnhancedAdmin
es una subclase ModelAdmin
con algunas modificaciones menores que no deberían ser una consecuencia. Se puede mostrar un código adicional por solicitud razonada, pero no quiero confundirlo con un código irrelevante.
Para completar: Estoy usando django 1.3.1 en python 2.7.2.
En realidad, no se representan de forma consistente, lo que hará que el javascript sea un dolor; Probablemente tendré que hacerlo, así que gracias por la información. – Marcin