Можно ли установить неявный ключ OneToOne напрямую при использовании наследования нескольких таблиц в Django?

Я пытаюсь расширить библиотечную модель за счет наследования нескольких таблиц, и вот чем я закончил:

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

Можно ли сделать это?

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/11618 и https://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__)

Насколько я понимаю, вы хотите получить что-то вроде этого:

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)
Другие вопросы по тегам