Django中的通用一对一关系

And*_*rei 21 python django django-models one-to-one django-admin

我需要建立一对一的关系,这种关系也必须是通用的.也许你可以建议我一个更好的设计.到目前为止,我提出了以下模型

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):...
Run Code Online (Sandbox Code Playgroud)

在事件列表中的Django Admin中,我想收集所有操作,然后从那里我想去管理页面进行操作.是否有可能避免event在动作模型中创建属性?有更好的解决方案吗?将字段events和属性组合event在一个定义中会很好.我正在使用的项目使用Django 1.1

Tim*_*ony 15

我最近遇到了这个问题.你所做的很好,但你可以通过创建一个透明地反转关系的mixin来进一步概括它:

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)
    ...
Run Code Online (Sandbox Code Playgroud)

action = Action1.object.get(id=1)
event = action.get_event
Run Code Online (Sandbox Code Playgroud)

您可能还希望将缓存添加到反向关系中

  • 我不喜欢这个解决方案 - >`GenericRelation`看起来好多了,即使你需要使用`self.events.get()`或`self.events.first()` (3认同)

Gee*_*ado 11

GenericRelation是一个用于表示通用多对一并添加first_event属性允许表示通用一对一的类。

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') # Important

class Action1(models.Model):
    events = generic.GenericRelation(Event)

    @property
    def first_event(self):
        return self.events.first()
Run Code Online (Sandbox Code Playgroud)

此外,我建议使用.first()insideAction1.first_event而不是.get()due,None因为如果事件不存在,它就会返回。.get()如果事件不存在,则会引发异常,并且这种行为可能是不需要的。