如何通过可重用的应用程序扩展模型?

时间:2011-12-26 17:56:10

标签: python django django-models

我写了一个主要允许用户通过jQuery将标签拖动到对象的应用程序。我想允许该应用程序适用于多个模型,以便我可以标记即。用户或图像。为此我想到在页面上的每个模型表示中添加一个包含“dropcode”的类:

<div class="droppable" dropcode="drop_img"> some image </div>
<div class="droppable" dropcode="drop_user"> some user </div>

我想为主项目设置中的每个模型指定“dropcode”:

droppable_models={User:'drop_user',Image:'drop_img'}

安装应用程序后,我希望能够从受影响模型的每个实例中检索丢弃代码:

image_instance1.dropcode -> drop_img
image_instance2.dropcode -> drop_img

user_instance1.dropcode -> drop_user
user_instance2.dropcode -> drop_user

这样我就可以简单地在页面上使用dropcode,通过jQuery返回它来选择合适的模型

这可能吗?有没有更好的方法来实现我想做的事情?

3 个答案:

答案 0 :(得分:0)

如果您的应用程序适用于任何模型,那么您应该使用contentypes framework

  

Django包含一个可以跟踪所有内容的contenttypes应用程序   安装在Django驱动项目中的模型,提供了一个   用于处理模型的高级通用界面。

实现这一点允许您的应用程序是通用的 - 它可以与任何已安装的模型一起使用。

编辑:

以下是如何使用内容类型框架(直接来自documentation):

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

class TaggedItem(models.Model):
    tag = models.SlugField()
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')

    def __unicode__(self):
        return self.tag

现在,要为项目添加标记:

item = Model.object.get(pk=1)
ti = TaggedItem(tag='foo',content_object=item)
ti.save()

获取特定项目的标签:

i = Image.object.get(pk=1) # or any instance of the Image object, or any object
the_type_of_object = ContentType.objects.get_for_model(i)

# Find all tags for this object
image_tags = TaggedItem.objects.filter(content_type__pk=the_type_of_object.id,
                                       object_id=i.id)

答案 1 :(得分:0)

为什么不在适当的模型中添加dropcode属性?例如

class Image(models.Model):
    ....
    dropcode = property(lambda self: "drop_img")

对于无法修改models.py(例如User型号)的现有模型,请将此类代码添加到您自己的某个应用的models.py中:

from django.contrib.auth.models import User
class UserMixin:
    dropcode = property(lambda self: "drop_user")
User.__bases__ += (UserMixin,)

然后在您的模板中,使用if标记检查某个项目是否包含丢弃代码。因此,您可以取消droppable_models设置:

<div class="droppable"{% if item.dropcode %} dropcode="{{item.dropcode}}"{% endif %}>{{item}}</div>

答案 2 :(得分:0)

根据Simon和Burhan的提示,我得出以下解决方案:我在设置中定义受影响的模型,然后将DragToTagable类作为基类添加到这些模型中。这看起来像在设置中:

DROPPABLE_MODELS=('test.TestItem:item',)

需要做的就是将应用功能应用于该模型或我项目的任何其他模型。我的应用程序的model.py现在看起来像这样:

from django.contrib.contenttypes.models import ContentType

from django.conf import settings

try:
    #perform this when starting the project
    for definition in settings.DROPPABLE_MODELS:     
        #parse contenttype 
        parsed=definition.split(':')
        dropcode=parsed[1]
        parsed=parsed[0].split('.')
        appname=parsed[0]
        modelname=parsed[1]

        #get the models class for the specified contenttype
        model_class=ContentType(app_label=appname, model=modelname).model_class()

        #create class Mixin, containing the dropcode property
        class DragToTagable:
            dropcode = dropcode

        #add DragToTagable as a base class to the model class
        model_class.__bases__+=(DragToTagable,)

except AttributeError:
    pass

except:
    import sys
    print "Unexpected error:", sys.exc_info()[0]
    raise

这样我就不必创建额外的表,就像在burhans提案中一样。该应用程序保持完全独立,无需在现有模型上实施。

感谢您的提示。