Создание уникального объекта с использованием DateField () - PullRequest
0 голосов
/ 09 января 2019

Я просто хотел бы создать модель, которая, по существу, предотвращает выбор одной и той же даты двумя разными пользователями (или одним и тем же пользователем).
Например, если Пользователь1 выбрал 2019-01-10 в качестве "date" для бронирования, то Пользователь2 (или любые другие Пользователи) не смогут создать объект с такой же датой.

Я создал очень простую модель, которая позволяет различным пользователям создавать объекты с помощью DateField(). Используя страницу администрирования Django, я могу создавать разные экземпляры объектов двумя разными пользователями (admin и Test_User).

Чтобы убедиться, что новый объект не может быть создан, если эта дата уже использовалась другим объектом, я попробовал следующий подход: функция сравнения, которая использует __dict__.

models.py

from __future__ import unicode_literals

from django.db import models, IntegrityError
from django.db.models import Q
from django.contrib.auth.models import User
from datetime import datetime

class Booking(models.Model):
    date = models.DateField(null=False, blank=False)
    booked_at = models.DateTimeField(auto_now_add=True)
    booking_last_modified = models.DateTimeField(auto_now=True)


class PersonalBooking(Booking):
    user = models.ForeignKey(User, on_delete=models.CASCADE)

    def compare(self, obj):
        excluded_keys = 'booked_at', '_state', 'booking_last_modified', 'user', 
        return self._compare(self, obj, excluded_keys)

    def _compare(self, obj1, obj2, excluded_keys):
        d1, d2 = obj1.__dict__, obj2.__dict__
        for k,v in d1.items():
            if k in excluded_keys:
                continue
            try:
                if v != d2[k]:
                    pass
            except IntegrityError as error:
                print(error)             
                print('Date already selected by different User. Please select another date.')

admin.py

from django.contrib import admin
from . import models
from .models import Booking, PersonalBooking


class PersonalBookingAdmin(admin.ModelAdmin):
    list_display = ('format_date', 'user', )

    def format_date(self, obj):
        return obj.date.strftime('%d-%b-%Y')

    format_date.admin_order_field = 'date'
    format_date.short_description = 'Date'

    def user(self, obj):
        return obj.user()

    user.admin_order_field = 'user'
    user.short_description = 'User'


admin.site.register(models.PersonalBooking, PersonalBookingAdmin)

Это не сработало, как я надеялся, объекты с одинаковой датой все еще могли создаваться одинаковыми или разными пользователями. Возможно, есть более простой способ? Или, может быть, мне нужно использовать класс Q ()? Я не очень знаком с этим. Любая помощь очень ценится. Благодаря.

Ответы [ 2 ]

0 голосов
/ 09 января 2019

Эту проверку можно выполнить на уровне базы данных, установив для атрибута unique значение True в поле вашей модели.

class Booking(models.Model):
    date = models.DateField(null=False, blank=False, unique=True)
    booked_at = models.DateTimeField(auto_now_add=True)
    booking_last_modified = models.DateTimeField(auto_now=True)

Но это могло бы вызвать проблемы, если бы поле было позже изменено для сохранения времени.

Если вы также собираетесь хранить время, вы можете переопределить функцию save по умолчанию, чтобы проверить, что нет другого Booking с такой же датой (__date ) каждый раз, когда он сохраняется. exists() возвращает True, если есть совпадение, поэтому будет выброшено ValidationError, если есть совпадение.

from django.core.exceptions import ValidationError

class Booking(models.Model):
    date = models.DateTimeField(null=False, blank=False)
    booked_at = models.DateTimeField(auto_now_add=True)
    booking_last_modified = models.DateTimeField(auto_now=True)

    def save(self, *args, **kwargs):
        # Make sure there are no bookings on the same day
        if Booking.objects.exclude(pk=self.pk).filter(date__date=self.date.date).exists():
            raise ValidationError('There cannot be two bookings with the same date.')

        super(Booking, self).save(*args, **kwargs)
0 голосов
/ 09 января 2019

Попробуйте это
https://docs.djangoproject.com/en/2.1/ref/models/fields/#unique-for-date Для user набора столбцов unique_for_date=True

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...