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

2024-10-03 06:28:35 发布

您现在位置:Python中文网/ 问答频道 /正文

我编写了一个应用程序,主要允许用户通过jQuery将标记拖到对象上。我想让该应用程序可以为多个模型工作,这样我就可以标记ie。一个用户或图像。为此,我考虑在页面上的每个模型表示中添加一个包含“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'}

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

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

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

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

有可能吗?有没有更好的方法来实现我的目标?你知道吗


Tags: 用户标记模型imagediv应用程序imgsome
3条回答

根据Simon和Burhan的提示,我找到了以下解决方案:在设置中定义受影响的模型,然后将dragtotatable类作为基类添加到这些模型中。在设置中如下所示:

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

这就是将应用程序功能应用于该模型或我的项目的任何其他模型所需要做的全部工作。这个型号.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提案那样创建额外的表。而且该应用程序保持完全独立,不需要对现有模型进行任何工作即可实现。你知道吗

谢谢你的小费。你知道吗

如果应用程序应与任何模型一起工作,则应使用contentypes framework

Django includes a contenttypes application that can track all of the models installed in your Django-powered project, providing a high-level, generic interface for working with your models.

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

编辑:

下面是如何使用内容类型框架(直接从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)

为什么不在适当的模型中添加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标记检查项目是否有dropcode。因此,可以消除droppable_models设置:

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

相关问题 更多 >