Как вставить данные в определенную категорию, если она не определена в поле модели Django?

У меня есть проект Django, в котором я создал две модели: Category и Shop. Каждый магазин может иметь только одну категорию. Если я не определил категорию магазина, я хочу, чтобы она была в секции Without category в шаблоне. Как мне установить значение по умолчанию?

Мои модели:

class Category(models.Model):
    name = models.CharField(max_length=100)
    position = models.IntegerField(unique=True)

    def __str__(self):
        return f'{self.name}'


class DemoShop(models.Model):
    title = models.CharField(max_length=100)
    category = models.ForeignKey(Category, on_delete=models.CASCADE,
                             related_name='Cat')

    def __str__(self):
        return f"{self.title}"

Когда я пишу:

category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='Cat', default='Without category')

Это не имеет никакого эффекта в моей базе данных и не отображается в разделе Without category в моем шаблоне. Если я не поместил магазин в определенную категорию, я хочу, чтобы он отображался в Without category на странице, например:

Products:
    -lorem;
    -testshop;
Watch:
    -keram;
    -pollop;
Without category:
    (All shop what I haven't define a category in DB)

Значением по умолчанию для поля модели ForeignKey является первичный ключ экземпляра модели, на который оно ссылается (если только вы не установите to_field в вашем ForeignKey значение, указывающее на какое-то другое поле ссылающейся модели). Обратитесь к https://docs.djangoproject.com/en/4.1/ref/models/fields/#django.db.models.Field.default

Если вы хотите установить для DemoShop категорию по умолчанию "Без значения", вы можете создать метод класса, который создает/возвращает, если существует Category с именем "Без категории" (я произвольно выбрал значение аргумента position=5 для метода get_or_create):

class Category(models.Model):
   name = models.CharField(max_length=100)
   position = models.IntegerField(unique=True)

   def __str__(self):
       return f'{self.name}'

   @classmethod
   def get_default_pk(cls):
       obj, created = cls.objects.get_or_create(
           name="Without category",
           position=5
       )
       return obj.pk

Затем вы можете использовать определенный classmethod для получения вашей фиктивной категории с именем "Без категории" (при условии, что модели Category и DemoShop определены в одном файле models.py:

).
class DemoShop(models.Model):
    title = models.CharField(max_length=100)
    category = models.ForeignKey(Category, on_delete=models.CASCADE,
                             related_name='Cat', default=Category.get_default_pk())

Если по какой-то причине вы действительно не можете/не хотите вставлять фиктивную категорию с именем "Без категории" в вашу базу данных, вы можете установить поле category в вашей модели DemoShop, чтобы оно допускало пустой ввод и было nullable, а затем определить пользовательский метод как getter для связанного имени категории:

class DemoShop(models.Model):
    title = models.CharField(max_length=100)
    category = models.ForeignKey(Category, on_delete=models.CASCADE,
                             related_name='Cat', blank=True, null=True)

    def __str__(self):
        return f"{self.title}"

    def get_category_name(self):
        if self.category is None:
            return "Without category"
        return self.category.name
        

Затем используйте этот метод в своем шаблоне, чтобы получить название категории для экземпляров DemoShop.

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