Должен ли я использовать django Сигналы в этом случае? - PullRequest
0 голосов
/ 06 марта 2020

Я новичок, я открываю для себя много вещей, и иногда мне не хватает всей информации и уловок, которые нужно выучить.

Я пытаюсь сделать проект django для пиццерии. Люди могут заказать пиццу онлайн, порядок простой: вы можете выбрать одну или несколько пицц и при желании добавить несколько дополнительных услуг (добавляя сыр, ветчину или что-то еще ...) для каждой заказанной вами пиццы, и она будет добавлена ​​в корзину.

Моя задача - автоматически рассчитать цену для каждой пиццы.

В основном вот мой файл модели:

class Pizza(models.Model):

    nom = models.CharField(max_length=30)
    ingrédients = models.CharField(max_length=500)
    prix = models.DecimalField(max_digits=4, decimal_places=2)

nom означает имя

class Extra(models.Model):

    sup = models.CharField(max_length=30)
    prix = models.DecimalField(max_digits=3, decimal_places=2)

sup - это имя дополнительного.

class IndividualChoice(models.Model):

    pizzaChosen = models.ForeignKey(‘Pizza’, default="", null=True, on_delete=models.CASCADE)
    extraChosen = models.ManyToManyField(‘Extra’, blank=True)
    panier = models.ForeignKey(‘Cart’, default="", on_delete=models.CASCADE)
    calzone = models.BooleanField(default=False)
    prix = models.DecimalField(max_digits=5, decimal_places=2, default=0)

IndividualChoice немного странно. Это модель, в которой хранится каждый выбор, здесь «корзина» означает корзину, в которой есть модель, но я не думаю, что было бы полезно показывать ее здесь.

Я немного узнал о django сигналах, поэтому я попытался создать один:

def prix_extra_calcul(sender, instance, action, *args, **kwargs):
    instance.prix = 0
    if action == “post_add” or action == “post_remove” or action == “post_clear”:
        for extra in instance.extraChosen.all():
            instance.prix += extra.prix
        instance.prix += instance.pizzaChosen.prix
        instance.save()

m2m_changed.connect(prix_extra_calcul, sender=IndividualChoice.extraChosen.through)

Это хорошо работает, когда я создаю пиццу с дополнительным, но если только заменить пиццу, сигнал m2m не будет запущен. Поэтому я попытался найти другое решение, но это глупо:

def prix_pizza_calcul(sender, instance, *args, **kwargs):
    instance.prix = 0
    for extra in instance.extraChosen.all():
        instance.prix += extra.prix
    instance.prix += instance.pizzaChosen.prix

def prix_extra_calcul(sender, instance, action, *args, **kwargs):
    if action == “post_add” or action == “post_remove” or action == “post_clear”:
    # no need to write code because prix_pizza_calcul will be fired by instance.save()
        instance.save()

pre_save.connect(prix_pizza_calcul, sender=IndividualChoice)
m2m_changed.connect(prix_extra_calcul, sender=IndividualChoice.extraChosen.through)

Второе решение «хорошо работает», когда я хочу изменить выбор, но когда я создаю новую пиццу, у меня появляется это сообщение об ошибке «максимальная глубина рекурсии» превышено при вызове объекта Python ». И я думаю, это потому, что я зацикливаюсь на том, что не сохранено.

Я полностью застрял в этой проблеме, я пытался решить ее в течение нескольких дней. Должен ли я создать Сигнал, подходит ли сигнал для такого рода проблем?

(Какой простой способ быть веб-разработчиком ...)

Спасибо за чтение!

Ответы [ 2 ]

0 голосов
/ 06 марта 2020

Я не знаю ваших знаний о нормализации базы данных, но здесь с ценой на IndividualChoice вы дублируете данные: цена - это просто вычисление уже сохраненных данных. Если вы избегаете дублирования данных, вы избежите аномалий данных.

Если у вас есть имя и фамилия, вы бы сохранили «полное имя»? Если вы ответили «да», пожалуйста, прочитайте документацию о @property здесь: https://docs.djangoproject.com/en/3.0/topics/db/models/#model -методы

Решение, вероятно, заключается в удалении DecimalField prix на модели IndividualChoice и добавлении как то так:

    @property
    def prix(self):
        "Returns the price of the item"
        price = self.pizzaChosen.prix
        for extra in self.extraChosen.all():
            price += extra.prix
        return price 
0 голосов
/ 06 марта 2020

Может быть, вы можете попробовать использовать для этого декоратор @receiver. Сигнал будет излучаться при каждом post_save.

from django.dispatch import receiver

@receiver(post_save, sender=IndividualChoice)
def prix_extra_calcul(sender, instance, created, **kwargs):
    ...
...