Estoy tratando de crear un sistema para administrar los diversos tipos de contenido en una página. Por ejemplo, una página puede tener contenido de texto, contenido de hipervínculos, contenido de video, etc.Herencia de modelo de Django y sistema de administración
En mi código de modelos, que tienen una clase base:
class ContentItem(models.Model):
title = models.CharField(max_length=1000)
page_order = models.IntegerField()
last_update_date = models.DateTimeField(default=datetime.now())
class Meta:
abstract = True
ordering = ['page_order', 'last_update_date', 'title']
Ésta es la clase base para todos los elementos de contenido. El orden de las páginas controla la posición en la página, por ejemplo, el elemento con page_order = 0 debe estar en la parte superior de la página. A continuación, defino algunos modelos de contenido específicos que heredan de este.
class LinkContent(ContentItem):
url = models.URLField()
link_text = models.CharField(max_lenth=1000)
class TextContent(ContentItem):
text = models.CharField()
class VideoContent(ContentItem):
title = models.CharField()
video_file = models.FieldField(upload_to = 'videos')
Podría haber muchos más tipos de contenido de este tipo. Luego definiría un modelo de Página que está compuesto por todos los diversos tipos de contenido. Idealmente, podría poner todos los tipos en una relación basada en el tipo de base. Entonces, en esta relación tendrías una mezcla de LinkContents, TextContents y VideoContents. Se ordenan por page_order para determinar su orden en la página al procesar la plantilla.
class Page(models.Model):
contents = models.ManyToManyField(ContentItem)
title = models.CharField()
¿Hay alguna manera de hacer que un esquema así funcione? ¿O es problemático tener una relación con diferentes tipos de modelos? Sé que esta es una buena solución desde el punto de vista de programación orientada a objetos, básicamente usando polimorfismo para mi beneficio, pero no estoy seguro de que tenga sentido a nivel de base de datos.
hacer yo en vez necesito algo más parecido a esto:
class Page(models.Model):
video_contents = models.ManyToManyField(VideoContent)
link_contents = models.ManyToManyField(LinkContent)
text_contents = models.ManyToManyField(TextContent)
title = models.CharField()
Sé que esto funcionaría, pero mi esquema de determinación de la colocación de los objetos de la página se vuelve más difícil. Necesitaría recorrer todas las relaciones de contenido, ordenarlas por page_order y luego renderizarlas.
Creo que en ambos casos, quiero declarar un método render() en la clase base que cada tipo de contenido específico puede heredar. De esta forma, si tengo una lista de ContentItems, puedo usar la tipificación de pato para representarlos sin preocuparme por su tipo específico.
Mi última pregunta es ¿cómo hago que el lugar de administración sea agradable con esto? ¿Cómo podría hacer una manera fácil de ver todos los elementos de contenido que componen una página en una vista, para que puedan moverse fácilmente cambiando page_order?
Gracias por leer esto, avíseme si necesita más información.
Gracias @jcdyer. Esa fue una información muy útil. Una cosa de la que aún no estoy claro es cómo haría que esto funcione en la interfaz de administración. Idealmente, me gustaría obtener una lista de los contenidos de la página y mostrar el formulario de administración correspondiente para cada elemento en función de la clase específica. Por ejemplo, si una Página tiene 2 LinkContents y 1 TextContent en su atributo de contenido, quiero que los dos primeros sean editables con el formulario de Enlace y el otro con el formulario de texto. ¿Hay una manera simple de hacer algo como esto? He hecho mucha personalización de administrador, pero nunca he visto algo así. – Jon