Django模型ID被GenericForeignKey的ID覆盖

时间:2019-03-20 16:50:07

标签: mysql django python-3.x

我正在尝试使用我创建的自定义Django模型创建新的数据库条目。但是,当我尝试创建模型并将其保存时,id不会增加。相反,先前的数据库条目将被覆盖,其ID ==1。我尝试在save()函数中设置 force_insert = True ,但是这会导致运行时错误,其中主键已经存在。我在创建对象时未设置任何主要值,因此我不确定为什么ID不会增加。我正在manage.py shell中运行测试代码。所有模型均已正确迁移。

模型:

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))

Shell输出:

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

编辑#1: 我正在使用mySQL数据库,但尚未覆盖save()函数。 mySQL控制台仅在表(最近保存的模型)中显示一个条目。

编辑#2 我注释掉了RoadWayData模型,并迁移了更改以清除表格。之后,我取消了对模型的注释,并迁移了更改以将其添加回数据库。问题仍然存在。

编辑#3 我能够使用mySQL控制台将新条目手动插入表中。 ID正确增加。也许是Django错误?

编辑#4 我已经查明了问题的根源。问题源于 contenttypes 库。更具体地说,是 GenericForeignKey 。出于某种原因,当分配了内容对象时,模型会继承内容对象的ID。

代码与问题隔离:

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(在我的情况下为 incident_object )之前,创建一个变量来跟踪模型的ID。

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 个答案:

答案 0 :(得分:1)

RoadWayData 模型中的 incident_object 字段将引用 id (第二个参数)设置为其自己的id。因此,当模型分配 incident_object 时,它将覆盖模型的 id

要修复此问题,请创建一个新的 PostiveIntegerField (如 incident_id )并替换

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

incident_id = models.PostiveIntegerField(null=True)
incident_object = GenericForeignKey('incident_type', 'incident_id')