Django 数据库模型 一对多、多对多问题疑惑

2018-11-09 15:45:53 +08:00
 GPU

一个域名监控

思路如下

域名 -> IP -> IP 段

但是 IP 与 IP 段都分别有 v4 与 v6 的 且域名可能同时拥有 v4 与 v6 的 IP

想了半天也不知道怎么去设计

看了很多 Django 的多对多(ManyToManyField) 的文章也弄不懂

如下代码 Domain 类里面的属性 ip 是不是应该用多对多的方式

方法一的代码是不是不应该这样子写的

方法一

class IPv4Range(models.Model):
    ipv4_range = models.CharField(max_length=20)
    last_update = models.DateTimeField(auto_now_add=True)


class IPv6Range(models.Model):
    ipv6_range = models.CharField(max_length=40)
    last_update = models.DateTimeField(auto_now_add=True)


class IPv4Address(models.Model):
    iprange = models.ForeignKey('IPv4Range', on_delete=models.PROTECT)
    ipv4 = models.CharField(max_length=20)
    last_update = models.DateTimeField(auto_now_add=True)
    

class IPv6Address(models.Model):
    iprange = models.ForeignKey('IPv6Range', on_delete=models.PROTECT)
    ipv6 = models.CharField(max_length=40)
    last_update = models.DateTimeField(auto_now_add=True)
    

class Domain(models.Model):
    ip = models.ForeignKey(IPv4Address, on_delete=models.PROTECT)
    domain = models.CharField(max_length=255)
    checked = models.BooleanField(default=False)
    keyword = models.CharField(max_length=255)
    add_date = models.DateTimeField(auto_now_add=True)
    last_update = models.DateTimeField(auto_now=True)

方法二

class IPRange(models.Model):
    ipv4_range = models.CharField(max_length=20, null=True)
    ipv6_range = models.CharField(max_length=40, null=True)
    last_update = models.DateTimeField(auto_now_add=True)



class IPAddress(models.Model):
    iprange = models.ForeignKey('IPRange', on_delete=models.PROTECT)
    ipv4 = models.CharField(max_length=20, null=True)
    ipv6 = models.CharField(max_length=40, null=True)
    last_update = models.DateTimeField(auto_now_add=True)
    


class Domain(models.Model):
    ip = models.ForeignKey(IPAddress, on_delete=models.PROTECT)
    domain = models.CharField(max_length=255)
    checked = models.BooleanField(default=False)
    keyword = models.CharField(max_length=255)
    add_date = models.DateTimeField(auto_now_add=True)
    last_update = models.DateTimeField(auto_now=True)

1910 次点击
所在节点    Python
9 条回复
matrix1010
2018-11-09 19:39:07 +08:00
方法 1,ipv4address 和 ipv6address 都加 domain 的 foreignkey, 再加个 related_name
GPU
2018-11-09 21:02:46 +08:00
@matrix1010 #1
有个问题是 域名有可能会有多个 IP , IP 也有可能会有多个域名 .
找你说的设计也好像有问题
Domain 类的 ip 属性好像不能同时指定 ipv4 和 ipv6
matrix1010
2018-11-09 21:32:36 +08:00
我的意思是 domain 里的 ip field 可以删了, 直接用 related name 反查,比如 domain.ipv4_address。不过一个 ip 对多个 domain 有点奇怪
syhsyh9696
2018-11-09 21:38:45 +08:00
django 我不太熟,但是你这个需求应该有点像 rails has_and_belongs_to_many,在 rails 中是通过一张没有主键的表来完成的,表中存放着两方的 ID (主键)
GPU
2018-11-09 21:41:53 +08:00
@matrix1010 #3
这样子做好像也实现不知到
域名有可能会有多个 IP , IP 也有可能会有多个域名 .
37Y37
2018-11-09 21:46:59 +08:00
只需要 ip 的 FK 换成 M2M 即可,能表示一个域名有多个 ip,一个 ip 有多个域名,关于查询可以看这个:
https://mp.weixin.qq.com/s/JVh4UnS2Tql9gUVaBSoGuA
GPU
2018-11-09 21:59:59 +08:00
@37Y37 #6 也就是要用方法二这种数据库模型了?
xpresslink
2018-11-09 23:22:24 +08:00
我觉得楼主把问题复杂化了。
楼主学习一上 DNS 解析原理,仿照 DNS 数据库直接弄个解析记录表就可以了
域名和 IP 本身都是有唯一性的,没必要再外键一下了。其实就在一个模型就行

域名,记录类型,主机 IP 只要这三个字段,记录类型表示后面的主机 IP 类型,A:V4 ,AAAA:V6
一个域名多个 IP,就多条记录
abc.com, A, 123.2.4.12
abc.com, A, 34,12,22,45
abc.com, AAAA, as234:345345:345
def.com, A, 56.7.8.9
ghj.com, A, 78.1.2.3

查询时直接用 domain 或 IP 来 filter 出多条记录就可以了。
GPU
2018-11-09 23:27:19 +08:00
@xpresslink #8
对哦 还可以这样
现在这个逻辑想来想去太复杂了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/506152

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX