2017-09-04 9 views
0

私はdjango adminの上書きモデルModelFormのsave()メソッドで問題に直面しています。Django admin 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) 

予約アイテムは、可用性のクエリによって、サービスから派生しているので、管理者用のカスタムのModelFormを書かit've。

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/ja/1.11/topics/db/transactions/#django.db)内にカプセル化されたトランザクションです。 .transaction.atomic)コンテキスト。 – spectras

+0

あなたは正しいですが、ReservationItemsがインラインの場合、それらは親Instanceを持つ単一のトランザクションに保存されます。 –

+0

簡単:saveメソッドをその上に '@ transaction.atomic(savepoint = False)'デコレータを追加して、手動で単一のトランザクションとしてマークします。あるいは、メソッド内で 'with transaction.atomic(savepoint = False)'を使用してください。それともあなたの意見ではなく、あなたの姿勢でやる方がいいですか?フォームはトランザクションの構造に関与すべきではありません。 – spectras

答えて

0

私は解決策を見つけました。 予約モデルtemp_itemsに属性を追加し、モデルsave()メソッドにトランザクションで保存しました。これにより、ModelForm save()のアイテムを抽出して検証し、実際にsave()メソッドに保存できます。 これはうまくいくようです

関連する問題