【问题标题】:Django: UniqueConstraint validator does work neither for model nor for intermediate modelDjango:UniqueConstraint 验证器既不适用于模型也不适用于中间模型
【发布时间】:2021-10-03 17:36:00
【问题描述】:

我的项目基本上是一个平台,人们可以在其中发布带有标签(例如早餐或晚餐)和配料(胡萝卜、牛奶等)的食谱。

我想为配方实现唯一约束,这样用户就不能创建一个具有两个相同标签或成分的约束。因此,我决定为此使用 django UniqueConstraint 验证器,但即使迁移也不适用,django 说:“未检测到更改”。

from django.db import models
from django.contrib.auth import get_user_model
from django.core.validators import MinValueValidator, MaxValueValidator


User = get_user_model()


class Recipe(models.Model):
    author = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='recipes',
        verbose_name='автор',
    )

    name = models.CharField(
        max_length=200,
        verbose_name='имя',
    )

    image = models.ImageField(
        max_length=4096,
        upload_to='images/%Y-%m-%d',
        verbose_name='фото',
    )

    text = models.TextField(verbose_name='описание')

    ingredients = models.ManyToManyField(
        'Ingredient',
        through='RecipeIngredient',
        verbose_name='ингредиет',
    )

    tags = models.ManyToManyField(
        'Tag',
        through='RecipeTag',
        verbose_name='тэг',
    )

    cooking_time = models.IntegerField(
        default=60,
        validators=(
            MinValueValidator(1),
            MaxValueValidator(44640)
        ),
        verbose_name='время приготовления (в минутах)',
    )

    creation_date = models.DateTimeField(
        auto_now=True,
        verbose_name='дата создания рецепта',
    )

    class Meta:
        verbose_name = 'рецепт'
        verbose_name_plural = 'рецепты'

    def __str__(self):
        return f'Рецепт - id: {self.id}, имя: {self.name}.'


class Tag(models.Model):
    name = models.CharField(
        max_length=256,
        verbose_name='имя',
    )
    color = models.CharField(
        max_length=64,
        verbose_name='цвет',
    )
    slug = models.SlugField(
        max_length=64,
        verbose_name='слаг',
    )

    class Meta:
        verbose_name = 'тэг'
        verbose_name_plural = 'тэги'

    def __str__(self):
        return f'Тэг - id: {self.id}, имя: {self.name}.'


class Ingredient(models.Model):
    name = models.CharField(
        max_length=256,
        verbose_name='имя',
    )

    measurement_unit = models.CharField(
        max_length=32,
        verbose_name='еденица измерения',
    )

    class Meta:
        verbose_name = 'ингредиент'
        verbose_name_plural = 'ингредиенты'

    def __str__(self):
        return f'Игредиент - id: {self.id}, имя: {self.name}.'


class RecipeIngredient(models.Model):
    """Intermediate "join" table for a relation between a recipe
    and an ingredient. Additionaly implements <amount> field.
    """
    recipe = models.ForeignKey(
        'Recipe',
        on_delete=models.CASCADE,
        verbose_name='рецепт',
    )

    ingredient = models.ForeignKey(
        'Ingredient',
        on_delete=models.CASCADE,
        verbose_name='игредиент',
    )

    amount = models.IntegerField(
        default=1,
        validators=(
            MinValueValidator(1),
            MaxValueValidator(44640)
        ),
        verbose_name='количество',
    )

    class Meta:
        verbose_name = 'отношение рецепта к ингредиенту'
        verbose_name_plural = 'отношение рецепта к ингредиентам'

    def __str__(self):
        return f'РецептИнгредиент - id: {self.id}.'


class RecipeTag(models.Model):
    """Intermediate "join" table for a relation between a recipe and tag.
    """
    recipe = models.ForeignKey(
        'Recipe',
        on_delete=models.CASCADE,
        verbose_name='рецепт',
    )

    tag = models.ForeignKey(
        'Tag',
        on_delete=models.CASCADE,
        verbose_name='тэг',
    )

    class Meta:
        verbose_name = 'отношение рецепта к тэгу'
        verbose_name_plural = 'отношение рецепта к тэгам'

        models.UniqueConstraint(
            fields=('recipe__id', 'tag__id'),
            name='recipe_tag_unique_constraint'
        )

    def __str__(self):
        return f'РецептТэг - id: {self.id}.'

【问题讨论】:

  • 已决定将 UniqueConstraint 放入 RecipeTag 中间模型,但即使这样也无济于事。
  • 你只是加错了,RecipeTag模型确实是正确的模型,但是不能简单的写成Meta类中的表达式,需要定义一个变量命名为constraints

标签: python django django-models


【解决方案1】:

您应该将这些添加到 Meta 选项中名为 constraints 的变量中,因此:

class RecipeTag(models.Model):
    # &vellip;

    class Meta:
        verbose_name = 'отношение рецепта к тэгу'
        verbose_name_plural = 'отношение рецепта к тэгам'

        #   &downarrow; add this to a variable named constraints
        constraints = [
            models.UniqueConstraint(
                fields=('recipe_id', 'tag_id'),
                name='recipe_tag_unique_constraint'
            )
        ]

约束只能跨越RecipeTag的表,所以recipe__idtag__id没有多大意义,可以使用recipe_idtag_id

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-17
    • 1970-01-01
    相关资源
    最近更新 更多