避免 django 模型中的重复行条目
Avoiding duplicate row entry inside django model
我有一个 CarRent
模型,它是 Car
模型的外键。在 Car
detailView 页面上,我有一个用于 driver 的按钮来放置租金,这将导致向 CarRent Table 添加一行。在车主批准租金请求之前,租金尚未生效。现在的问题是 driver 可以多次点击租车按钮,从而导致 CarRent
模型中出现许多重复的行,并且还会向车主提出多次冗余的租车请求。如果当前用户 (driver) 已经请求特定汽车并且 rent_approval 不正确,我正在寻找一种隐藏“Place A Rent”表格的方法。
谢谢。任何帮助将不胜感激。
models.py
class Car(models.Model):
car_owner = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='car_owner', on_delete=models.CASCADE)
car_model = models.CharField(max_length=20, blank=True, null=True)
rented = models.BooleanField(default=False)
class CarRent(models.Model):
car = models.ForeignKey(Car, related_name='rented_car', on_delete=models.CASCADE)
driver = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='driver_renting', on_delete=models.CASCADE)
rent_approval = models.BooleanField(null=True)
active_rent = models.BooleanField(default=False, null=True)
views.py
class CarView(LoginRequiredMixin, UserPassesTestMixin, FormMixin, DetailView):
model = Car
form_class = RentForm
def get_success_url(self):
return reverse('app:car-detail', kwargs={'pk': self.object.pk})
def post(self, request, *args, **kwargs):
form = self.get_form()
self.object = self.get_object()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form, *args, **kwargs):
form.instance.car_id = self.kwargs['pk']
form.instance.driver = self.request.user
form.save()
messages.success(self.request, f'Rent request successful! the car owner will be notified immediately.')
return super().form_valid(form)
def test_func(self):
return self.request.user.is_driver and self.request.user.is_active
car_detail.html
...
<h3>Place a Rent</h3>
<form action="" method="post" novalidate class="form-inline">
{% csrf_token %}
{% include 'app/bs4_form.html' with form=form %}
<button class="book-now-btn" type="submit">Rent</button>
</form>
...
在您的 CarView 中 class:
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['rentAlreadyExists'] = CarRent.objects.filter(driver=self.request.user, car=self.object, active_rent=False).exists()
return context
然后在您的模板中您可以:
{% if not rentAlreadyExists %}
... your form ...
{% endif %}
为了获得正确的解决方案,您可以为 CurRent 定义一个内部 Meta class 并为字段 driver 和 car 定义一个 unique_together 属性以避免重复输入。
class CarRent(models.Model):
car = models.ForeignKey(Car, related_name='rented_car', on_delete=models.CASCADE)
driver = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='driver_renting', on_delete=models.CASCADE)
rent_approval = models.BooleanField(null=True)
active_rent = models.BooleanField(default=False, null=True)
class Meta:
unique_together = ("driver", "car")
所以这是一个有效的问题。为此,您可能必须通过覆盖 CarRent 的保存功能来提供验证。
from django.core.exceptions import ValidationError
def save(self, *args, **kwargs):
has_reservation = self.__class__.objects.filter(car=self.car, driver=self.driver)
#reservation_valid = some logic to find if reservation is allowed
if not reservation_valid:
raise ValidationError("Driver reservation is not valid", code="drive_not_valid")
return super().save(*args, **kwargs)
然后在视图中
try:
#try renting
except Exception as e:
if hasattr(e, "code"):
if e.code == "drive_not_valid":
#place your invalid view logic here
我有一个 CarRent
模型,它是 Car
模型的外键。在 Car
detailView 页面上,我有一个用于 driver 的按钮来放置租金,这将导致向 CarRent Table 添加一行。在车主批准租金请求之前,租金尚未生效。现在的问题是 driver 可以多次点击租车按钮,从而导致 CarRent
模型中出现许多重复的行,并且还会向车主提出多次冗余的租车请求。如果当前用户 (driver) 已经请求特定汽车并且 rent_approval 不正确,我正在寻找一种隐藏“Place A Rent”表格的方法。
谢谢。任何帮助将不胜感激。
models.py
class Car(models.Model):
car_owner = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='car_owner', on_delete=models.CASCADE)
car_model = models.CharField(max_length=20, blank=True, null=True)
rented = models.BooleanField(default=False)
class CarRent(models.Model):
car = models.ForeignKey(Car, related_name='rented_car', on_delete=models.CASCADE)
driver = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='driver_renting', on_delete=models.CASCADE)
rent_approval = models.BooleanField(null=True)
active_rent = models.BooleanField(default=False, null=True)
views.py
class CarView(LoginRequiredMixin, UserPassesTestMixin, FormMixin, DetailView):
model = Car
form_class = RentForm
def get_success_url(self):
return reverse('app:car-detail', kwargs={'pk': self.object.pk})
def post(self, request, *args, **kwargs):
form = self.get_form()
self.object = self.get_object()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form, *args, **kwargs):
form.instance.car_id = self.kwargs['pk']
form.instance.driver = self.request.user
form.save()
messages.success(self.request, f'Rent request successful! the car owner will be notified immediately.')
return super().form_valid(form)
def test_func(self):
return self.request.user.is_driver and self.request.user.is_active
car_detail.html
...
<h3>Place a Rent</h3>
<form action="" method="post" novalidate class="form-inline">
{% csrf_token %}
{% include 'app/bs4_form.html' with form=form %}
<button class="book-now-btn" type="submit">Rent</button>
</form>
...
在您的 CarView 中 class:
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['rentAlreadyExists'] = CarRent.objects.filter(driver=self.request.user, car=self.object, active_rent=False).exists()
return context
然后在您的模板中您可以:
{% if not rentAlreadyExists %}
... your form ...
{% endif %}
为了获得正确的解决方案,您可以为 CurRent 定义一个内部 Meta class 并为字段 driver 和 car 定义一个 unique_together 属性以避免重复输入。
class CarRent(models.Model):
car = models.ForeignKey(Car, related_name='rented_car', on_delete=models.CASCADE)
driver = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='driver_renting', on_delete=models.CASCADE)
rent_approval = models.BooleanField(null=True)
active_rent = models.BooleanField(default=False, null=True)
class Meta:
unique_together = ("driver", "car")
所以这是一个有效的问题。为此,您可能必须通过覆盖 CarRent 的保存功能来提供验证。
from django.core.exceptions import ValidationError
def save(self, *args, **kwargs):
has_reservation = self.__class__.objects.filter(car=self.car, driver=self.driver)
#reservation_valid = some logic to find if reservation is allowed
if not reservation_valid:
raise ValidationError("Driver reservation is not valid", code="drive_not_valid")
return super().save(*args, **kwargs)
然后在视图中
try:
#try renting
except Exception as e:
if hasattr(e, "code"):
if e.code == "drive_not_valid":
#place your invalid view logic here