Django 中的通用一对一关系

发布于 2024-12-11 09:46:47 字数 918 浏览 0 评论 0原文

我需要建立一对一的关系,该关系也必须是通用的。也许你可以建议我更好的设计。到目前为止,我在事件列表中的 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):...

,我想收集所有操作,然后从那里我想转到管理页面进行操作。是否可以避免在操作模型中创建 event 属性?有更好的解决方案吗?最好将字段 events 和属性 event 组合在一个定义中。我正在处理的项目使用 Django 1.1

I need to set up one-to-one relation which must also be generic. May be you can advice me a better design. So far I came up to the following models

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

In Django Admin in event list I want to collect all actions, and from there I want go to admin pages for actions. Is it possible to avoid creating event property in the action models? Is there a better solution? It would be nice to combine the field events and the property event in a single definition. The project I am working with uses Django 1.1

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

娇俏 2024-12-18 09:46:47

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

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

你可能也想向反向关系添加缓存

I recently came across this problem. What you have done is fine, but you can generalise it a little bit more by creating a mixin that reverses the relationship transparently:

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

and

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

You might want to add caching to the reverse relationship too

南街九尾狐 2024-12-18 09:46:47

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

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

GenericRelation is a class for representing a Generic Many to One and adding a first_event property allow to represent a Generic One to One.

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

In addition, I recommend using .first() inside Action1.first_event instead of .get() due to, it returning None if the event doesn't exist. .get() raises an exception if the event doesn't exist and this behavior can be unwanted.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文