widgets is_valid formularios form fields example avanzados django django-models django-admin

is_valid - formularios django



Administrador de Django anidado en lĂ­nea (6)

Necesito un administrador de django anidado en línea, que puedo incluir en línea el campo de fecha en otro en línea como a continuación.

Tengo los modelos a continuación:

class Person(models.Model): name = models.CharField(max_length=200) id_no = models.IntegerField() class Certificate(models.Model): cerfificate_no = models.CharField(max_length=200) certificate_date = models.DateField(max_length=100) person = models.ForeignKey(Person) training = models.CharField(max_length=200) class Training_Date(models.Model): date = models.DateField() certificate = models.ForeignKey(Certificate)

y el administrador a continuación:

class CertificateInline(admin.StackedInline): model = Certificate class PersonAdmin(admin.ModelAdmin): inlines = [CertificateInline,] admin.site.register(Person,PersonAdmin)

pero necesito incluir el modelo Training_Date como en línea, que es parte de la administración de certificados en línea.

Alguna idea ?


AFAIK, no puedes tener un segundo nivel de líneas en el administrador predeterminado de Django.

El administrador de Django es solo una aplicación Django normal, por lo que nada le impide implementar un segundo nivel de formularios anidados, pero en mi humilde opinión sería un tipo de diseño complejo de implementar. Tal vez es por eso que no hay ninguna disposición para ello.


Ha habido algún movimiento en https://code.djangoproject.com/ticket/9025 recientemente, pero no contuve la respiración.

Una forma común de evitar esto es vincular a un administrador entre el primer y segundo nivel (o el segundo y el tercero) al tener tanto un ModelAdmin como un Inline para el mismo modelo:

Dé Certificado a ModelAdmin con TrainingDate como en línea. Dé a CertificateInline un campo adicional "Detalles" que es un enlace a su formulario de modificación ModelAdmin.

models.py:

from django.core import urlresolvers class Certificate(models.Model): # ... def changeform_link(self): if self.id: # Replace "myapp" with the name of the app containing # your Certificate model: changeform_url = urlresolvers.reverse( ''admin:myapp_certificate_change'', args=(self.id,) ) return u''<a href="%s" target="_blank">Details</a>'' % changeform_url return u'''' changeform_link.allow_tags = True changeform_link.short_description = '''' # omit column header

admin.py:

# Certificate change form has training dates as inline class TrainingDateInline(admin.StackedInline): model = TrainingDate class CertificateAdmin(admin.ModelAdmin): inlines = [TrainingDateInline,] admin.site.register(Certificate ,CertificateAdmin) # Person has Certificates inline but rather # than nesting inlines (not possible), shows a link to # its own ModelAdmin''s change form, for accessing TrainingDates: class CertificateLinkInline(admin.TabularInline): model = Certificate # Whichever fields you want: (I usually use only a couple # needed to identify the entry) fields = (''cerfificate_no'', ''certificate_date'', ''changeform_link'') readonly_fields = (''changeform_link'', ) class PersonAdmin(admin.ModelAdmin): inlines = [CertificateLinkInline,] admin.site.register(Person, PersonAdmin)



Una solución más universal

from django.utils.safestring import mark_safe from django.core.urlresolvers import reverse class EditLinkToInlineObject(object): def edit_link(self, instance): url = reverse(''admin:%s_%s_change'' % ( instance._meta.app_label, instance._meta.model_name), args=[instance.pk] ) if instance.pk: return mark_safe(u''<a href="{u}">edit</a>''.format(u=url)) else: return '''' class MyModelInline(EditLinkToInlineObject, admin.TabularInline): model = MyModel readonly_fields = (''edit_link'', ) class MySecondModelAdmin(admin.ModelAdmin): inlines = (MyModelInline, ) admin.site.register(MyModel) admin.site.register(MySecondModel, MySecondModelAdmin)


Usé la solución proporcionada por @bigzbig (gracias).

También quería volver a la primera página de la lista una vez que se habían guardado los cambios, así que agregué:

class MyModelInline(EditLinkToInlineObject, admin.TabularInline): model = MyModel readonly_fields = (''edit_link'', ) def response_post_save_change(self, request, obj): my_second_model_id = MyModel.objects.get(pk=obj.pk).my_second_model_id return redirect("/admin/mysite/mysecondmodel/%s/change/" % (my_second_model_id))


pip install django-nested-inline

Este paquete debe hacer lo que necesita.