问题
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