Reputation: 43
I am trying create a new database entry using a custom Django model I created. However, when I try to create the model and save it, the id does not increment. Instead, the previous database entry is overwritten whose id == 1. I have tried setting force_insert=True inside the save() function, but it results in a runtime error where the primary key already exists. I don't set any primary values in the creation of the object, so I'm not sure why the id is not being incremented. I am running the test code in the manage.py shell. All the models have been migrated properly.
The model:
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()
The test code:
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 Output:
ID already exists in DB: 1
New Data Object ID: 1
Edit #1: I am using a mySQL database and have not overridden the save() function. The mySQL console shows only one entry in the table(the model that was most recently saved).
Edit #2 I commented out the RoadWayData model and migrated the changes to wipe the table. Afterwards, I un-commented the model and migrated the changes to add it back to the database. The issue still persists.
Edit #3 I was able to manually insert a new entry into the table using the mySQL console. The ID incremented correctly. Perhaps it is a Django bug?
Edit #4 I've pinpointed the source of the problem. The problem stems from the contenttypes library. More specifically, the GenericForeignKey. For some reason when an the content object is assigned, the model inherits the content object's id.
Code with problem isolated:
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
The easiest fix would be to create a variable to keep track of the Model's id BEFORE assigning the content_object (incident_object in my 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()
Upvotes: 1
Views: 248
Reputation: 43
The incident_object field in the RoadWayData model, has the reference id (the second parameter) set to its own id. So, when model assigns incident_object , it overwrites the id of the model.
To fix it, create a new PostiveIntegerField (like incident_id) and replace
incident_object = GenericForeignKey('incident_type', 'id')
with
incident_id = models.PostiveIntegerField(null=True)
incident_object = GenericForeignKey('incident_type', 'incident_id')
Upvotes: 1