Django – duplicate key error after trying to create a new model
Question:
I have a location model and it has a city field, which is a foreign key. The database is already filled with all the countries, states and cities so when I want to create a new location I will just select the city, which is connected to a state and the state is connected to a country.
Here is the location model:
class Location(models.Model):
name = models.CharField(max_length=50, default=None, null=True, blank=True)
street = models.CharField(max_length=100)
additional = models.CharField(max_length=100, null=True, blank=True)
city = models.OneToOneField(City, on_delete=models.CASCADE, related_name="cities")
zip_code = models.CharField(max_length=30)
phone = models.CharField(max_length=15, null=True, blank=True)
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True, verbose_name="created at")
updated_at = models.DateTimeField(auto_now=True, verbose_name="updated at")
class Meta:
verbose_name = "location"
verbose_name_plural = "locations"
db_table = "locations"
ordering = ["zip_code"]
def __str__(self):
return self.name
def get_absolute_url(self):
return self.slug
I am trying to update a location or create it if it does not exists yet and here is the code I use to do that. It’s part of a patch request:
class UpdateUserSettings(generics.UpdateAPIView):
permission_classes = [permissions.IsAuthenticated]
serializer_class = SettingsSerializer
name = 'user-settings'
def get_queryset(self):
id = self.kwargs['pk']
return UserSettings.objects.all().filter(user=id)
def patch(self, request, *args, **kwargs):
user = User.objects.get(id=self.request.data.get('user'))
settings = UserSettings.objects.get(user=user)
form = self.request.data.get('form')
if form == 'editEssentialsForm':
email = self.request.data.get('email')
elif form == 'editPaymentsForm':
gateway = Gateway.objects.get(name=request.data.get("gateway"))
settings.gateway = gateway
name = "user-" + str(user) + "'s billing address"
street = request.data.get("billing_street")
additional = request.data.get("billing_additional")
city = City.objects.get(id=request.data.get("billing_city"))
zipcode = request.data.get("billing_zip")
Location.objects.update_or_create(name=name, street=street, additional=additional, city=city, zip_code=zipcode, phone=settings.phone, user=user)
return Response("Settings updated successfully", status=HTTP_200_OK)
When I run the code to create the new location I get the following error:
django.db.utils.IntegrityError: duplicate key value violates unique constraint "locations_city_id_key"
DETAIL: Key (city_id)=(1) already exists.
There is one other location in the database with the same city so my question is why can I not have two locations with the same city which is what this error is telling me if I’m not wrong?
What am I doing wrong please?
Answers:
You have set:
city = models.OneToOneField(City, on_delete=models.CASCADE, related_name="cities")
An OneToOneField
ensures that there should be unique city
in your locations
table. You should use ForeignKey
if you want to add multiple locations
that have same city
.
Example:
city = models.ForeignKey(City, on_delete=models.CASCADE, related_name="cities")
Yes, Postgres uses what it calls a sequence 10 object to track the next PK to assign. If you restore the database and that restore process doesn’t include the related sequence object, you end up in exactly this situation.
You can use the ALTER SEQUENCE 47 statement (with the RESTART parameter) in psql to reset the sequence to the desired value.
You also want to ensure that your pg_dump command is written to include all sequences in your backup to prevent this from happening in the future.
I have a location model and it has a city field, which is a foreign key. The database is already filled with all the countries, states and cities so when I want to create a new location I will just select the city, which is connected to a state and the state is connected to a country.
Here is the location model:
class Location(models.Model):
name = models.CharField(max_length=50, default=None, null=True, blank=True)
street = models.CharField(max_length=100)
additional = models.CharField(max_length=100, null=True, blank=True)
city = models.OneToOneField(City, on_delete=models.CASCADE, related_name="cities")
zip_code = models.CharField(max_length=30)
phone = models.CharField(max_length=15, null=True, blank=True)
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True, verbose_name="created at")
updated_at = models.DateTimeField(auto_now=True, verbose_name="updated at")
class Meta:
verbose_name = "location"
verbose_name_plural = "locations"
db_table = "locations"
ordering = ["zip_code"]
def __str__(self):
return self.name
def get_absolute_url(self):
return self.slug
I am trying to update a location or create it if it does not exists yet and here is the code I use to do that. It’s part of a patch request:
class UpdateUserSettings(generics.UpdateAPIView):
permission_classes = [permissions.IsAuthenticated]
serializer_class = SettingsSerializer
name = 'user-settings'
def get_queryset(self):
id = self.kwargs['pk']
return UserSettings.objects.all().filter(user=id)
def patch(self, request, *args, **kwargs):
user = User.objects.get(id=self.request.data.get('user'))
settings = UserSettings.objects.get(user=user)
form = self.request.data.get('form')
if form == 'editEssentialsForm':
email = self.request.data.get('email')
elif form == 'editPaymentsForm':
gateway = Gateway.objects.get(name=request.data.get("gateway"))
settings.gateway = gateway
name = "user-" + str(user) + "'s billing address"
street = request.data.get("billing_street")
additional = request.data.get("billing_additional")
city = City.objects.get(id=request.data.get("billing_city"))
zipcode = request.data.get("billing_zip")
Location.objects.update_or_create(name=name, street=street, additional=additional, city=city, zip_code=zipcode, phone=settings.phone, user=user)
return Response("Settings updated successfully", status=HTTP_200_OK)
When I run the code to create the new location I get the following error:
django.db.utils.IntegrityError: duplicate key value violates unique constraint "locations_city_id_key"
DETAIL: Key (city_id)=(1) already exists.
There is one other location in the database with the same city so my question is why can I not have two locations with the same city which is what this error is telling me if I’m not wrong?
What am I doing wrong please?
You have set:
city = models.OneToOneField(City, on_delete=models.CASCADE, related_name="cities")
An OneToOneField
ensures that there should be unique city
in your locations
table. You should use ForeignKey
if you want to add multiple locations
that have same city
.
Example:
city = models.ForeignKey(City, on_delete=models.CASCADE, related_name="cities")
Yes, Postgres uses what it calls a sequence 10 object to track the next PK to assign. If you restore the database and that restore process doesn’t include the related sequence object, you end up in exactly this situation.
You can use the ALTER SEQUENCE 47 statement (with the RESTART parameter) in psql to reset the sequence to the desired value.
You also want to ensure that your pg_dump command is written to include all sequences in your backup to prevent this from happening in the future.