我正在Django中创建一个汽车预订应用程序。用户可以为给定的汽车创建预订。这发生在/reservation/<car_id>/add
。该表单不包含Car字段,因为ID是在URL中给出的。现在,我想向保留模型添加一个验证,以便没有保留可以重叠。我有以下代码(最低版本):
# models.py
class Car(models.Model):
name = models.CharField(max_length=200)
class Reservation(models.Model):
car = models.ForeignKey(Car, on_delete=models.CASCADE)
owner = models.ForeignKey(User, on_delete=models.CASCADE)
start_time = models.DateTimeField()
end_time = models.DateTimeField()
def clean(self):
# Check if overlaps with other reservations in self.car.reservation_set
# views.py
class ReservationAdd(LoginRequiredMixin, CreateView):
template_name = 'reservation/reservation_add.html'
model = Reservation
form_class = ReservationAddForm
def form_valid(self, form):
form.instance.car = Car.objects.get(pk=self.kwargs['car_id'])
form.instance.owner = self.request.user
return super().form_valid(form)
# forms.py
class ReservationAddForm(forms.ModelForm):
class Meta:
fields = ('start_time', 'end_time')
model = Reservation
现在,在Reservation.clean
方法中出现以下错误:
reservation.models.Reservation.car.RelatedObjectDoesNotExist: Reservation has no car.
在我看来,clean
方法在form_valid
方法之前被调用。因此,我认为我的设计并不完全正确。正确的方法是什么?
答案 0 :(得分:3)
是的。 form_valid
的意思是“一旦确认表单有效,便要运行的代码”。
您需要进行一些更改。首先,将您的验证移至ReservationAddForm本身;其次,将Car实例传递给该形式。所以:
class ReservationAddForm(forms.ModelForm):
class Meta:
fields = ('start_time', 'end_time')
model = Reservation
def __init__(self, *args, **kwargs):
self.car = kwargs.pop('car')
super().__init__(*args, **kwargs)
def clean(self):
... do something with self.car
class ReservationAdd(LoginRequiredMixin, CreateView):
template_name = 'reservation/reservation_add.html'
model = Reservation
form_class = ReservationAddForm
def get_form_kwargs(self):
self.car = Car.objects.get(pk=self.kwargs['car_id'])
kwargs = super().get_form_kwargs()
kwargs['car'] = self.car
return kwargs
def form_valid(self, form):
form.instance.car = self.car
form.instance.owner = self.request.user
return super().form_valid(form)
答案 1 :(得分:1)
我认为更好的方法是
class ReservationAdd(LoginRequiredMixin, CreateView):
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs["car"] = Car.objects.get(pk=self.kwargs['car_id'])
return kwargs
和模型表单覆盖__init__
方法
class ReservationAddForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.car = kwargs.pop("car")
super().__init__(*args, **kwargs)
def clean(self):
# cleaned data
cleaned_data = super().cleaned_data()
# access the car instance using self.car
# to do validation
return cleaned_data