Можно ли установить неявный ключ 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)