我希望实现的是"禁用";用户在一段时间后更新或删除记录的可能性。在我的应用程序中,用户创建了一个交付预订槽,作为该槽的一部分,他们指定了一个交付日期delivery_date
。
要求:用户不能在delivery_date
生效后7天内更新/删除预订时段
我该怎么做呢?
models.py
from django.db import models
from django.utils import timezone
from django.urls import reverse
from django.contrib.auth.models import User
class Customer(models.Model):
username = models.ForeignKey(User,on_delete=models.CASCADE)
name = models.CharField(max_length=20,null=True)
def __str__(self):
return self.name
# Create your models here.
class Booking(models.Model):
customer_name = models.ForeignKey(Customer,on_delete=models.CASCADE,null=True)
username = models.ForeignKey(User,on_delete=models.CASCADE)
qty_plts = models.PositiveSmallIntegerField(default=1)
cbm = models.PositiveSmallIntegerField(default=1)
created_date = models.DateTimeField(default=timezone.now())
delivery_date = models.DateField(null=True)
delivery_time = models.TimeField(null=True)
booking_number = models.CharField(max_length=50,unique=True)
def __str__(self):
return self.booking_number
def save(self, **kwargs):
if not self.booking_number:
self.booking_number = f"{self.delivery_date:%Y%m%d}{self.delivery_time:%H%M}"
super().save(**kwargs)
def get_absolute_url(self):
return reverse('bookmyslot:detail',kwargs={'pk':self.pk})
views.py
from django.shortcuts import render
# Create your views here.
from .models import Booking,Customer
from .forms import BookingForm
from django.urls import reverse,reverse_lazy
from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import (ListView,DetailView,CreateView,UpdateView,DeleteView,TemplateView)
class AboutView(TemplateView):
template_name = 'about.html'
class HomeView(TemplateView):
template_name = 'index.html'
class BookingCreate(LoginRequiredMixin,CreateView):
login_url = '/login'
redirect_field_name = 'bookmyslot/booking_detail.html'
model = Booking
form_class = BookingForm
def get_form_kwargs(self, **kwargs):
form_kwargs = super(BookingCreate,self).get_form_kwargs(**kwargs)
form_kwargs['username'] = self.request.user
return form_kwargs
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.username = self.request.user
self.object.save()
return super().form_valid(form)
class BookingList(LoginRequiredMixin,ListView):
login_url = '/login'
model = Booking
template_name = 'bookmyslot/booking_list.html'
context_object_name = 'bookings'
def get_queryset(self):
if not self.request.user.is_staff:
return Booking.objects.filter(username=self.request.user)
else:
return Booking.objects.all()
class BookingDetail(LoginRequiredMixin,DetailView):
login_url = '/login'
context_object_name = 'booking_detail'
model = Booking
def get_queryset(self):
if not self.request.user.is_staff:
return Booking.objects.filter(username=self.request.user)
else:
return Booking.objects.all()
class BookingUpdate(LoginRequiredMixin,UpdateView):
login_url = '/login'
template_name = 'bookmyslot/booking_form_update.html'
model = Booking
form_class = BookingForm
def get_form_kwargs(self, **kwargs):
form_kwargs = super(BookingUpdate,self).get_form_kwargs(**kwargs)
form_kwargs['username'] = self.request.user
return form_kwargs
class BookingDelete(LoginRequiredMixin,DeleteView):
login_url = '/login'
model = Booking
success_url = reverse_lazy('bookmyslot:list')
forms.py
from django import forms
from bookmyslot.models import Booking,Customer
from bootstrap_datepicker_plus import DatePickerInput
import datetime as dt
from django.utils import timezone
from .utilities import check_free_time
import os
HOUR_CHOICES = [(dt.time(hour=x), '{:02d}:00'.format(x)) for x in range(7, 13)]
class BookingForm(forms.ModelForm):
def __init__(self,*args,**kwargs):
user = kwargs.pop('username',None)
super(BookingForm,self).__init__(*args,**kwargs)
self.fields['qty_plts'].label = "Quantity Of Pallets"
self.fields['cbm'].label = "Shipment CBM"
self.fields['delivery_date'].label = "Delivery Date"
self.fields['delivery_time'].label = "Delivery Time"
self.fields['customer_name'].label = "Customer Name"
self.fields['customer_name'].queryset = Customer.objects.filter(username=user)
def clean(self):
cleaned_data = super(BookingForm,self).clean()
cleaned_delivery_date = cleaned_data.get('delivery_date')
cleaned_delivery_time = cleaned_data.get('delivery_time')
booking_number = f"{cleaned_delivery_date:%Y%m%d}{cleaned_delivery_time:%H%M}"
if Booking.objects.filter(booking_number=booking_number).exists():
x = Booking.objects.filter(delivery_date=cleaned_delivery_date)
occupied_slots = []
for i in range(0,len(x)):
occupied_slots.append(x[i].booking_number[-4:])
all_slots = ['{:02d}00'.format(x) for x in range(7, 13)]
available_slot = check_free_time(all_slots,occupied_slots)
if available_slot:
message = f"Requested slot is already booked, here are today's available times: {os.linesep.join(available_slot)}"
raise forms.ValidationError(message)
else:
message = "There are no more slots available today, please choose another date"
raise forms.ValidationError(message)
class Meta:
model = Booking
fields = ('customer_name','qty_plts','cbm','delivery_date','delivery_time')
widgets = {'delivery_date':DatePickerInput(options={"daysOfWeekDisabled":[0,6],"minDate":timezone.now().date().strftime('%Y-%m-%d')}),
'delivery_time':forms.Select(choices=HOUR_CHOICES)}
urls . py
from . import views
from django.urls import path
app_name = 'bookmyslot'
urlpatterns = [
path('mybookings/',views.BookingList.as_view(),name='list'),
path('mybookings/<int:pk>/',views.BookingDetail.as_view(),name='detail'),
path('update/<int:pk>/',views.BookingUpdate.as_view(),name='update'),
path('delete/<int:pk>/',views.BookingDelete.as_view(),name='delete'),
path('new/',views.BookingCreate.as_view(),name='create'),
path('',views.HomeView.as_view(),name='home'),
path('about/',views.AboutView.as_view(),name='about')
]
booking_detail.html
{% extends 'bookmyslot/base.html' %}
{% block content %}
<div class="jumbotron">
<h2>Booking Number: {{ booking_detail.booking_number }}</h2>
<h3>Details:</h3>
<p></p>
{% if user.is_staff %}
<p>Company Name: {{booking_detail.username}}</p>
<p>Customer Name: {{ booking_detail.customer_name }}</p>
<p>Quantity Of Pallets: {{ booking_detail.qty_plts }}</p>
<p>CBM Of Delivery: {{ booking_detail.cbm }}</p>
<p>Delivery Date: {{ booking_detail.delivery_date }}</p>
<p>Delivery Time: {{ booking_detail.delivery_time }}</p>
{% else %}
<p>Customer Name: {{ booking_detail.customer_name }}</p>
<p>Quantity Of Pallets: {{ booking_detail.qty_plts }}</p>
<p>CBM Of Delivery: {{ booking_detail.cbm }}</p>
<p>Delivery Date: {{ booking_detail.delivery_date }}</p>
<p>Delivery Time: {{ booking_detail.delivery_time }}</p>
{% endif %}
</div>
<div class="container">
<a class="btn btn-primary" href="{% url 'bookmyslot:update' pk=booking_detail.pk %}">Update Booking</a>
<a class="btn btn-danger" href="{% url 'bookmyslot:delete' pk=booking_detail.pk %}">Delete Booking</a>
</div>
{% endblock %}
您可以使用动态@property来检查预订是否在交货日期后不到7天内完成:
models.pyfrom datetime import date, timedelta
class Booking(models.Model):
# ...
@property
def can_be_altered(self):
"""Return True if delivery_date - 7 days >= 0 else return False"""
return self.delivery_date - date.today() >= timedelta(7)
booking_detail.html
<!-- Disable button if can not be altered -->
<!-- You can replace the button with a warning message too -->
<div class="container">
<a class="btn btn-primary" {% if booking_detail.can_be_altered is not True %} disabled {% endif %} href="{% url 'bookmyslot:update' pk=booking_detail.pk %}">Update Booking</a>
<a class="btn btn-danger" {% if booking_detail.can_be_altered is not True %} disabled {% endif %} href="{% url 'bookmyslot:delete' pk=booking_detail.pk %}">Delete Booking</a>
{% if booking_detail.can_be_altered is not True %}
<small class="form-text text-muted text-warning">You can not delete or update this booking within 7 days before delivery date </small>
{% endif %}
</div>