Django模型一对多关联字段选型与关系配置问题
解决方案
你的业务场景是单条网站分类关联多个域名,属于关联关系映射场景,根据域名是否可以归属多个分类,有两种配置方式,配置完成后都可以在查询分类时直接拿到关联域名列表。
场景1:单个域名仅归属一个分类(一对多关系,最常用)
一对多关系的外键需要定义在「多」的一侧,也就是Domain模型中,不要在WebClassification模型里加关联字段,你之前的字段定义位置写反了。
修正后的模型代码
- Domain 模型(Domain.py)
from django.db import models class Domain(models.Model): # 注意:你原代码自定义id字段漏了primary_key=True参数,不写的话Django还是会自动生成id主键 id = models.IntegerField(primary_key=True) domain_name = models.CharField(max_length=200) # 新增外键关联网站分类 web_classification = models.ForeignKey( "WebClassification", on_delete=models.CASCADE, # related_name 定义反向查询时的属性名,后续查分类下的域名就靠这个 related_name="domain_list", null=True, blank=True ) def __str__(self): return self.domain_name
- WebClassification 模型(Model.py)
把原来占位的domain_name字段直接删除即可,不需要在这个模型里存域名关联:
from django.db import models class WebClassification(models.Model): vendor_id = models.ForeignKey(Vendor, on_delete=models.CASCADE, default=None, null=True) id = models.IntegerField(primary_key=True) name = models.CharField(max_length=100) description = models.CharField(max_length=1000) # 删除原有的 domain_name 字段 def __str__(self): return self.name
查询方式
- 单条分类查询时直接取关联域名:
# 获取id=1的分类 category = WebClassification.objects.get(id=1) # 直接拿到该分类下所有关联域名的QuerySet,支持遍历、过滤、序列化 related_domains = category.domain_list.all()
- 批量查询分类时如果要避免N+1查询问题,加预加载即可:
# 一次性预加载所有分类的关联域名,后续取domain_list不会额外触发SQL查询 category_list = WebClassification.objects.all().prefetch_related("domain_list") for cat in category_list: print(cat.name, cat.domain_list.all())
场景2:单个域名可归属多个分类(多对多关系)
如果你的业务允许同一个域名绑定到多个网站分类,直接在WebClassification模型里加多对多字段即可,Django会自动生成中间关联表,不需要手动建关联字段。
模型配置
在WebClassification类里新增字段:
domain_list = models.ManyToManyField( Domain, related_name="category_list", blank=True )
查询方式和一对多完全一致,直接通过category.domain_list.all()就能拿到当前分类下的所有域名。
注意:模型修改完成后需要执行
python manage.py makemigrations和python manage.py migrate命令同步数据库结构。
内容的提问来源于stack exchange,提问作者Mukul
相关产品推荐
相关产品推荐

