ManyToManyField in Class Based Generic Views and Save Override

我只是一个虾纸丫 提交于 2021-02-11 07:51:55

问题


We have a class-based-generic view that adds an object with a ManyToManyField relationship. We're trying to modify some values on save() override for the relationships created on that ManyToManyField, but it doesn't seem like they ever get created in save(), so we're forced to call a post_save method in get_success_url so the relationships are created. This seems very, very ugly. How do we force the relationships to be created before we leave save()?

I've seen this answer on SO, which says to override form_valid() to create the relationship, but why do I need to do this if they're created automatically somewhere between form_valid() and get_success_url()?

# models.py
class Payment(models.Model):
    invoice = models.ManyToManyField(Invoice)
    deposit_date = models.DateField()
    check_number = models.CharField(max_length=100, blank=True, null=True)
    description = models.TextField(blank=True, null=True)

    def post_save(self):
        """
        ManyToManyField relationships aren't formed yet when overriding save() for Class Based Generic
        Views. Call this whenever you're saving a Payment object.
        """
        for invoice in self.invoice.all():
            # Do some calcualtions that make us happy
            invoice.save()

# views.py - We override get_success_url() in UpdateView too.
class PaymentAdd(CreateView):
    model = Payment
    form_class = PaymentForm
    context_object_name = 'object'
    template_name = 'form.html'

    def get_success_url(self):
        self.object.post_save()
        return reverse('payment-page')

回答1:


If this has to be done each time a Payment is saved, it's better to leave that responsibility to the model instead of moving it to view. The best way is to use the post_save signal, as something like this:

In models.py, somewhere below the definition of the Payment model:

from django.db.models.signals import post_save
from django.dispatch import receiver

@receiver(post_save, sender=Payment)
def my_handler(sender, instance, **kwargs):
    for invoice in instance.invoice.all():
        # Do some calcualtions that make us happy
        invoice.save()

On an unrelated note, I strongly suggest you to use plural attribute names for M2M fields: invoices instead of invoice in this case. It makes it much clearer to your fellow developers.



来源:https://stackoverflow.com/questions/16465560/manytomanyfield-in-class-based-generic-views-and-save-override

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!