2017-09-04 78 views
0

我在overwritter ModelForm的save()方法中遇到django admin的问题。Django管理员ModelForm,保存计算相关

models.py

class Reservation(models.Model): 

    status = models.PositiveSmallIntegerField(choices=STATUS, default=0) 
    creation_date = models.DateTimeField(auto_now_add=True) 
    date_start = models.DateField() 
    date_end = models.DateField() 
    service = models.ForeignKey(Service, on_delete=models.CASCADE) 

class ReservationItem(models.Model): 
    quantity = models.IntegerField() 
    unit_price = models.DecimalField(max_digits=10, decimal_places=2) 
    unit_tax = models.DecimalField(max_digits=10, decimal_places=2) 
    row_total = models.DecimalField(max_digits=10, decimal_places=2) 
    row_total_incl_tax = models.DecimalField(max_digits=10, decimal_places=2) 
    reservation = models.ForeignKey(Reservation, on_delete=models.CASCADE, related_name='items') 
    resource = models.ForeignKey(Resource, on_delete=models.CASCADE) 

项目从服务衍生,通过可用性查询预约,所以it've书面管理员自定义的ModelForm。

admin.py

class ReservationModelForm(forms.ModelForm): 
    def clean(self): 
     if 'service' in self.cleaned_data: 
      self._check_availability() 

     return self.cleaned_data 

    def _check_availability(self): 
     '''do some stuff an get items ad an array of ReservationItems instances created like this: 
     ReservationItem(
      resource=avail_resource, 
      quantity=resource_type.quantity, 
      unit_price=resource.unit_price, 
      unit_tax=resource.unit_price*resource.tax.percentage, 
      row_total=resource.unit_price*resource_type.quantity, 
      row_total_incl_tax=... 
     )''' 
     self.cleaned_data['items'] = items 

    # then the save method 
    def save(self, commit=True): 
     reservation = super(ReservationModelForm, self).save(commit=commit) 
     if not self.instance.id: 
      service = self.cleaned_data.get('service') 
      .... 
      reservation.items.set(self.cleaned_data['items'], bulk=False) 

     return reservation 

class ReservationAdmin(admin.ModelAdmin): 
    form = ReservationModelForm 

现在我得到的是一个错误:save() prohibited to prevent data loss due to unsaved related object 'reservation'

但是我不能先保存保留,因为我需要原子保存,我该如何解决?

+0

当然,你需要先保存预订。您希望如何知道要保存在'ReservationItem'的'Reservation'字段中的ID?原子的保存无关紧要:原子事务是封装在['transaction.atomic']中的事务(https://docs.djangoproject.com/en/1.11/topics/db/transactions/#django.db .transaction.atomic)上下文。 – spectras

+0

好的你是对的,但是如果ReservationItems里面有一个内联函数,它们将被保存在一个包含父实例的事务中。我想模拟同样的事情 –

+0

简单:通过在其上面添加'@ transaction.atomic(savepoint = False)'装饰器,手动将存储方法标记为单个事务。或者在方法中使用'with transaction.atomic(savepoint = False)'。或者更好的是:在你看来,而不是你的形式。表单不应涉及交易的结构。 – spectras

回答

0

我觉得我找到了解决方案。 我已将一个属性添加到预留模型temp_items并将它们保存在模型save()方法中,因此我可以提取和验证ModelForm save()中的项目并实际保存在模型save()方法中。 它似乎工作的很好