Идентификатор модели Django перезаписывается идентификатором GenericForeignKey - PullRequest
1 голос
/ 20 марта 2019

Я пытаюсь создать новую запись в базе данных, используя созданную мной модель Django.Однако, когда я пытаюсь создать модель и сохранить ее, идентификатор не увеличивается.Вместо этого предыдущая запись в базе данных перезаписывается с идентификатором == 1. Я попытался установить force_insert = True внутри функции save (), но это приводит к ошибке времени выполнения, когда первичный ключ уже существует.Я не устанавливаю никаких первичных значений при создании объекта, поэтому я не уверен, почему идентификатор не увеличивается.Я запускаю тестовый код в оболочке manage.py.Все модели были перенесены правильно.

Модель:

class RoadWayData(models.Model):
    blocked_lanes = models.PositiveIntegerField()
    city = models.CharField(max_length=255)
    county = models.CharField(max_length=255)
    direction = models.CharField(max_length=255, blank=True, null=True, default=None)
    eto = models.CharField(max_length=255)
    incident_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    incident_object = GenericForeignKey('incident_type', 'id')
    injuries = models.PositiveIntegerField()
    postmile = models.CharField(max_length=255, blank=True, null=True, default=None)
    queue = models.CharField(max_length=255, default="NONE: Freeflow Conditions")
    route = models.CharField(max_length=255, blank=True, null=True, default=None)
    street = models.CharField(max_length=255, blank=True, null=True, default=None)
    timestamp = models.DateTimeField(auto_now=True)
    update = models.PositiveIntegerField()
    maintenance = models.CharField(max_length=255)
    tow = models.CharField(max_length=255)
    weather = models.CharField(max_length=255)
    vehicles_involved = models.PositiveIntegerField()

Тестовый код:

from incident.models import *
import datetime

x = IncidentIndex.objects.get(id=1)
y = CHPIncident.objects.get(id=x.incident_object.id)

print("ID already exists in DB: {}".format(RoadWayData.objects.get(id=1).id))

z = RoadWayData(
        blocked_lanes=0,
        city="testCity",
        county="testCounty",
        direction="NB",
        eto="Unknown",
        highway_accident=True,
        incident_object=y,
        injuries=0,
        postmile="New Postmile",
        route="new Route",
        update = 2,
        maintenance= "Not Requested",
        tow="Not Requested",
        weather="Clear Skies",
        vehicles_involved=0,
    )

z.save()
print("New Data Object ID: {}".format(z.id))

Вывод оболочки:

ID already exists in DB: 1
New Data Object ID: 1

Редактировать # 1: Я использую базу данных mySQL и не переопределил функцию save ().Консоль mySQL показывает только одну запись в таблице (модель, которая была сохранена в последний раз).

Edit # 2 Я закомментировал модель RoadWayData и перенес изменения, чтобы стереть таблицу.После этого я откомментировал модель и перенес изменения, чтобы добавить ее обратно в базу данных.Проблема все еще сохраняется.

Edit # 3 Мне удалось вручную вставить новую запись в таблицу с помощью консоли mySQL.Идентификатор увеличен правильно.Возможно, это ошибка Django?

Edit # 4 Я точно определил источник проблемы.Проблема связана с библиотекой contenttypes .В частности, GenericForeignKey .По какой-то причине, когда объект контента назначен, модель наследует идентификатор объекта контента.

Код с изолированной проблемой:

x = IncidentIndex.objects.get(id=1)
y = CHPIncident.objects.get(id=x.incident_object.id)
r = RoadWayData( 
    ... 
    incident_object = None,  # Do not assign the generic foreign key
    ...
)

r.save()
print(r) # Shows <RoadWayData object> with CORRECT id
r.incident_object = y # Assign the general object
print(r) # Shows <RoadWayData object> with the id of y. INCORRECT

Самое простое решение - создать переменную для отслеживания идентификатора модели ДО присвоения content_object ( инцидент_объект в моемcase).

FIX:

... initialization from code above ...

r.save()
r_id = r.id # SAVE THE CORRECT ID BEFORE ASSIGNING GENERIC FOREIGN KEY

r.incident_object = y # ASSIGN THE GENERIC FOREIGN OBJECT

r.id = r_id # OVERWRITE THE ID WITH THE CORRECT OLD ID
r.save()

1 Ответ

1 голос
/ 25 марта 2019

Поле инцидент_объекта в модели RoadWayData имеет ссылку id (второй параметр), установленную на свой собственный идентификатор. Таким образом, когда модель назначает инцидент_объекта , она перезаписывает идентификатор модели.

Чтобы исправить это, создайте новый PostiveIntegerField (например, инцидент_ид ) и замените

incident_object = GenericForeignKey('incident_type', 'id')

с

incident_id = models.PostiveIntegerField(null=True)
incident_object = GenericForeignKey('incident_type', 'incident_id')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...