Django中如何将两个模型字段拼接后赋值给第三个模型字段
Django配送预约系统编号生成实现方案
现有代码问题修正
首先需要先修复现有代码的两处错误,否则功能无法正常运行:
- forms.py中
BookingForm的Meta.fields字段配置错误:你写的booking_date、booking_time和模型中定义的delivery_date、delivery_time字段名不匹配,需要同步修改。 - 不要把
booking_number的赋值逻辑放在__str__方法中,该方法仅用于返回实例的字符串标识,不会在数据入库时触发,赋值逻辑需要放在模型的save()方法中。
核心功能实现
你需要重写Booking模型的save方法,在数据写入数据库前自动拼接日期时间生成预约编号,修改后的完整models.py代码如下:
from django.db import models from django.utils import timezone from django.urls import reverse import datetime as dt from django.contrib.auth.models import User class Booking(models.Model): user = models.ForeignKey(User,on_delete=models.CASCADE) qty_plts = models.PositiveSmallIntegerField(default=1) cbm = models.PositiveSmallIntegerField(default=1) # 注意这里default不要加括号,否则会固定为项目启动时间 created_date = models.DateTimeField(default=timezone.now) delivery_date = models.DateTimeField() delivery_time = models.TimeField() booking_number = models.CharField(max_length=50, unique=True) def save(self, *args, **kwargs): # 拼接配送日期和时间为完整datetime对象 full_datetime = dt.datetime.combine(self.delivery_date.date(), self.delivery_time) # 按DDMMYYYYHHMM格式生成编号,要带分隔符就改成"%d-%m-%Y-%H-%M" self.booking_number = full_datetime.strftime("%d%m%Y%H%M") super().save(*args, **kwargs) def __str__(self): return self.booking_number def get_absolute_url(self): return reverse("booking_detail",kwargs={'pk':self.pk})
修正后的forms.py代码如下:
from django import forms from bookmyslot.models import Booking from bootstrap_datepicker_plus import DatePickerInput import datetime as dt HOUR_CHOICES = [(dt.time(hour=x), '{:02d}:00'.format(x)) for x in range(7, 13)] class BookingForm(forms.ModelForm): class Meta: model = Booking # 修正字段名匹配模型定义 fields = ('qty_plts','cbm','delivery_date','delivery_time') widgets = {'delivery_date':DatePickerInput(options={"daysOfWeekDisabled":[0,6]}), 'delivery_time':forms.Select(choices=HOUR_CHOICES)}
预约编号唯一性保障
如果你的业务允许同一时段多个用户预约,直接按上述代码生成的编号会重复,你可以选择两种方案解决:
- 方案1:给
delivery_date和delivery_time添加联合唯一约束,限制同一时段只能有一个预约,天然保证编号唯一,只需要在Booking模型中添加如下配置即可:class Meta: constraints = [ models.UniqueConstraint(fields=['delivery_date', 'delivery_time'], name='unique_delivery_slot') ] - 方案2:保留同一时段多预约的能力,在生成编号时追加用户ID后缀,修改save方法中的编号生成逻辑即可:
self.booking_number = f"{full_datetime.strftime('%d%m%Y%H%M')}-{self.user.id}"
内容的提问来源于stack exchange,提问作者logicpro
相关产品推荐
相关产品推荐

