V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
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
GPU
V2EX  ›  Python

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

  •  
  •   GPU · 2018-11-09 15:45:53 +08:00 · 1907 次点击
    这是一个创建于 2201 天前的主题,其中的信息可能已经有所发展或是发生改变。

    一个域名监控

    思路如下

    域名 -> 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
    matrix1010
        1
    matrix1010  
       2018-11-09 19:39:07 +08:00 via Android
    方法 1,ipv4address 和 ipv6address 都加 domain 的 foreignkey, 再加个 related_name
    GPU
        2
    GPU  
    OP
       2018-11-09 21:02:46 +08:00
    @matrix1010 #1
    有个问题是 域名有可能会有多个 IP , IP 也有可能会有多个域名 .
    找你说的设计也好像有问题
    Domain 类的 ip 属性好像不能同时指定 ipv4 和 ipv6
    matrix1010
        3
    matrix1010  
       2018-11-09 21:32:36 +08:00 via Android
    我的意思是 domain 里的 ip field 可以删了, 直接用 related name 反查,比如 domain.ipv4_address。不过一个 ip 对多个 domain 有点奇怪
    syhsyh9696
        4
    syhsyh9696  
       2018-11-09 21:38:45 +08:00 via Android
    django 我不太熟,但是你这个需求应该有点像 rails has_and_belongs_to_many,在 rails 中是通过一张没有主键的表来完成的,表中存放着两方的 ID (主键)
    GPU
        5
    GPU  
    OP
       2018-11-09 21:41:53 +08:00
    @matrix1010 #3
    这样子做好像也实现不知到
    域名有可能会有多个 IP , IP 也有可能会有多个域名 .
    37Y37
        6
    37Y37  
       2018-11-09 21:46:59 +08:00
    只需要 ip 的 FK 换成 M2M 即可,能表示一个域名有多个 ip,一个 ip 有多个域名,关于查询可以看这个:
    https://mp.weixin.qq.com/s/JVh4UnS2Tql9gUVaBSoGuA
    GPU
        7
    GPU  
    OP
       2018-11-09 21:59:59 +08:00
    @37Y37 #6 也就是要用方法二这种数据库模型了?
    xpresslink
        8
    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
        9
    GPU  
    OP
       2018-11-09 23:27:19 +08:00
    @xpresslink #8
    对哦 还可以这样
    现在这个逻辑想来想去太复杂了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3851 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 10:28 · PVG 18:28 · LAX 02:28 · JFK 05:28
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.