torinaブログ

DjangoとBootstrap4で作成したブログ
Python, Django, Kivy, Bootstrap, Apache等のメモです
ソースコード

Django、モデルのフィールドで一意な組み合わせ

Python Django Django
約146日前 2016年10月4日3:38
以下のようなモデルがあります。一日の食事メニューです。
名前と、朝食と、昼食と、夕食を指定します。
from django.db import models


class Menu(models.Model):
    """一日の食事のメニュー"""

    name = models.CharField(max_length=255)
    morning = models.CharField(max_length=255)
    lunch = models.CharField(max_length=255)
    dinner = models.CharField(max_length=255)

    def __str__(self):
        return self.name



データを投入してみましょう。


名前だけ変えて、前と同様のメニューを追加できてしまいます。



このような場合に、朝食、昼食、夕食の組み合わせが同じならエラーにしたいとします。
そのような場合、Modelを以下のようにします。
from django.db import models


class Menu(models.Model):
    """一日の食事のメニュー"""

    name = models.CharField(max_length=255)
    morning = models.CharField(max_length=255)
    lunch = models.CharField(max_length=255)
    dinner = models.CharField(max_length=255)

    # 増えた
    class Meta:
        unique_together = ('morning', 'lunch', 'dinner')

    def __str__(self):
        return self.name



すると...


期待した動作です!



以下のように、複数指定することも可能です。
from django.db import models


class Menu(models.Model):
    """食事のメニュー"""

    name = models.CharField(max_length=255)
    morning_main = models.CharField(max_length=255)
    morning_dessert = models.CharField(max_length=255)

    dinner_main = models.CharField(max_length=255)
    dinner_dessert = models.CharField(max_length=255)

    class Meta:
        unique_together = (
            ('morning_main', 'morning_dessert'),
            ('dinner_main', 'dinner_dessert'),
        )

    def __str__(self):
        return self.name




morning_mainとmorning_dessertが前と同じでNG




dinner_mainとdinner_dessertが前と同じでNG




ForeignKeyやOneToOneFieldも同様に可能です。
ManyToManyは、ダメです。
from django.db import models


class MorningFood(models.Model):
    """朝ごはん"""

    name = models.CharField(max_length=255)

    def __str__(self):
        return self.name


class DinnerFood(models.Model):
    """夜ごはん"""

    name = models.CharField(max_length=255)

    def __str__(self):
        return self.name


class Menu(models.Model):
    """食事のメニュー"""

    name = models.CharField(max_length=255, blank=True, null=True)
    morning = models.ForeignKey(MorningFood, max_length=255, blank=True, null=True)
    dinner = models.ForeignKey(DinnerFood, max_length=255, blank=True, null=True)

    class Meta:
        unique_together = ('morning', 'dinner')

    def __str__(self):
        return self.name