Django поле многие ко многим - программно получить отношения - PullRequest
1 голос
/ 12 августа 2011

Я работаю над моделью для тегов и пытаюсь избежать использования типов контента. У меня есть пара вопросов, связанных с ManyToManyField в Django.

У меня есть следующая модель

taggables / models.py

class Tag(models.Model):
    tag_statuses = (
        (u'P', _('Pending approval')),
        (u'A', _('Approved')),
    )
    slug             = models.SlugField()

    created_at      = models.DateTimeField(null=True, blank=True)
    created_by      = models.ForeignKey(User, related_name='tagged_item_created_by')
    status          = models.CharField(max_length=20, choices=tag_statuses)
    site            = models.ForeignKey(Site, default=settings.SITE_ID, related_name='tagged_item_site')


    def __unicode__(self):
        return self.slug


class TagI18n(models.Model):
    tag                 = models.CharField(max_length=100)
    descriptor          = models.TextField(null=True, blank=True)

    # i18n properties
    item                = models.ForeignKey(Tag)
    language            = models.CharField(max_length=6, choices=settings.LANGUAGES, default=settings.LANGUAGE_CODE)

    class Meta:
        unique_together = (("language", "item"))
    def __unicode__(self):
        return self.tag

У меня также есть различные приложения в моем проекте, которые используют модель тегов от поля ко многим до многих. такие как события например

evetns / models.py

class Item(models.Model):
    event_status_list = (
        (u'P', _('Pending approval')),
        (u'A', _('Approved')),
        (u'R', _('Rejected')),
        (u'S', _('Spam')),
    )

    published_at        = models.DateTimeField(null=True, blank=True)
    published_by        = models.ForeignKey(User, null=True, blank=True, related_name='item_published_by')
    updated_by          = models.ForeignKey(User, null=True, blank=True, related_name='item_updated_by')
    updated_at          = models.DateTimeField(null=True, blank=True)

    site                = models.ForeignKey(Site, default=settings.SITE_ID, related_name='events_item_site')

    event_slug          = models.SlugField(null=True, blank=True)

    # event timing
    event_start_date    = models.DateField()
    event_start_time    = models.TimeField(null=True, blank=True)
    event_end_date      = models.DateField()
    event_end_time      = models.TimeField(null=True, blank=True)


    event_recurrent     = models.BooleanField(default=False)
    event_status        = models.CharField(max_length=20, choices=event_status_list, default=u'P')

    # relations
    media        = models.ManyToManyField(ImageFile, null=True, blank=True)
    comments     = models.ManyToManyField(Comment, null=True, blank=True)
    votes        = models.ManyToManyField(Vote, null=True, blank=True)
    tags         = models.ManyToManyField(Tag, null=True, blank=True)
    audience     = models.ManyToManyField(Audience, null=True, blank=True)

Теперь я пытаюсь выполнить запрос, чтобы программно получить все связанные модели в Tag, а затем посчитать, сколько раз использовался тег. Я уверен, что смогу сделать это с типами контента (универсальными типами), но я не знаю, как он будет работать при интенсивном использовании, поэтому я хотел использовать поля многие ко многим.

Ответы [ 2 ]

0 голосов
/ 12 августа 2011

В вашем случае производительность generic не имеет значения, потому что вам все равно нужно выполнить N запросов к 2N таблицам (по крайней мере, один для каждой модели с тегами и один для каждой таблицы соединения m2m).

При подходе m2m у вас должен быть список моделей 'taggable', хранящийся где-то, по крайней мере, как список пар ('app_name', 'model'). Затем используйте ContentType (он очень производительный), чтобы получить реальный класс модели или запрос непосредственно оттуда:

counts = {}
for m in taggable_models:
    ct = ContentType.get_by_natural_key(*m)
    c = ct.model_class().objects.filter(tags=yourtag).distinct().count()
    counts[ct.name] = c
0 голосов
/ 12 августа 2011

Если вас очень интересует общее количество использований (так называемый счетчик ссылок) тега, я думаю, вам следует сохранить его в базе данных, например, поместите одно дополнительное поле в модель тега, например

* 1002.*

Чем в соответствующих местах (например, модели .save()) вы можете увеличивать или уменьшать его значение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...