Django моделирует БД поставщика с различными продуктами. Не удается определить таблицу отношения supplier_product

У меня есть проект Django, в котором есть поставщик и несколько продуктов, которые сильно отличаются друг от друга. Продукты называются ресурсами. Поскольку они очень разные, я не могу иметь таблицу продуктов и поэтому не знаю, как сделать модель supplier_product, через которую я могу получить все продукты, связанные с поставщиком.

Вот примеры моделей:

class Company(models.Model):
    ...... #some common fields

class Supplier(Company):
    # delivery_time = "3 weeks"
    delivery_time = models.CharField(max_length=255, blank=True, null=True)
    # minimun order quantity
    MOQ = models.FloatField(blank=True, null=True)
    moq_unit = models.CharField(max_length=255, blank=True, null=True)
    billing_address = models.ForeignKey(
        ....
    )
    shipping_address = models.ForeignKey(
        ....
    )

В поставщике есть еще несколько полей. Вот ресурсы:

class Resource(models.Model):
    ....... #some common fields

class Part(Resource):
    code = models.CharField(max_length=255, unique=True, blank=True, null=True)
    supplier = models.ForeignKey(
        Company,
        related_name="supplier_part",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
    )
    country = models.CharField(max_length=255, blank=True, null=True)

class Fuel(Resource):
    code = models.CharField(max_length=255, unique=True, null=True, blank=True)
    color = models.CharField(max_length=255)
    supplier = models.ForeignKey(
        Company,
        related_name="supplier_fuel",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
    )

Теперь проблема в том, как я могу сделать модель SupplierProduct с полем (поставщик, продукт). Которую я могу использовать для получения всех продуктов от поставщика. В этом случае я удалю поставщика из модели Fuel и Part.

Нужно ли мне перестроить все модели. Какая конструкция лучше для этого случая.

Спасибо.

Можно ли использовать Generic Foreign Keys? Они используют content_type и object_id для сопоставления одного и того же поля с разными моделями:

https://docs.djangoproject.com/en/4.0/ref/contrib/contenttypes/#generic-relations

Как упоминал C14L, вы можете использовать GenericForeignKey для создания отношений с другой моделью. Однако GenericForeignKeys имеют свои проблемы. Они не создают обратных отношений. Поэтому вы не сможете сделать, например, [sr.supplier for sr in Part.supplier_resources], однако это позволит вам избавиться от родительской модели Resource. То, что у вас есть с родительской моделью ресурсов, я считаю правильной идеей. Я бы предложил в модели ресурсов добавить поле под названием child_model_name

class Resource(models.Model):
    child_model_name = models.TextField()
    some_attr = models.CharField(max_length=255, blank=True, null=True)

где child_model_name = 'part' и т.д.

Тогда в вашей модели SupplierResource Model у вас есть

class SupplierResource(models.Model):
    supplier = models.ForeignKey(Supplier, ..., related_name="supplier_resources")
    resource = models.ForeignKey(Resource, ..., related_name="supplier_resources")

Здесь django создает для вас таблицу Resource, которая содержит все поля для ресурса. Он также создает для вас таблицу под названием Part с полями, специфичными для части, которая имеет отношение OneToOne к Resource.

Теперь вы можете сделать следующее:

parts = Part.objects.filter(supplier_rescources__supplier=supplier)

Или получить разные типы ресурсов в одном списке (деталь, топливо и т.д.).

resources = Resource.objects.filter(supplier_resources__supplier=supplier)

[getattr(resource, resource.child_model_name) for resource in resources]

Вы можете рассмотреть возможность использования django-polymorphic.

Если вы сделаете это, просто позвольте Resource наследоваться от PolymorphicModel следующим образом:

from polymorphic.models import PolymorphicModel

class Supplier(models.Model):
    delivery_time = models.CharField(max_length=255, blank=True, null=True)
    minimum_order_quantity = models.FloatField(blank=True, null=True)


class Resource(PolymorphicModel):
    code = models.CharField(max_length=255, unique=True, blank=True, null=True)
    country = models.CharField(max_length=255, blank=True, null=True)


class Part(Resource):
    some_attr = models.CharField(max_length=255, blank=True, null=True)


class Fuel(Resource):
    some_other_attr = models.CharField(max_length=255, blank=True, null=True)

Затем вы можете создать модель SupplierResource следующим образом:

class SupplierResource(models.Model):
    supplier = models.ForeignKey(Supplier, on_delete=models.CASCADE)
    resource = models.ForeignKey(Resource, on_delete=models.CASCADE)

Или, отношения "многие ко многим" между поставщиком и ресурсом:

class Supplier(models.Model):
    delivery_time = models.CharField(max_length=255, blank=True, null=True)
    minimum_order_quantity = models.FloatField(blank=True, null=True)
    resources = models.ManyToManyField(Resource, related_name="suppliers")
Вернуться на верх