Django汽车清洗项目:模型关系设计与数据库分表咨询
Django汽车清洗项目模型设计与分表方案解答
问题1:SetOfServices的关联关系与套餐总价自动计算
关联关系选择
不能用ForeignKey,一个套餐包含多个SingleService,同时一个SingleService也可被多个套餐复用,属于**多对多(ManyToMany)**关联场景,应使用ManyToManyField定义关联。
套餐总价自动计算
两种常用实现方式:
- 保存时自动计算并存库:适合需频繁查询总价、后台直接展示的场景,通过重写模型
save方法或Django信号实现。 - 动态计算(不存库):用
@property装饰器实时计算,适合总价变化频繁、无需持久化的场景。
代码示例
from django.db import models # 服务类型选项 SERVICES = ( ('exterior', '外部清洗'), ('interior', '内饰清洁'), ('wax', '打蜡'), # 其他服务类型... ) class SingleService(models.Model): name = models.CharField(max_length=100) service_type = models.CharField(max_length=20, choices=SERVICES) price = models.DecimalField(max_digits=8, decimal_places=2) def __str__(self): return self.name class SetOfServices(models.Model): name = models.CharField(max_length=100) set_of_services = models.ManyToManyField(SingleService, related_name='service_sets') price_of_set = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True) def save(self, *args, **kwargs): # 计算关联服务的总价 total = self.set_of_services.aggregate(total=models.Sum('price'))['total'] or 0 self.price_of_set = total super().save(*args, **kwargs) def __str__(self): return self.name
复杂场景用信号实现:
from django.db.models.signals import m2m_changed from django.dispatch import receiver @receiver(m2m_changed, sender=SetOfServices.set_of_services.through) def update_set_price(sender, instance, **kwargs): total = instance.set_of_services.aggregate(total=models.Sum('price'))['total'] or 0 instance.price_of_set = total instance.save()
问题2:PostgreSQL中Django模型分表方案
通过db_table参数指定模型对应数据库表名即可实现分表,关联关系无需特殊修改,Django会自动识别目标模型的db_table并生成正确的SQL关联语句。
分表场景示例
按业务维度拆分Purchase模型为普通客户订单和VIP客户订单,或按时间维度拆分年度订单。
代码示例
- 定义抽象基类(避免重复代码):
from django.db import models class BasePurchase(models.Model): customer = models.ForeignKey('Customer', on_delete=models.CASCADE) service_set = models.ForeignKey(SetOfServices, on_delete=models.CASCADE) payment_amount = models.DecimalField(max_digits=10, decimal_places=2) purchase_time = models.DateTimeField(auto_now_add=True) class Meta: abstract = True
- 分表模型实现:
class RegularPurchase(BasePurchase): class Meta: db_table = 'car_wash_regular_purchase' # 指定PostgreSQL表名 class VIPPurchase(BasePurchase): discount_rate = models.DecimalField(max_digits=3, decimal_places=2, default=0.8) # VIP专属字段 class Meta: db_table = 'car_wash_vip_purchase'
- 按区域拆分客户模型:
class Customer(models.Model): name = models.CharField(max_length=100) car_info = models.CharField(max_length=200) # 其他字段... class Meta: abstract = True class NorthCustomer(Customer): class Meta: db_table = 'car_wash_north_customer' class SouthCustomer(Customer): class Meta: db_table = 'car_wash_south_customer'
关联关系注意事项
- 外键直接指向分表后的模型即可,Django自动处理跨表关联。
- 跨分表查询需手动指定目标模型,也可自定义管理器统一查询逻辑。
- 迁移文件会自动为每个分表模型生成建表语句,执行迁移后PostgreSQL将创建独立表。
内容的提问来源于stack exchange,提问作者PrertoQuebas
相关产品推荐
相关产品推荐

