In Django, come si può usare la vista generica update_object di Django per modificare forme di modelli ereditati?

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

Domanda

In Django, dati estratti da un'applicazione animali likeo:

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()

E un animali / 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+)

Come si possono usare le viste generiche per modificare Dog e / o Cat usando lo stesso modulo?

vale a dire. L'oggetto form che viene passato a animals / animal_form.html sarà Animal, e quindi non conterrà alcuno dei dettagli per le classi derivate Dog and Cat. Come potrei avere Django passare automaticamente un modulo per la classe del bambino a animal / animals_form.html ?

Per inciso, sto usando Djangosnippets # 1031 per la gestione di ContentType, quindi Animal avrebbe ha un metodo chiamato as_leaf_class che restituisce la classe derivata.

Chiaramente, si potrebbero creare moduli per ogni classe derivata, ma si tratta di un sacco di duplicazioni non necessarie (poiché i modelli saranno tutti generici, essenzialmente {{form.as_p}}).

Per inciso, è meglio supporre che Animal sarà probabilmente una delle diverse classi base non correlate con lo stesso problema, quindi una soluzione ideale sarebbe generica.

Grazie in anticipo per l'aiuto.

, 'create_update.update_object', dict), )

Come si possono usare le viste generiche per modificare Dog e / o Cat usando lo stesso modulo?

vale a dire. L'oggetto form che viene passato a animals / animal_form.html sarà Animal, e quindi non conterrà alcuno dei dettagli per le classi derivate Dog and Cat. Come potrei avere Django passare automaticamente un modulo per la classe del bambino a animal / animals_form.html ?

Per inciso, sto usando Djangosnippets # 1031 per la gestione di ContentType, quindi Animal avrebbe ha un metodo chiamato as_leaf_class che restituisce la classe derivata.

Chiaramente, si potrebbero creare moduli per ogni classe derivata, ma si tratta di un sacco di duplicazioni non necessarie (poiché i modelli saranno tutti generici, essenzialmente {{form.as_p}}).

Per inciso, è meglio supporre che Animal sarà probabilmente una delle diverse classi base non correlate con lo stesso problema, quindi una soluzione ideale sarebbe generica.

Grazie in anticipo per l'aiuto.

È stato utile?

Soluzione

Va ??bene, ecco quello che ho fatto, e sembra funzionare ed essere un design ragionevole (anche se sto per essere corretto!).

In una libreria principale (ad esempio mysite.core.views.create_update), ho scritto un decoratore:

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

E in animals / views.py, ho:

from mysite.core.views.create_update import update_object_as_child

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

E in animals / urls.py, ho:

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

Ora ho solo bisogno di una funzione di modifica unica per ogni classe base, che è banale da creare con un decoratore.

Spero che qualcuno lo trovi utile e sarei felice di avere un feedback.

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

Ora ho solo bisogno di una funzione di modifica unica per ogni classe base, che è banale da creare con un decoratore.

Spero che qualcuno lo trovi utile e sarei felice di avere un feedback.

Altri suggerimenti

AFAICT, cani e gatti si trovano su diverse tabelle DB e forse non esiste una tabella animali. ma stai usando un pattern URL per tutti. da qualche parte devi scegliere tra ciascuna.

Userei un diverso scalpello URL per cani e gatti, entrambi chiamerei 'create_update.update_object' ; ma utilizzando un dict diverso per ciascuno. uno con 'modello': Dog e l'altro con 'model':Cat

o forse vuoi una singola tabella in cui ogni record può essere un gatto o un cane? non penso che tu possa usare modelli ereditati per questo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top