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