Модель Django позволяет только один раз во многих

Прошу прощения за название, но я не уверен, как выразить это словами. У меня есть модель "карта" и модель "компьютер":

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',
)

(Разумеется, что данная модель компьютера недействительна) Карты уникальны и должны быть разрешены к использованию только в одном слоте - любого компьютера. Каков наилучший способ достичь этого? Я думал о промежуточной таблице, что-то вроде

card n-1 cardcomputer n-1 computer

но я надеюсь, что есть лучший способ, который я сейчас не вижу. Спасибо

Используйте мета-опцию constraints для вашей модели.

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

class computer(models.Model)

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

Ответ Ягуса правильный, но вот альтернатива чистой модели.

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,
    )

Таким образом, у вас есть возможность гибко добавлять/изменять слоты для каждого компьютера в панели администратора, и все имхо более читабельно, чем ограничения.

Вы все еще можете получить доступ к Computer.slots благодаря связанному имени.

Вернуться на верх