Django 模型只允许多次

Django model allow only once in many

请原谅标题,但我不确定如何用文字表达。 我有一个模型“卡”和一个模型“计算机”:

class card(models.Model):
name=models.CharField(
    verbose_name = 'Name',
    max_length=50,
    null=True,
    blank=True,
)
serial=models.CharField(
    verbose_name = 'Serial',
    max_length=50,
    null=True,
    blank=True,
)

class computer(models.Model):
name=models.CharField(
    verbose_name = 'Name',
    max_length=50,
    null=True,
    blank=True,
)
slot1 = models.OneToOneField(
    'card',
    related_name='cardslot1',
    on_delete=models.SET_NULL,
    null=True,
    blank=True,
    verbose_name = 'Slot 1',
)
slot2 = models.OneToOneField(
    'card', 
    related_name='cardslot2',
    on_delete=models.SET_NULL,
    null=True,
    blank=True,
    verbose_name = 'Slot 2',
)

(当然这个电脑型号是无效的) 这些卡是独一无二的,只允许在任何计算机的一个插槽中使用。实现这一目标的最佳方法是什么?我在考虑 in-between table,比如

卡片 n-1 卡片电脑 n-1 电脑

但我希望有更好的方法我现在还没有看到。 谢谢

为您的模型使用 constraints 元选项。

from django.db import models
from django.db.models import CheckConstraint, Q

class computer(models.Model)

    name=models.CharField(
        verbose_name = 'Name',
        max_length=50,
        null=True,
        blank=True,
    )
    slot1 = models.OneToOneField(
        'card',
        related_name='cardslot1',
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name = 'Slot 1',
    )
    slot2 = models.OneToOneField(
        'card', 
        related_name='cardslot2',
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name = 'Slot 2',
    )

    class Meta:
        constraints = [
            CheckConstraint(
                check = ~Q(slot1=slot2), 
                name = 'unique_slot',
            ),
        ]

Yagus 的答案是正确的,但这里有一个纯模型替代方案。

class Card(models.Model):
    name = models.CharField(
        verbose_name='Name',
        max_length=50,
        null=True,
        blank=True,
    )
    serial = models.CharField(
        verbose_name='Serial',
        max_length=50,
        null=True,
        blank=True,
    )


class Slot(models.Model):
    card = models.OneToOneField(Card,
        on_delete=models.SET_NULL,
        null=True,
        blank=True
    )
    computer = models.ForeignKey('Computer',
        on_delete=models.CASCADE, 
        related_name='slots'
    )


class Computer(models.Model):
    name = models.CharField(
        verbose_name='Name',
        max_length=50,
        null=True,
        blank=True,
    )

这样您就可以灵活地在管理面板中为每台计算机设置 add/change 个插槽,恕我直言,这些内容比限制条件更具可读性。

由于相关名称,您仍然可以访问 Computer.slots