Ограничение 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())}

Большое спасибо! Я с нетерпением жду ваших ответов :)

Вернуться на верх