Django OneToOneField теряет связь, возвращая None после save()

Я немного запутался в поведении Django, и я не смог найти это ни в соответствующих вопросах, ни в официальной документации.

Например, в коде ниже:

from django.db import models

class Category(models.Model):
    name = models.CharField(max_length=255)

class Post(models.Model):
    title = models.CharField(max_length=255)
    category = models.OneToOneField(Category)

post = Post(title='My Title')
post.category = Category(name='My Category')
post.category.save()
# Here: post.category => Category(pk=1, name="My Category") 🎉
post.save()
# Here: post.category => None 😭

Я создаю объект Post. Затем я создаю на нем категорию, которую сохраняю перед сохранением поста. Но когда я вызываю метод post.save(), post.category очищается и устанавливается в None. Почему так происходит?

Я исправил это, сделав следующее, что вводит дополнительную переменную:

post = Post(title='My Title')
category = Category(name='My Category')
category.save()
post.category = category
# Here: post.category => Category(pk=1, name="My Category") 🎉
post.save()
# Here: post.category => Category(pk=1, name="My Category") 🎉

Почему введение дополнительной переменной изменяет поведение метода save() ?

Поскольку django использует lazy для своего кверисета, транзакция базы данных не выполняется, пока не будет вызвана save():

post = Post(title='My Title')
# cool you created a post instance of Post model(not database record)
post.category = Category(name='My Category')
# you set the instance attribute value to an instance of Category model
post.category.save()
# calling save() execute database transaction -> it create category object in DB -> your post instance with its attribute never get saved

post.save()
# now you only be saving Post(title='My Title')

Я не думаю, что это лучший ответ, но он объяснил поток

TLDR: ваш первый save() выполняется только для экземпляра Category, а не для экземпляра Post

Вернуться на верх