0

在 Django 中,给出了应用程序动物的摘录,如下所示:

带有以下内容的动物/模型.py

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

还有一个动物/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 可能是具有相同问题的几个不相关的基类之一,因此理想的解决方案将是通用的。

预先感谢您的帮助。

4

2 回答 2

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

在动物/urls.py 中,我有:

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

现在我只需要为每个基类创建一个唯一的编辑函数,使用装饰器创建它是微不足道的。

希望有人觉得这很有帮助,我很高兴得到反馈。

于 2008-10-18T19:40:12.103 回答
0

AFAICT,猫和狗在不同的数据库表上,也许没有动物表。但是您对所有人都使用一种 URL 模式。您需要在每个位置之间进行选择。

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

或者您可能想要一个表,其中每条记录都可以是猫或狗?我认为您不能为此使用继承的模型。

于 2008-10-17T18:51:06.433 回答