避免 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