2017-09-04 11 views
0

나는 장고 작성자 ModelForm의 save() 메소드에서 django admin의 문제점에 직면하고 있습니다.Django admin ModelForm, 계산 된 결과 저장

it've은 관리자에 대한 사용자 정의 ModelForm를 작성

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) 

항목 가용성 쿼리 서비스에서 파생되는 예약 할 수 있도록 models.py.

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

Easy : 저장 메소드를 그 위에'@ transaction.atomic (savepoint = False)'데코레이터를 추가하여 수동으로 단일 트랜잭션으로 표시하십시오. 또는 메소드 내에서 with transaction.atomic (savepoint = False)를 사용하십시오. 또는 더 나은 방법은 귀하의 견해가 아니라 귀하의 견해에 따라하십시오. 양식은 거래의 구조에 개입해서는 안됩니다. – spectras

답변

0

나는 해결책을 찾았을 것이다. Reservation 모델 temp_items에 속성을 추가하고 ModelForm save()의 항목을 추출 및 유효화하고 save() 메소드에 실제로 저장할 수 있도록 트랜잭션과 함께 save() 메소드 모델에 저장했습니다. 위대한 작품으로 보인다