【问题标题】:Override Django Unique_Together Validation by adding extra Field通过添加额外的字段覆盖 Django Unique_Together 验证
【发布时间】:2018-09-24 11:58:42
【问题描述】:

我需要一些帮助来将一些记录保存到数据库中。为停车应用程序工作,我想通过额外的参数来扩展 unique_together 查询数据库的方式。只是为了了解我的情况。

例如,我让用户可以在位置 P1 的 9 至 18 日(parking_on)25 日预订地块。因为这两个过滤器的方式都是数据库独有的,所以其他人不能在 25 日但从 19-24 日预订相同的情节 P1 ==>因此我需要在这里进行某种验证或手动更改方式unique_together 验证有效。

有人可以帮忙吗?

请在下面找到我的模型和管理员

from django.db import models
from django.conf import settings
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _
from datetime import datetime, timedelta, time
from django.core.exceptions import NON_FIELD_ERRORS
today = datetime.now().date()
tomorrow = today + timedelta(1)
now = datetime.now()
l = now.hour
m = int(now.strftime("%H"))


class ParcareManager(models.Manager):
    def active(self, *args, **kwargs):
        return super(ParcareManager, self).filter(draft=False).filter(parking_on__lte=datetime.now())


class Parcare(models.Model):
    PARKING_PLOT = (('P1', 'Parking #1'),
                    ('P2', 'Parking #2'), ('P3', 'Parking #3'))
    user = models.ForeignKey(settings.AUTH_USER_MODEL,
                             blank=True, null=True, default=1, on_delete=True)
    email = models.EmailField(blank=True, null=True)
    parking_on = models.DateField(auto_now=False, auto_now_add=False, blank=True, null=True,
                                  help_text='Alege data cand doresti sa vii in office',)
    parking_off = models.DateField(auto_now=False, auto_now_add=False, blank=True, null=True,
                                   help_text='Alege Data Plecarii')
    numar_masina = models.CharField(max_length=8, default="IF77WXV", blank=True, null=True,
                                    help_text='Introdu Numarul Masinii')
    location = models.CharField(max_length=3, blank=True, default="P1", null=True, choices=PARKING_PLOT,
                                help_text='Alege Locul de Parcare Dorit')
    updated = models.DateTimeField(
        auto_now=True, auto_now_add=False, blank=True, null=True)
    timestamp = models.DateTimeField(
        auto_now=False, auto_now_add=True, blank=True, null=True)
    venire = models.TimeField(default=time(
        9, 00), auto_now=False, auto_now_add=False, help_text='Alege Ora Venirii')
    plecare = models.TimeField(default=time(
        18, 00), auto_now=False, auto_now_add=False, help_text='Alege Ora Plecarii')
    objects = ParcareManager()

    def __str__(self):
        return self.location + " | " + str(self.parking_on) + " | " + str(self.parking_off)

    class Meta:
        verbose_name_plural = "parcare"
        ordering = ["-parking_on"]
        unique_together = ("parking_on", "location")

    def clean(self):
        if self.parking_on == today:  # merge--vedem dak parcam azi
            raise ValidationError(
                {'parking_on': _('Please book for a date starting tomorrow')})
        if self.parking_off < self.parking_on:  # merge-vedem daca bookam in trecut
            raise ValidationError(
                {'parking_off': _('You cant book for a past date!')})



    def save(self):
        list = []
        d = self.parking_on
        while d <= self.parking_off:
            list.append(
                Parcare(user=self.user,
                        email=self.email,
                        parking_on=d,
                        parking_off=d,
                        location=self.location
                        )
            )
            d = d + timedelta(days=1)
        Parcare.objects.bulk_create(list)


from django.contrib import admin
from .models import Parcare


class ParcareModelAdmin(admin.ModelAdmin):
    list_display = ["user", "location",
                    "parking_on", "parking_off",  "venire", "plecare", "timestamp"]
    list_display_links = ["user", "location"]
    list_editable = ["parking_off", "parking_on", "venire", "plecare"]
    list_filter = ["parking_on", "location", "email"]
    search_fields = ["location", "parking_on"]
    date_hierarchy = 'parking_on'

    class Meta: 
        model = Parcare
    def get_form(self, request, obj=None, **kwargs):
        form = super().get_form(request, obj, **kwargs)
        if not obj:
            user = request.user
            form.base_fields['user'].initial = user
            form.base_fields['email'].initial = user.email
        return form 

admin.site.register(Parcare, ParcareModelAdmin)

提前谢谢你!

【问题讨论】:

    标签: django validation


    【解决方案1】:

    我只是对这个问题有一些想法。 我认为最好的解决方案是在DateTimeField 上替换DateField。然后你可以在clean 方法中使用类似这样的东西(就像一个性能不好的例子):

    def clean(self):
        qs = Parcare.objects.filter(location=self.location)
                            .filter(parking_on__gt=self.parking_on)
                            .filter(parking_off__lt=self.parking_on)
        qs2 = Parcare.objects.filter(location=self.location)
                             .filter(parking_on__gt=self.parking_off)
                             .filter(parking_off__lt=self.parking_off)
        if len(qs) > 0 or len(qs2) > 0:
            raise ValidationError('Time is booked already')
        if self.parking_on < datetime.now():  # merge--vedem dak parcam azi
            raise ValidationError(
                {'parking_on': _('Please book for a time more than now')})
        if self.parking_off < self.parking_on:  # merge-vedem daca bookam in trecut
            raise ValidationError(
                {'parking_off': _('You cant book for a past date!')})
    

    【讨论】:

    • 谢谢,但我必须接受我所拥有的!
    猜你喜欢
    • 2019-08-08
    • 2012-08-13
    • 2015-06-19
    • 2015-08-06
    • 1970-01-01
    • 1970-01-01
    • 2019-12-30
    • 1970-01-01
    • 2011-01-09
    相关资源
    最近更新 更多