Django中Date、Construction_site与Machinery模型关系及查询问题
Django建筑日程应用模型关系调整方案
现有模型的问题
- 单独的
Date模型没必要,Django的DateField可以直接存储日期,单独建表会增加关联复杂度 - 模型命名不符合Django规范(应使用驼峰式,比如
ConstructionSite而非Construction_site),字段名也容易混淆(比如construction_site_name作为多对多字段名,不如直接叫sites清晰) - 现有关联下查询机械需要通过反向关联,容易出错
方案一:调整现有模型实现需求
先修正模型命名和关联关系,让查询更顺畅:
from django.db import models # 重命名为DateEntry避免和内置date类型冲突,同时设置日期唯一 class DateEntry(models.Model): date = models.DateField(unique=True) def __str__(self): return str(self.date) class ConstructionSite(models.Model): name = models.CharField(max_length=50) # 用related_name指定反向关联名称,避免默认的construction_site_set dates = models.ManyToManyField(DateEntry, related_name='sites') def __str__(self): return self.name class Machinery(models.Model): name = models.CharField(max_length=50) # 同样用related_name指定反向关联,方便从工地查机械 sites = models.ManyToManyField(ConstructionSite, related_name='machineries') def __str__(self): return self.name
视图查询代码
def date_schedule(request): # 获取指定日期的条目 target_date = DateEntry.objects.get(id=1) # 通过related_name直接拿到该日期下的所有工地 construction_sites = target_date.sites.all() # 预加载工地对应的机械,减少数据库查询次数 construction_sites = construction_sites.prefetch_related('machineries') return render(request, 'schedule.html', {'construction_sites': construction_sites})
模板示例(schedule.html)
{% for site in construction_sites %} <h2>{{ site.name }}</h2> <h3>当日使用机械:</h3> <ul> {% for machine in site.machineries.all %} <li>{{ machine.name }}</li> {% endfor %} </ul> {% endfor %}
方案二:更贴合业务逻辑的模型重构
考虑到业务是「每日施工安排」,可以直接建立每日安排模型,关联日期、工地和机械,逻辑更清晰:
from django.db import models class ConstructionSite(models.Model): name = models.CharField(max_length=50) def __str__(self): return self.name class Machinery(models.Model): name = models.CharField(max_length=50) def __str__(self): return self.name class DailySchedule(models.Model): date = models.DateField() # 外键关联工地,一个安排对应一个工地 site = models.ForeignKey(ConstructionSite, on_delete=models.CASCADE, related_name='daily_schedules') # 多对多关联机械,一个工地一天可用多台机械 machines = models.ManyToManyField(Machinery, related_name='assigned_schedules') class Meta: # 确保同一个工地同一天只有一条安排 unique_together = ('date', 'site') def __str__(self): return f"{self.date} - {self.site.name}"
视图查询代码
def date_schedule(request): # 可以直接用日期字符串查询,比如'2024-05-20' target_date = '2024-05-20' # 预加载工地和机械,提升查询效率 schedules = DailySchedule.objects.filter(date=target_date).select_related('site').prefetch_related('machines') return render(request, 'schedule.html', {'schedules': schedules})
模板示例(schedule.html)
{% for schedule in schedules %} <h2>{{ schedule.site.name }}</h2> <h3>日期:{{ schedule.date }}</h3> <h3>使用机械:</h3> <ul> {% for machine in schedule.machines.all %} <li>{{ machine.name }}</li> {% endfor %} </ul> {% endfor %}
内容的提问来源于stack exchange,提问作者Teofilex
相关产品推荐
相关产品推荐

