【问题标题】:Is it possible to set the implicit OneToOne key directly when using multi table inheritance in Django?在 Django 中使用多表继承时是否可以直接设置隐式 OneToOne 键?
【发布时间】:2012-09-02 23:33:19
【问题描述】:

我正在尝试通过多表继承来扩展库模型,这就是我最终得到的结果:

class CompetitionMedia(InstagramMedia):
    visible = models.BooleanField(default=True)
    most_creative = models.BooleanField(default=False)

@receiver(post_save, sender=InstagramMedia, dispatch_uid='create_competition_media')
def create_competition_media(sender, instance, created, **kwargs):
    competition_media = CompetitionMedia()
    competition_media.instagrammedia = instance
    competition_media.save() # fails

@receiver(post_save, sender=InstagramMedia, dispatch_uid='create_competition_media2')
def create_competition_media2(sender, instance, created, **kwargs):
    CompetitionMedia.objects.create(instagrammedia=instance) # Fails

可以这样做吗?

【问题讨论】:

  • 只有在创建新实例时才需要保存。顺便说一句,你得到什么错误?
  • @Rohan 我在简化示例时将其排除在外,但您是对的。我得到的错误是 instagrammedia 字段不存在。

标签: python django django-models django-orm django-signals


【解决方案1】:

据我了解,您希望得到这样的东西:

class CompetitionMedia(models.Model):
    instagrammedia = models.OneToOneField(InstagramMedia, primary_key=True)
    visible = models.BooleanField(default=True)
    most_creative = models.BooleanField(default=False)

@receiver(post_save, sender=InstagramMedia, dispatch_uid='create_competition_media2')
def create_competition_media(sender, instance, created, **kwargs):
    if created:  
         CompetitionMedia.objects.create(instagrammedia=instance)

【讨论】:

  • 虽然这是实现相同目标的一种方法,但实际上我只想知道是否可以使用多表继承而不是组合。
  • 这不是你想要的,但也许这是一个可以接受的解决方案(我项目中的一个例子):gist.github.com/3693618
  • 但据我所知,通常你想要的都是不可能的。继承将创建一个单独的表,如果它是 proxy=Trueabstract=True 模型,则不执行任何操作。显而易见的方法 - 覆盖模型的元类。
【解决方案2】:

我显然应该设置parent_ptr,例如:

@receiver(post_save, sender=InstagramMedia, dispatch_uid='create_competition_media')
def create_competition_media2(sender, instance, created, **kwargs):
    if created:
        CompetitionMedia.objects.create(instagrammedia_ptr=instance)

但是,如果您先创建并保存父级然后尝试创建子级,则存在一个问题,即使在您未在子级中设置的字段上,子级也会覆盖父级。正如https://code.djangoproject.com/ticket/11618https://code.djangoproject.com/ticket/7623 中所述,所以我会避免它,因为它不是很明显会发生。

如果有人真的想走那条路,你需要这样做:

@receiver(post_save, sender=InstagramMedia, dispatch_uid='create_competition_media')
def create_competition_media2(sender, instance, created, **kwargs):
    if created:
        CompetitionMedia.objects.create(instagrammedia_ptr=instance)
        instance.save() # This should re-save the parent values.

更好:

@receiver(post_save, sender=InstagramMedia, dispatch_uid='create_competition_media')
def create_competition_media2(sender, instance, created, **kwargs):
    if created:
        CompetitionMedia.objects.create(instagrammedia_ptr=instance,
            **instance.__dict__)

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2012-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-24
  • 2016-03-31
  • 1970-01-01
相关资源
最近更新 更多