En Django, ¿cómo podría uno usar la vista genérica update_object de Django para editar formas de modelos heredados?

StackOverflow https://stackoverflow.com/questions/213237

Pregunta

En Django, dados extractos de una aplicación animales likeso:

A animals / models.py con:

from django.db import models
from django.contrib.contenttypes.models import ContentType

class Animal(models.Model):
  content_type = models.ForeignKey(ContentType,editable=False,null=True)
  name = models.CharField()

class Dog(Animal):
  is_lucky = models.BooleanField()

class Cat(Animal):
  lives_left = models.IntegerField()

Y un animals / urls.py :

from django.conf.urls.default import *

from animals.models import Animal, Dog, Cat

dict = { 'model' : Animal }

urlpatterns = (
  url(r'^edit/(?P<object_id>\d+)

¿Cómo se pueden usar vistas genéricas para editar Dog y / o Cat utilizando el mismo formulario?

I.e. El objeto form que se pasa a animals / animal_form.html será Animal, y por lo tanto no contendrá ninguno de los detalles de las clases derivadas Dog y Cat. ¿Cómo puedo hacer que Django pase automáticamente un formulario para la clase secundaria a animal / animals_form.html ?

Por cierto, estoy usando Djangosnippets # 1031 para la administración de ContentType, por lo que Animal tener un método llamado as_leaf_class que devuelve la clase derivada.

Claramente, uno podría crear formularios para cada clase derivada, pero eso es bastante duplicación innecesaria (ya que todas las plantillas serán genéricas, esencialmente {{form.as_p}}).

Por cierto, es mejor asumir que Animal probablemente será una de varias clases base no relacionadas con el mismo problema, por lo que una solución ideal sería genérica.

Gracias de antemano por la ayuda.

, 'create_update.update_object', dict), )

¿Cómo se pueden usar vistas genéricas para editar Dog y / o Cat utilizando el mismo formulario?

I.e. El objeto form que se pasa a animals / animal_form.html será Animal, y por lo tanto no contendrá ninguno de los detalles de las clases derivadas Dog y Cat. ¿Cómo puedo hacer que Django pase automáticamente un formulario para la clase secundaria a animal / animals_form.html ?

Por cierto, estoy usando Djangosnippets # 1031 para la administración de ContentType, por lo que Animal tener un método llamado as_leaf_class que devuelve la clase derivada.

Claramente, uno podría crear formularios para cada clase derivada, pero eso es bastante duplicación innecesaria (ya que todas las plantillas serán genéricas, esencialmente {{form.as_p}}).

Por cierto, es mejor asumir que Animal probablemente será una de varias clases base no relacionadas con el mismo problema, por lo que una solución ideal sería genérica.

Gracias de antemano por la ayuda.

¿Fue útil?

Solución

Muy bien, esto es lo que he hecho, y parece funcionar y ser un diseño sensato (¡aunque tengo que corregirlo!).

En una biblioteca principal (por ejemplo, mysite.core.views.create_update), he escrito un decorador:

from django.contrib.contenttypes.models import ContentType
from django.views.generic import create_update

def update_object_as_child(parent_model_class):
   """
   Given a base models.Model class, decorate a function to return  
   create_update.update_object, on the child class.

   e.g.
   @update_object(Animal)
   def update_object(request, object_id):
      pass

  kwargs should have an object_id defined.
  """

  def decorator(function):
      def wrapper(request, **kwargs):
          # may raise KeyError
          id = kwargs['object_id']

          parent_obj = parent_model_class.objects.get( pk=id )

          # following http://www.djangosnippets.org/snippets/1031/
          child_class = parent_obj.content_type.model_class()

          kwargs['model'] = child_class

          # rely on the generic code for testing/validation/404
          return create_update.update_object(request, **kwargs)
      return wrapper

  return decorator

Y en animals / views.py, tengo:

from mysite.core.views.create_update import update_object_as_child

@update_object_as_child(Animal)
def edit_animal(request, object_id):
  pass

Y en animals / urls.py, tengo:

urlpatterns += patterns('animals.views',
  url(r'^edit/(?P<object_id>\d+)

Ahora solo necesito una función de edición única para cada clase base, lo cual es trivial de crear con un decorador.

Espero que alguien lo encuentre útil, y me encantaría tener comentarios.

, 'edit_animal', name="edit_animal"), )

Ahora solo necesito una función de edición única para cada clase base, lo cual es trivial de crear con un decorador.

Espero que alguien lo encuentre útil, y me encantaría tener comentarios.

Otros consejos

AFAICT, los gatos y los perros están en diferentes tablas de bases de datos, y tal vez no haya una tabla de animales. pero estás usando un patrón de URL para todos. En algún lugar debes elegir entre cada uno.

Usaré un patrón diferente de URL para gatos y perros, ambos llamarían 'create_update.update_object' ; pero usando un dict diferente para cada uno. uno con 'model': Dog y el otro con 'model':Cat

¿

o tal vez quieres una sola mesa donde cada registro puede ser un gato o un perro? No creo que puedas usar modelos heredados para eso.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top