我正在与Django建立一个个人项目来训练自己(因为我爱Django,但我错过了技能)。我有基本的要求,我知道Python,即使没有三次,我也仔细阅读了Django的书两次。
我的目标是使用基于Django的Web界面创建一个简单的监视服务,使我可以检查“节点”(服务器)的状态。每个节点都有多个“服务”。该应用程序检查每个节点的每个服务的可用性。
我的问题是我不知道如何在数据库中表示不同类型的服务。我想到了两个“解决方案”:
这是我的 models.py 文件的简短摘录:(我删除了与此问题无关的所有内容)
from django.db import models # Create your models here. class service(models.Model): port = models.PositiveIntegerField() class Meta: abstract = True class sshService(service): username = models.CharField(max_length=64) pkey = models.TextField() class telnetService(service): username = models.CharField(max_length=64) password = models.CharField(max_length=64) class genericTcpService(service): pass class genericUdpService(service): pass class node(models.Model): name = models.CharField(max_length=64) # various fields services = models.ManyToManyField(service)
当然,ManyToManyField的行是伪造的。我不知道该用什么代替“ *服务”。我老实地搜索了有关此问题的解决方案,听说过“通用关系”,三联接表,但是我并没有真正理解这些东西。
而且,英语不是我的母语,因此在数据库结构和语义方面,我对所读内容的了解和理解是有限的(但这就是我的问题)
首先,请使用Django的多表继承,而不要使用当前使用的抽象模型。
您的代码将变为:
from django.db import models class Service(models.Model): port = models.PositiveIntegerField() class SSHService(Service): username = models.CharField(max_length=64) pkey = models.TextField() class TelnetService(Service): username = models.CharField(max_length=64) password = models.CharField(max_length=64) class GenericTcpService(Service): pass class GenericUDPService(Service): pass class Node(models.Model): name = models.CharField(max_length=64) # various fields services = models.ManyToManyField(Service)
在数据库级别,这将创建一个“服务”表,该表的行将通过一对一关系与每个子服务的单独表链接在一起。
这种方法的唯一困难是,当您执行以下操作时:
node = Node.objects.get(pk=node_id) for service in node.services.all(): # Do something with the service
您在循环中访问的“服务”对象将是父类型。如果您事先知道这些子类型将是哪种类型,则可以通过以下方式访问该子类:
from django.core.exceptions import ObjectDoesNotExist try: telnet_service = service.telnetservice except (AttributeError, ObjectDoesNotExist): # You chose the wrong child type! telnet_service = None
如果您事先不知道子类型,则它会变得有些棘手。有一些hacky / messy解决方案,包括父模型上的“ serviceType”字段,但是,如Joe J所提到的,更好的方法是使用“子类化查询集”。django-model- utils中的InheritanceManager类可能是最容易使用的。在这里阅读文档,这是一段非常不错的代码。