首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python 学习手册
Python Cookbook
Python 基础教程
Python Sites
PyPI - Python Package Index
http://www.simple-is-better.com/
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
华为云
V2EX  ›  Python

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

  •  
  •   GPU · 9 天前 · 683 次点击

    一个域名监控

    思路如下

    域名 -> 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)
    
    
    9 回复  |  直到 2018-11-09 23:27:19 +08:00
        1
    matrix1010   9 天前 via Android
    方法 1,ipv4address 和 ipv6address 都加 domain 的 foreignkey, 再加个 related_name
        2
    GPU   9 天前
    @matrix1010 #1
    有个问题是 域名有可能会有多个 IP , IP 也有可能会有多个域名 .
    找你说的设计也好像有问题
    Domain 类的 ip 属性好像不能同时指定 ipv4 和 ipv6
        3
    matrix1010   9 天前 via Android
    我的意思是 domain 里的 ip field 可以删了, 直接用 related name 反查,比如 domain.ipv4_address。不过一个 ip 对多个 domain 有点奇怪
        4
    syhsyh9696   9 天前 via Android
    django 我不太熟,但是你这个需求应该有点像 rails has_and_belongs_to_many,在 rails 中是通过一张没有主键的表来完成的,表中存放着两方的 ID (主键)
        5
    GPU   9 天前
    @matrix1010 #3
    这样子做好像也实现不知到
    域名有可能会有多个 IP , IP 也有可能会有多个域名 .
        6
    37Y37   9 天前
    只需要 ip 的 FK 换成 M2M 即可,能表示一个域名有多个 ip,一个 ip 有多个域名,关于查询可以看这个:
    https://mp.weixin.qq.com/s/JVh4UnS2Tql9gUVaBSoGuA
        7
    GPU   9 天前
    @37Y37 #6 也就是要用方法二这种数据库模型了?
        8
    xpresslink   9 天前
    我觉得楼主把问题复杂化了。
    楼主学习一上 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 出多条记录就可以了。
        9
    GPU   9 天前
    @xpresslink #8
    对哦 还可以这样
    现在这个逻辑想来想去太复杂了
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   3526 人在线   最高记录 3821   ·  
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.1 · 18ms · UTC 02:47 · PVG 10:47 · LAX 18:47 · JFK 21:47
    ♥ Do have faith in what you're doing.
    沪ICP备16043287号-1