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

Python 如何通过可重用的应用程序扩展模型?,python,django,django-models,Python,Django,Django Models,我编写了一个应用程序,主要允许用户通过jQuery将标签拖动到对象。我想让该应用程序可以在多个模型上运行,这样我就可以标记用户或图像。为此,我考虑在页面上的每个模型表示中添加一个包含“dropcode”的类: <div class="droppable" dropcode="drop_img"> some image </div> <div class="droppable" dropcode="drop_user"> some user </div&g

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

<div class="droppable" dropcode="drop_img"> some image </div>
<div class="droppable" dropcode="drop_user"> some user </div>
安装应用程序后,我希望能够从受影响型号的每个实例检索dropcode:

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

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


可能吗?是否有更好的方法实现我的目标?

如果您的应用程序适用于任何型号,那么您应该使用:

Django包括一个contenttypes应用程序,可以跟踪所有 安装在Django项目中的型号,提供 用于处理模型的高级通用界面

实现这一点可以使您的应用程序具有通用性—它可以与任何已安装的模型一起工作

编辑:

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

现在,要向项目添加标记,请执行以下操作:

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
model)的现有机型,请将类似这样的代码添加到您自己应用程序之一的
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>
{{item}

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

droppable_models={User:'drop_user',Image:'drop_img'}
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提案中那样创建额外的表。该应用程序保持完全独立,不需要对现有模型进行任何操作即可实现


谢谢你的提示。

嘿,谢谢你的回答。我知道contenttypes框架,并且已经怀疑我应该使用它。但是我不能绞尽脑汁去思考如何利用它来实现我想要的。。。给我一个从哪里开始的提示?好吧,这就是我在django文档中提到的。但无论如何,我都需要一个模型。当我使用taggit应用程序存储标签时,我宁愿避免创建新模型。我的应用不需要存储任何数据,它只需要在现有应用之间创建一些链接。如果您正在创建链接,存储它们的唯一方法是使用模型。我不熟悉taggit,但如果它与其他标记应用程序有任何相似之处的话,我肯定它在某处使用了内容类型。也许你可以自定义它?只是一般意义上的链接,而不是超链接——也许我应该写“逻辑连接”。无论如何,我意识到我的问题可能更多的是Python而不是Django。我想我可以通过动态地将属性分配给相应的类来解决这个问题。我只需要找到如何通过contenttypes检索该模型。顺便说一下,我创建的应用程序现在没有任何模型。只有一堆视图来处理ajax请求,用于存储标签,它使用taggit应用程序。你的建议不起作用,因为可重用应用程序的目的不是改变你的其他应用程序。可重用的应用程序应该只需要更改主url.py、settings.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