在Django中,如何使用Django的update_object通用视图来编辑继承模型的形式?

时间:2008-10-17 18:16:08

标签: python django forms inheritance decorator

在Django中,给出了应用 animals 喜欢的摘录:

animals / models.py with:

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

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+)$', 'create_update.update_object', dict),
)

如何使用通用视图使用相同的表单编辑Dog和/或Cat?

即。传递给 animals / animal_form.html 表单对象将是Animal,因此不会包含派生类Dog和Cat的任何细节。我怎么能让Django自动将子类的表单传递给 animal / animals_form.html

顺便说一句,我正在使用Djangosnippets #1031进行ContentType管理,因此Animal会有一个名为 as_leaf_class 的方法来返回派生类。

显然,可以为每个派生类创建表单,但这是非常多的不必要的重复(因为模板都是通用的 - 基本上是{{form.as_p}})。

顺便说一句,最好假设Animal可能是具有相同问题的几个不相关基类之一,因此理想的解决方案是通用的。

提前感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

好吧,这就是我所做的,它似乎有效并且是一个明智的设计(虽然我有待纠正!)。

在核心库(例如mysite.core.views.create_update)中,我写了一个装饰器:

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

在animals / views.py中,我有:

from mysite.core.views.create_update import update_object_as_child

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

在animals / urls.py中,我有:

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

现在我只需要为每个基类创建一个独特的编辑函数,这对于使用装饰器创建来说是微不足道的。

希望有人觉得有帮助,我很乐意收到反馈。

答案 1 :(得分:0)

AFAICT,猫和狗在不同的数据库表上,也许没有Animal表。但你正在使用一种URL模式。你需要在每个地方之间做出选择。

我会为猫和狗使用不同的网址模式,两者都会调用'create_update.update_object';但每个使用不同的dict。一个'model':Dog,另一个'model':Cat

或者你想要一张表,每张唱片都可以是猫还是狗?我认为你不能使用继承的模型。