Django flush выдает ошибку «cannot truncate a table referenced in a foreign key constraint».
Рассмотрите следующие models.py
:
from django.db import models
class Foo(models.Model):
bars = models.ManyToManyField(
"Bar",
blank=True
)
class Bar(models.Model):
foos = models.ManyToManyField(
"Foo",
blank=True,
through="Foo_bars"
)
и связанная с этим миграция:
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = []
operations = [
migrations.CreateModel(
name="Bar",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
],
),
migrations.CreateModel(
name="Foo",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("bars", models.ManyToManyField(blank=True, to="demo.bar")),
],
),
migrations.AddField(
model_name="bar",
name="foos",
field=models.ManyToManyField(blank=True, to="demo.foo"),
),
]
Бег
python manage.py migrate && python manage.py flush --no-input --traceback
выдает следующую трассировку
File "/opt/venv/lib/python3.13/site-packages/psycopg/cursor.py", line 97, in execute
raise ex.with_traceback(None)
django.db.utils.NotSupportedError: cannot truncate a table referenced in a foreign key constraint
DETAIL: Table "demo_bar_foos" references "demo_foo".
HINT: Truncate table "demo_bar_foos" at the same time, or use TRUNCATE ... CASCADE.
Как решить эту проблему? Как добавить каскад?
Полный воспроизводимый пример доступен по адресу https://github.com/rgaiacs/django-flush-problem.
Это не то, как вы определяете ManyToManyField
. Если вы определите ManyToManyField
в одной из моделей, вы сможете получить к ней доступ в другом направлении благодаря foo_bars
, так что:
from django.db import models
class Foo(models.Model):
bars = models.ManyToManyField('Bar', blank=True, related_name='foos')
class Bar(models.Model):
# foos = models.ManyToManyField(
# "Foo",
# blank=True,
# through="Foo_bars"
# )
pass
Таким образом, он позволяет работать с my_bar.foos.all()
благодаря related_name=...
[Django-doc].