Django模型一对多关系设计:多电话/邮箱的公司信息存储咨询
Django模型设计:支持一家公司多个电话/邮箱
嘿,我来帮你梳理下这个问题~你现在的需求是一个城市对应多家公司,每家公司可以有多个电话和邮箱,但之前的模型设计没法满足“多联系方式”的需求对吧?先看看你原来的代码:
class City(models.Model): name = models.CharField(max_length=200, blank=True, null=True) class CompanyDetails(models.Model): com_name = models.ForeignKey(City) email = models.EmailField(max_length=100, blank=True, null=True) mobile_number = models.CharField(max_length=10, blank=True, null=True)
这个设计的问题在于,一家公司如果有多个电话或邮箱,就得创建多条CompanyDetails记录,但这样既没法明确区分“同一家公司”的多条记录,还把公司基础信息和联系方式混在了一起,显然不太合理。
优化后的模型设计思路
我们需要拆分出三个核心模型,清晰划分层级,完美适配你的业务场景:
1. 城市模型(City)
这个和你原来的思路一致,不过建议把城市名设为必填项(毕竟城市不该是空的):
class City(models.Model): name = models.CharField(max_length=200, blank=False, null=False) def __str__(self): return self.name
2. 公司模型(Company)
单独存储公司的基础信息,和所属城市关联:
class Company(models.Model): name = models.CharField(max_length=200, blank=False, null=False) city = models.ForeignKey(City, on_delete=models.CASCADE, related_name="companies") # related_name可以让你从City对象反向查询它下面的所有公司,比如city.companies.all() def __str__(self): return self.name
3. 联系方式模型(ContactInfo)
专门用来存储单个的电话或邮箱,通过外键绑定到对应的公司,还加了一个类型字段区分是电话还是邮箱:
class ContactInfo(models.Model): # 定义联系方式的类型选项 CONTACT_TYPES = ( ('phone', 'Phone Number'), ('email', 'Email Address'), ) company = models.ForeignKey(Company, on_delete=models.CASCADE, related_name="contacts") contact_type = models.CharField(max_length=10, choices=CONTACT_TYPES) value = models.CharField(max_length=100, blank=False, null=False) # 用value统一存储电话或邮箱的内容,不用分开字段,更灵活 def __str__(self): return f"{self.get_contact_type_display()}: {self.value}"
这样设计的好处
- 层级清晰:城市→公司→联系方式,完全匹配你描述的业务逻辑
- 扩展性强:以后如果要加微信、地址这类新的联系方式,只需要在
CONTACT_TYPES里加个选项就行,不用改模型结构 - 查询便捷:通过
related_name可以轻松获取某家公司的所有联系方式,比如:# 示例:获取city1下company1的所有联系方式 target_company = Company.objects.get(name="company1", city__name="city1") all_contacts = target_company.contacts.all()
对应你期望的存储格式
这样设计后,你可以通过查询轻松把数据组合成你想要的格式:
< city1, company1:[phone1, email1] >
< city1, company2:[phone1, email2, phone3] >
比如遍历公司的时候,把它的所有contacts的value字段收集起来,就能得到这个结构啦。
内容的提问来源于stack exchange,提问作者Prashant
相关产品推荐
相关产品推荐

