Как смоделировать внешний ключ в допускающем повторное использование приложении Django?

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

мне напоминают о студенте, делающем аналитическую программу видения, кто не мог понять, почему это было настолько медленно. Он просто следовал за хорошей практикой программирования - каждый пиксель был объектом и работавшим путем отправки сообщений его соседям...

проверка это

14
задан Apreche 14 September 2009 в 02:24
поделиться

5 ответов

Если вы считаете, что приложение-ссылка всегда будет указывать на одно приложение, то одним из подходов будет передача имени внешней модели в виде строки, содержащей метку приложения. ссылки на класс ( Django docs объяснение ).

Другими словами, вместо:

class Link(models.Model):
    blog_post = models.ForeignKey(BlogPost)

сделайте:

from django.conf import setings
class Link(models.Model):
    link_model = models.ForeignKey(settings.LINK_MODEL)

и в ваших settings.py:[1273 impression

23
ответ дан 1 December 2019 в 12:01
поделиться

Я думаю, что TokenMacGuy на правильном пути. Я хотел бы посмотреть, как django-tagging обрабатывает аналогичные общие отношения, используя тип содержимого, общий object_id, и generic.py . Из models.py

class TaggedItem(models.Model):
    """
    Holds the relationship between a tag and the item being tagged.
    """
    tag          = models.ForeignKey(Tag, verbose_name=_('tag'), related_name='items')
    content_type = models.ForeignKey(ContentType, verbose_name=_('content type'))
    object_id    = models.PositiveIntegerField(_('object id'), db_index=True)
    object       = generic.GenericForeignKey('content_type', 'object_id')

    objects = TaggedItemManager()

    class Meta:
        # Enforce unique tag association per object
        unique_together = (('tag', 'content_type', 'object_id'),)
        verbose_name = _('tagged item')
        verbose_name_plural = _('tagged items')
1
ответ дан 1 December 2019 в 12:01
поделиться

I Пойдем с родовыми отношениями. Вы можете сделать что-то вроде select_related, это просто требует дополнительной работы. Но я думаю, оно того стоит.

Одно из возможных решений для общих функций, подобных select_related:

http:

0
ответ дан 1 December 2019 в 12:01
поделиться

Этот вопрос и ответ Ван Гейла подводят меня к вопросу, как это может быть возможно, чтобы ограничить типы содержимого для GFK без необходимости определять его через объекты Q в модель, чтобы его можно было полностью использовать повторно

, решение основано на

  • django.db.models.get_model
  • и встроенной функции eval, которая оценивает Q-объект из settings.TAGGING_ALLOWED . Это необходимо для использования в админ-интерфейсе

Мой код довольно грубый и не полностью протестирован

settings.py

TAGGING_ALLOWED=('myapp.modela', 'myapp.modelb')

models.py:

from django.db import models
from django.db.models import Q
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic
from django.db.models import get_model
from django.conf import settings as s
from django.db import IntegrityError

TAGABLE = [get_model(i.split('.')[0],i.split('.')[1]) 
        for i in s.TAGGING_ALLOWED if type(i) is type('')]
print TAGABLE

TAGABLE_Q = eval( '|'.join(
    ["Q(name='%s', app_label='%s')"%(
        i.split('.')[1],i.split('.')[0]) for i in s.TAGGING_ALLOWED
    ]
))

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

    def save(self, force_insert=False, force_update=False):
        if self.content_object and not type(
            self.content_object) in TAGABLE:
            raise IntegrityError(
               'ContentType %s not allowed'%(
                type(kwargs['instance'].content_object)))
        super(TaggedItem,self).save(force_insert, force_update)

from django.db.models.signals import post_init
def post_init_action(sender, **kwargs):
    if kwargs['instance'].content_object and not type(
        kwargs['instance'].content_object) in TAGABLE:
        raise IntegrityError(
           'ContentType %s not allowed'%(
            type(kwargs['instance'].content_object)))

post_init.connect(post_init_action, sender= TaggedItem)

Конечно, на это решение влияют ограничения contenttype-framework

# This will fail
>>> TaggedItem.objects.filter(content_object=a)
# This will also fail
>>> TaggedItem.objects.get(content_object=a)
0
ответ дан 1 December 2019 в 12:01
поделиться

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

0
ответ дан 1 December 2019 в 12:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: