Django ManyToMany с количеством
У меня возникла небольшая проблема при попытке смоделировать в Django нечто, что я концептуально представил. Я знаю, что это отношение "многие ко многим"... однако оно как бы самореферентно и имеет количественное значение. Я представляю, что для этого нужна некая модель моста, которая у меня есть, но как мне теперь редактировать ее на странице администратора?
Что у меня есть, так это класс Component. Например, "винт" - это компонент, и для его создания не требуется никаких других компонентов. Но так же и "корпус" требует 4 винта, чтобы удержать его вместе. Затем этот корпус может войти в коллектор, а коллектор может войти в автомобиль и т.д.
Каждая вещь может быть компонентом другой вещи, если это имеет смысл. Я ввел все винты, болты и т.д. в базу данных через страницу редактирования администратора. Но теперь я хочу начать вводить более сложные сборки. Я могу просто создать класс Assembly, который содержит список одного или нескольких компонентов. Но я все еще остаюсь с проблемой, что эта сборка может войти в более крупную сборку ноль или более раз.
Как мне это представить?
в настоящее время у меня
class ComponentBase(models.Model)
name = models.CharField(max_length=255)
class Meta:
abstract = True
ordering = ['name']
class ItemComponent(ComponentBase):
components = models.ManyToManyField('ItemComponentWithQuantity', blank=True)
class ItemComponentWithQuantity(ItemComponent):
quantity = models.IntegerField(default=1)
Предполагая, что это правильный способ моделирования (так ли это?), как мне заставить форму редактирования администратора установить это как электронную таблицу или список?
like
name: manifold assembly
components:
10x screws
10x bolts
1x assembly housing
В поле компонентов должны отображаться только те, которые были добавлены, и их количество. Не все возможные компоненты.
Изначально в моей модели было установлено, что components = models.ManyToManyField('ItemComponent', blank=True). Это привело к тому, что в панели администратора появился список всех существующих ItemComponents, как и ожидалось, но, очевидно, без количества.
Добавив класс ItemComponentWithQuantity, я изменил manytomanyfield на ItemComponentWithQuantity. Но теперь поле компонентов администратора пусто.
Надеюсь, что я все правильно понимаю. Я не уверен, что делаю неправильно.
заранее спасибо. EK
Наследование, которое вы делаете, делает это слишком сложным. Вы можете смоделировать это по-другому. Измените ComponentBase
на базовую модель Model.Model (не абстрактную) с именем Assembly
. Измените ItemComponent
на просто Component
. И наконец, измените ItemComponentWithQuantity
на AssemblyComponent
.
В AssemblyComponent
должны быть поля
assembly
- Иностранный ключ кAssembly
component
- ForeignKey toComponent
quantity
- IntegerField
Создайте другую модель AssemblyAssembly
с полями
assembly_parent
- Иностранный ключ кAssembly
assembly_child
- ForeignKey toAssembly
quantity
- IntegerField
Затем вы создадите либо табличный, либо стековый встроенный администратор (в зависимости от желаемого пользовательского опыта) для AssemblyComponent
и AssemblyAssembly
. Обязательно установите fk_name в AssemblyAssembly
для указания на assembly_parent
в качестве fk_name, поскольку у вас есть два поля внешнего ключа, ссылающиеся на одну и ту же модель. Вы можете использовать raw_id_field
для assembly_child
, если в системе будет много возможных сборок. Используйте инлайн-администраторы для Assembly
админа.
- Подробнее о встроенных администраторах см: https://docs.djangoproject.com/en/4.0/ref/contrib/admin/#inlinemodeladmin-objects .
Это даст вам примерно тот пользовательский интерфейс администратора, который вы хотите, за исключением того, что ссылки на компоненты и сборки будут находиться в отдельных встроенных админках.
Для этого можно просто иметь одну модель и сделать ее рекурсивной моделью, где она находится в отношениях с самой собой
component = models.ForeignKey('self', on_delete=models.CASCADE)
я также советую вам добавить дополнительное поле для количества вместо того, чтобы создавать целую модель для этого. Надеюсь, это сработает.