Установка уникального констрата только для прямых родителей (Django MPTT)
Я создал модель "Категория" с помощью Django MPTT:
from django.db import models
from mptt.models import MPTTModel, TreeForeignKey
class Category(MPTTModel):
name = models.CharField(max_length=50)
parent = TreeForeignKey("self", on_delete=models.CASCADE, null=True, blank=True, related_name="children")
Но, используя эту модель "Категория" , я могу добавить дублирующиеся данные "3F" и "4F" под "Здание B" (прямой родитель), как показано ниже:
- USA
- Нью-Йорк
- Здание А
- 3F
- 4F
- Здание B
- 3F // Здесь
- 3F // Здесь
- 4F // Здесь
- 4F // Здесь
- Здание А
- Нью-Йорк
Поэтому я добавил "unique=True" к полю "name" в модели "Category":
from django.db import models
from mptt.models import MPTTModel, TreeForeignKey
class Category(MPTTModel): // Here
name = models.CharField(max_length=50, unique=True)
parent = TreeForeignKey("self", on_delete=models.CASCADE, null=True, blank=True, related_name="children")
Но с этой моделью "Категория", я больше не мог добавить данные "3F" и "4F" под "Здание B", потому что "3F" и "4F" уже существуют под "Здание A" в "Категория". Я обнаружил, что добавление "unique=True" к полю "name" в модели "Category" устанавливает Unique Constrait в всей модели "Category" о поле "name". Поэтому, если есть одинаковые значения "name", такие как "F3" и "F4" где-либо в "Category", мы не можем добавить такие же значения "имени", как "F3" и "F4" в любом месте "Категории". Короче говоря, если "3F" и "4F" уже существуют где-либо в "Категория", мы не можем добавить "3F" и "4F" куда-либо в "Категория":
- USA
- Нью-Йорк
- Здание А
- 3F // Так как уже существует
- 4F // Потому что уже существует
- Здание B
- 3F // Так нельзя добавить
- 3F // Так что нельзя добавить
- 4F // Так что нельзя добавить
- 4F // Так что нельзя добавить
- Здание А
- Нью-Йорк
Это мой желаемый результат, не позволяющий дублировать данные только под прямыми родителями:
- USA
- Нью-Йорк
- Здание А
- 3F
- 4F
- Здание B
- 3F
- 4F
- Здание А
- Нью-Йорк
Есть ли способ установить Unique Constrait только для прямых родителей?
Удалите "unique=True" из поля "name" :
name = models.CharField(max_length=50) # "unique=True" is removed
Затем добавьте этот код в модель "Категория" :
class Meta:
unique_together = [['name', 'parent']]
Вот полный код:
from django.db import models
from mptt.models import MPTTModel, TreeForeignKey
class Category(MPTTModel): # "unique=True" is removed
name = models.CharField(max_length=50)
parent = TreeForeignKey("self", on_delete=models.CASCADE, null=True, blank=True, related_name="children")
class Meta:
unique_together = [['name', 'parent']]
Приведенный выше код реализует то, что вы желаете:
- USA
- Нью-Йорк
- Здание А
- 3F // Даже если уже существует
- 4F // Даже если уже существует
- Здание B
- 3F // 〇 Но разрешено добавить
- 3F // ✖ Не разрешено добавлять
- 4F // 〇 Но разрешено добавить
- 4F // ✖ Не разрешено добавлять
- Здание А
- Нью-Йорк
Но только верхний уровень (уровень 1) по-прежнему не имеет Unique Constraint поэтому верхний уровень (уровень 1) по-прежнему может иметь дублированные данные, как показано ниже:
- USA // Верхний уровень (уровень 1) все еще не имеет Unique Constraint.
- USA // Таким образом, верхний уровень (уровень 1) все еще может иметь дублированные данные.
- USA
- Нью-Йорк
- Здание А
- 3F // Даже если уже существует
- 4F // Даже если уже существует
- Здание B
- 3F // 〇 Но разрешено добавить
- 3F // ✖ Не разрешено добавлять
- 4F // 〇 Но разрешено добавить
- 4F // ✖ Не разрешено добавлять
- Здание А
- Нью-Йорк
На самом деле, я пробовал некоторые решения, чтобы добавить Unique Constraint в the top level(level 1), но не смог, поэтому я рекомендую не использовать the top level(level 1) для хранения нужных данных, которые вы на самом деле используете для своего приложения. Поэтому вместо этого, для верхнего уровня (уровень 1) просто добавьте "Root", "Top" или что-либо, что показывает "This is the top level (level 1)" как показано ниже:
- Root // Здесь
- USA
- Нью-Йорк
- Здание А
- 3F // Даже если уже существует
- 4F // Даже если уже существует
- Здание B
- 3F // 〇 Но разрешено добавить
- 3F // ✖ Не разрешено добавлять
- 4F // 〇 Но разрешено добавить
- 4F // ✖ Не разрешено добавлять
- Здание А
- Нью-Йорк
- USA