Как я могу расширить модель с помощью повторно используемого приложения? - PullRequest
0 голосов
/ 26 декабря 2011

Я написал приложение, которое в основном позволяет пользователю перетаскивать теги на объекты через 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

Таким образом, я могу просто использовать дропкод настраницы, верните ее через jQuery, чтобы выбрать подходящую модель

Возможно ли это?Есть ли лучший способ добиться того, что я хочу сделать?

Ответы [ 3 ]

0 голосов
/ 26 декабря 2011

Почему бы не добавить свойство 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>
0 голосов
/ 27 декабря 2011

На основе советов Саймона и Бурхана я пришел к следующему решению: я определяю затронутые модели в настройках, а затем добавляю класс 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

Таким образом, мне не нужно создавать дополнительную таблицу, как в предложении бурханов. И приложение остается полностью независимым и не требует работы над существующими моделями.

Спасибо за советы.

0 голосов
/ 26 декабря 2011

Если ваше приложение должно работать с любой моделью, вам следует использовать frameworky contentypes :

Django включает приложение contenttypes, которое может отслеживать все модели, установленные в вашемПроект на основе Django, предоставляющий универсальный общий интерфейс для работы с вашими моделями.

Реализация этого позволяет вашему приложению быть универсальным - оно может работать с любой установленной моделью.* РЕДАКТИРОВАТЬ:

Вот как использовать структуру типов контента (непосредственно из документации ):

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