Ограничение Django FOREIGN KEY не работает при добавлении ассоциации Many To Many к экземпляру во второй раз
В настоящее время я пытаюсь освоить фреймворк django framework. При попытке подключиться к экземплярам объектов через ManyToManyField происходит что-то очень странное.
Запуск со свежей Базы Данных (создание объекта в Shell, но та же проблема в Code): Когда я создаю первый объект (Product), все работает нормально. Я создаю объект и добавляю другой объект (ProductTag) в поле ManyToManyField первого.
Теперь возникает проблема: после того, как я сделал это, и попробовал повторить то же самое с разными экземплярами (или теми же самыми, что и в прошлый раз), я получаю django.db.utils.IntegrityError, который говорит "FOREIGN KEY constraint failed"
Вход/выход консоли проблемы:
(InteractiveConsole)
>>> from onlineShop.apps.products.models import Product, ProductTag
>>> from django.contrib.auth.models import User
>>> from onlineShop.apps.profiles.models import Profile
>>> p = Profile.objects.first()
>>> t = ProductTag.objects.create(name="outdoor", name_verbose="Outdoor")
>>> p.save()
>>> p
<Profile: superuser>
>>> t.save()
>>> t
<ProductTag: Outdoor>
>>> prod1 = Product.objects.create(vendor=p, title="test1", price=123.42, description="test1-desc")
>>> prod1.save()
>>> prod1
<Product: test1>
>>> prod2 = Product.objects.create(vendor=p, title="test2", price=223.42, description="test2-desc")
>>> prod2.save()
>>> prod2
<Product: test2>
>>> prod1.tags.add(t)
>>> prod1.save()
>>> prod1
<Product: test1>
>>> prod2.tags.add(t)
Traceback (most recent call last):
File "C:\Users\lukas\.virtualenvs\Django_Shop-2dmIjN-v\lib\site-packages\django\db\backends\base\base.py", line 267, in _commit
return self.connection.commit()
sqlite3.IntegrityError: FOREIGN KEY constraint failed
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "C:\Users\lukas\.virtualenvs\Django_Shop-2dmIjN-v\lib\site-packages\django\db\models\fields\related_descriptors.py", line 1047, in add
with transaction.atomic(using=db, savepoint=False):
File "C:\Users\lukas\.virtualenvs\Django_Shop-2dmIjN-v\lib\site-packages\django\db\transaction.py", line 255, in __exit__
connection.commit()
File "C:\Users\lukas\.virtualenvs\Django_Shop-2dmIjN-v\lib\site-packages\django\utils\asyncio.py", line 26, in inner
return func(*args, **kwargs)
File "C:\Users\lukas\.virtualenvs\Django_Shop-2dmIjN-v\lib\site-packages\django\db\backends\base\base.py", line 291, in commit
self._commit()
File "C:\Users\lukas\.virtualenvs\Django_Shop-2dmIjN-v\lib\site-packages\django\db\backends\base\base.py", line 266, in _commit
with self.wrap_database_errors:
File "C:\Users\lukas\.virtualenvs\Django_Shop-2dmIjN-v\lib\site-packages\django\db\utils.py", line 91, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "C:\Users\lukas\.virtualenvs\Django_Shop-2dmIjN-v\lib\site-packages\django\db\backends\base\base.py", line 267, in _commit
return self.connection.commit()
django.db.utils.IntegrityError: FOREIGN KEY constraint failed
Я понятия не имею, что я делаю неправильно. После небольшого тестирования я обнаружил, что иногда связывание более двух объектов без удаления базы данных может работать. Но я не нашел причины, почему иногда это работает... Случай, когда несколько сохранений сработали:
>>> prod2.tags.add(t)
Traceback (most recent call last):
File "C:\Users\lukas\.virtualenvs\Django_Shop-2dmIjN-v\lib\site-packages\django\db\backends\base\base.py", line 267, in _commit
return self.connection.commit()
sqlite3.IntegrityError: FOREIGN KEY constraint failed
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "C:\Users\lukas\.virtualenvs\Django_Shop-2dmIjN-v\lib\site-packages\django\db\models\fields\related_descriptors.py", line 1047, in add
with transaction.atomic(using=db, savepoint=False):
File "C:\Users\lukas\.virtualenvs\Django_Shop-2dmIjN-v\lib\site-packages\django\db\transaction.py", line 255, in __exit__
connection.commit()
File "C:\Users\lukas\.virtualenvs\Django_Shop-2dmIjN-v\lib\site-packages\django\utils\asyncio.py", line 26, in inner
return func(*args, **kwargs)
File "C:\Users\lukas\.virtualenvs\Django_Shop-2dmIjN-v\lib\site-packages\django\db\backends\base\base.py", line 291, in commit
self._commit()
File "C:\Users\lukas\.virtualenvs\Django_Shop-2dmIjN-v\lib\site-packages\django\db\backends\base\base.py", line 266, in _commit
with self.wrap_database_errors:
File "C:\Users\lukas\.virtualenvs\Django_Shop-2dmIjN-v\lib\site-packages\django\db\utils.py", line 91, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "C:\Users\lukas\.virtualenvs\Django_Shop-2dmIjN-v\lib\site-packages\django\db\backends\base\base.py", line 267, in _commit
return self.connection.commit()
django.db.utils.IntegrityError: FOREIGN KEY constraint failed
>>> t2 = ProductTag.objects.create(name="garden", name_verbose="Garden")
>>> t2.save # TYPO :)
<bound method Model.save of <ProductTag: Garden>>
>>> prod2.tags.add(t2)
>>> prod1.tags.add(t2)
>>> prod2.save()
>>> prod1.save()
>>> prod3 = Product.objects.create(vendor=p, title="test3", price=323.42, description="test3-desc")
>>> prod3.save()
>>> prod3.tags.add(t)
Traceback (most recent call last):
File "C:\Users\lukas\.virtualenvs\Django_Shop-2dmIjN-v\lib\site-packages\django\db\backends\base\base.py", line 267, in _commit
return self.connection.commit()
sqlite3.IntegrityError: FOREIGN KEY constraint failed
Вот некоторые таблицы из базы данных после попытки, описанной выше:
Таблица связи продуктов и меток
models.py:
from django.db import models
from onlineShop.apps.profiles.models import Profile
class ProductTag(models.Model):
name = models.CharField(max_length=20)
name_verbose = models.CharField(max_length=40)
associated_tags = models.ManyToManyField(
'self',
symmetrical=True
)
def __str__(self):
return self.name_verbose
class Product(models.Model):
vendor = models.ForeignKey(
Profile,
on_delete=models.CASCADE
)
title = models.CharField(max_length=300)
price = models.DecimalField(decimal_places=2, max_digits=8)
description = models.TextField(blank=True)
image = models.URLField(blank=True)
listing_date = models.DateField(auto_now=True)
is_private = models.BooleanField(default=False)
tags = models.ManyToManyField(
ProductTag,
symmetrical=True
)
def __str__(self):
return self.title
def has_tag(self, tag):
return self.tags.filter(pk=tag.pk).exists()
Я не совсем уверен, какие файлы могут быть релевантными, кроме модели. Если это поможет: вот файл forms.py
from django import forms
from .models import Product, ProductTag
class ProductCreateForm(forms.ModelForm):
def clean(self):
cleaned_data = super().clean()
if cleaned_data.get('price') < 0:
self.add_error('price', "Price has to be positive!")
class Meta:
model = Product
fields = ['title', 'price', 'description', 'image', 'is_private', 'tags']
#widgets = {'tags': forms.ModelMultipleChoiceField(ProductTag.objects.all())}
Большое спасибо! Я с нетерпением жду ваших ответов :)