Цены нашего бизнеса зависят от множества параметров, и теперь мы хотим ввести еще один возможный параметр M2M в существующую настройку в Django.
Для этого у нас есть существующая таблица для расчета цены, которая имеет ограничение unique_together
для всех полей, кроме price_field
. Извинения за общее/буквенное именование в примере.
class PricingTable(models.Model):
a = models.ForeignKey(A, on_delete=models.CASCADE)
price = MoneyField()
b = ArrayField(models.CharField(choices=CHOICES))
c = models.ForeignKey(C, on_delete=models.CASCADE)
class Meta:
ordering = ("a",)
unique_together = ("a", "b", "c")
def validate_b(self):
# b can't be empty
if not len(self.b) >= 1:
raise ValueError
# each element in b needs to be unique
if not len(self.b) == len(set(self.b)):
raise ValueError
# each element in b needs to be unique together with a & c
for i in self.b:
query = PricingTable.objects.filter(
a=self.a, c=self.c, b__contains=[i]
).exclude(pk=self.pk)
if query.count() > 0:
raise ValueError
def save(self, *args, **kwargs):
self.validate_b()
return super().save(*args, **kwargs)
Я хочу ввести в эту таблицу еще один параметр, который должен быть уникальным - вместе с неценовыми параметрами (a
, b
& c
).
d = models.ManyToManyField("x.D", related_name="+")
Каждый элемент в списке b
должен быть уникальным вместе с a
& c
.
Проблема с вышесказанным заключается в том, что функцию validate_b
необходимо обновить до возможно сложной функции с тяжелыми запросами к БД. Наряду с этим, Django не предоставляет прямой путь для обеспечения уникального единения многих со многими полями.
Итак, есть ли другой подход, который я, вероятно, должен попробовать? А through
столик возможно? Но тогда, что все поля я должен включить в сквозную таблицу? Все неценовые поля? Или я должен перестать мечтать о том, чтобы иметь поле "многие ко многим" для " d
и перейти к простому подходу с иностранными ключами и иметь unique_together
всех тех, которые были бы просты?
Версии:
- Джанго 2.2
- Postgres 11
При необходимости я могу преобразовать существующий ArrayField в простой CharField
который будет означать больше строк БД, что несколько хорошо, если я CharField
все уникальные ограничения в базу данных, а не проверю каждый раз при сохранении.