В Джанго 4.x
Код работает как ожидалось
from django.db import models
class Project(models.Model):
rough_data = models.OneToOneField(
"Data",
related_name = "rough_project",
on_delete=models.SET_NULL,
null=True,
blank=True,
)
final_data = models.OneToOneField(
"Data",
related_name = "final_project",
on_delete=models.SET_NULL,
null=True,
blank=True,
)
class Data(models.Model):
pass
data, created = Data.objects.update_or_create(
rough_project=project, defaults=data
)
В Джанго 5.x:
ValueError: The following fields do not exist in this model: rough_project
Я не вижу никаких изменений, связанных с этим, в журнале изменений
В Django 4.2 и ниже это работало одной строкой с update_or_create
, а в 5.0 оно перестало работать, поэтому вместо этого мне нужно сделать что-то вроде этого:
data = getattr(project, "rough_data", None)
if data:
# update fields here
else:
# create Data object
Нет, я хочу сделать это: ``` data = getattr(project, "rough_project", None) if data: # обновить поля здесь else: # создать объект данных ``` В django 4.2 и ниже это работало как одна строка с update_or_create
и в 5.0 он перестал работать. Я не понимаю, почему.
Пожалуйста, укажите код в своем if else
В Django 4.x он не вызывал исключения, но и не сохранял связь, если объект был создан — так что на самом деле он работал не так, как ожидалось.
Кажется, что он работает так, как ожидалось, только если после этого вызывается project.save()
.
1Вы можете исправить это и вместо этого заранее сохранить отношения, создав подкласс QuerySet
и переопределив метод create
, а затем указав Data
objects
для использования вашего Manager
:
class CreateSaveReverseOneToOneFieldsQuerySet(models.QuerySet):
def create(self, **kwargs):
"""
Create a new object with the given kwargs, saving it to the database and returning the created object.
Also save objects in reverse OneToOne fields — see https://stackoverflow.com/questions/78863608/django-5-update-or-create-reverse-one-to-one-field.
"""
obj = self.model(**kwargs)
self._for_write = True
obj.save(force_insert=True, using=self.db)
# Save reverse OneToOne fields
reverse_one_to_one_fields = frozenset(kwargs).intersection(self.model._meta._reverse_one_to_one_field_names)
for field_name in reverse_one_to_one_fields:
getattr(obj, field_name).save()
return obj
class DataManager(models.manager.BaseManager.from_queryset(CreateSaveReverseOneToOneFieldsQuerySet)):
pass
class Data(models.Model):
objects = DataManager()
Я думаю, что это проблема модели:
Внутри модели данных нет полей rough_project
Предоставленный вами код не будет работать должным образом из-за способа использования update_or_create с OneToOneField.
Поиск rough_project=project
пытается найти объект Data
, где обратная связь rough_project
указывает на объект Project
. Однако rough_project
является обратной связью в модели Data
, и Django не позволяет использовать обратные связи в части поиска update_or_create
.
Если вы хотите обновить или создать объект Data
и связать его с Project
, вам нужно сделать что-то вроде следующего:
data, created = Data.objects.update_or_create(
id=some_id, # Use an appropriate field to identify the Data object, e.g., primary key (id).
defaults = {'rough_project': project} # Correctly specify the relationship in defaults.
)
Если у вас есть экземпляр Project
и вы хотите установить его rough_data
или final_data
:
# Create or get the Data object
data, created = Data.objects.update_or_create(
id=some_id, # some unique identifier for Data
defaults = {'some_field': some_value} # other fields to update or set
)
# Assign the Data object to the Project
project.rough_data = data
project.save()
** Надеюсь, это поможет **
Это то, что ты хотел сделать?
data = Data.objects.get(project_set=project)