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'
。
私はアトミックセーブが必要なので、まず予約を保存できません。どのように解決できますか?
もちろん、まず予約を保存する必要があります。それ以外の場合、 'ReservationItem'の' Reservation'フィールドにどのように保存するIDを知っていると思いますか?節約されている原子はそこで何もしません。アトミックトランザクションは、['transaction.atomic'](https://docs.djangoproject.com/ja/1.11/topics/db/transactions/#django.db)内にカプセル化されたトランザクションです。 .transaction.atomic)コンテキスト。 – spectras
あなたは正しいですが、ReservationItemsがインラインの場合、それらは親Instanceを持つ単一のトランザクションに保存されます。 –
簡単:saveメソッドをその上に '@ transaction.atomic(savepoint = False)'デコレータを追加して、手動で単一のトランザクションとしてマークします。あるいは、メソッド内で 'with transaction.atomic(savepoint = False)'を使用してください。それともあなたの意見ではなく、あなたの姿勢でやる方がいいですか?フォームはトランザクションの構造に関与すべきではありません。 – spectras