Типичное отношение один к одному в Django

20

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

class Event(models.Model):
    # skip event related fields...
    content_type      = models.ForeignKey(ContentType)
    object_id         = models.PositiveIntegerField()
    content_object    = generic.GenericForeignKey('content_type', 'object_id')

    class Meta:
        unique_together   = ('content_type', 'object_id')

class Action1(models.Model):
    # skip action1 related fields...
    events = generic.GenericRelation(Event, content_type_field='content_type', object_id_field='object_id')

    @property
    def event(self):
        return self.events.get() # <<<<<< Is this reasonable?

class Action2(models.Model):...

В Django Admin в списке событий я хочу собрать все действия, а оттуда я хочу перейти на страницы администратора для действий. Можно ли избежать создания свойства event в моделях действий? Есть ли лучшее решение? Было бы неплохо объединить поле events и свойство event в одном определении. В проекте, с которым я работаю, используется Django 1.1

    
задан Andrei 20.10.2011 в 16:18
источник
  • Если вы действительно хотите избежать событий, вам необходимо выполнить запрос к таблице событий вручную, как это предлагается ниже. Я бы предпочел иметь события как GenericRelation, а затем использовать self.events.first () в свойстве события. Кроме того, это позволит вам в будущем удалить уникальное ограничение. –  alexcasalboni 13.07.2017 в 17:53

1 ответ

15

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

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

    class Meta:
        unique_together   = ('content_type', 'object_id')

class EventMixin(object):
     @property
     def get_event(self):
         ctype = ContentType.objects.get_for_model(self.__class__)
         try:
             event = Event.objects.get(content_type__pk = ctype.id, object_id=self.id)
         except:
            return None 
         return event

class Action1(EventMixin, models.Model):
    # Don't need to mess up the models fields (make sure the mixing it placed before models.Model)
    ...

и

action = Action1.object.get(id=1)
event = action.get_event

Возможно, вы захотите добавить кеширование и в обратную связь

    
ответ дан Timmy O'Mahony 15.02.2012 в 16:02
  • Его работы хорошо, но это не дает возможности: Action.objects.select_related ('event') –  ramusus 24.05.2013 в 14:58
  • Мне не нравится это решение -> GenericRelation выглядит намного лучше, даже если вам нужно использовать self.events.get () или self.events.first () –  alexcasalboni 13.07.2017 в 17:50
  • То же, что и комментарии выше. То, что у вас было первоначально с GenericRelation, намного лучше. –  s-block 27.02.2018 в 11:13
  • Следовательно, «Что вы сделали хорошо» –  Timmy O'Mahony 27.02.2018 в 11:31