Django:多对多订购

时间:2019-05-22 11:29:41

标签: django many-to-many

我有许多服务器通过ip关系联网:

class Server(models.Model):
    hostname = models.CharField(max_length=50)
    networks = models.ManyToManyField(Network, through='Ip')

class Network(models.Model):
    name = models.CharField(max_length=50)

class Ip(models.Model):
    ip = models.CharField(max_length=20)
    server = models.ForeignKey(Server) # initially this line was missing

我将其渲染到表格中

Hostname | Network 1 | Network 2
==============================
server 1 | 1.1.1.10  | 5.5.5.100
server 2 | 1.1.1.15  | 5.5.5.20

我需要将此表按列排序。按列排序很容易:

Server.objecs.all().order_by('hostname')

如何对其他两列进行相同操作?例如。如果按“网络2”列对表进行排序,则顺序为“服务器2,服务器1”。

编辑:更正了代码。

2 个答案:

答案 0 :(得分:0)

如果要在 Django 中订购多对多表,则需要中间模型(首先)。您的IP模式不好(IMO)。完全没有完成。

class Server(models.Model):
    hostname = models.CharField(max_length=50)
    networks = models.ManyToManyField(to='Network', through='ServerNetworkRel')

    class Meta:
        db_table = 'server'

    def __str__(self):
        return self.hostname

class Network(models.Model):
    name = models.CharField(max_length=50)


    class Meta:
        db_table = 'network'

    def __str__(self):
        return self.name

class ServerNetworkRel(models.Model):
    ip = models.CharField(max_length=20)
    server = models.ForeignKey(to=Server, on_delete=models.PROTECT)
    network = models.ForeignKey(to=Network, on_delete=models.PROTECT)

    class Meta:
        db_table = 'server_network_rel'

    def __str__(self):
        return self.server.hostname + ' ' + self.network.name

并立即执行sql查询

filtered_rows = ServerNetworkRel.objects.select_related('server', 'network').order_by('network__field') # This returns ServerNetworkRel which has already made INNER JOIN On (Server and Network)

for row in filtered_rows:
    print(row.server) # returns Server instance
    print(row.network) # returns Network instance

答案 1 :(得分:0)

好的,这是我设法做到的方式:

首先,我们需要将queryset转换为list:

qs = Server.objects.all()
net = Network.objects.get(pk=1) # we gonna sort servers by ip in this network
list = [x for x in qs]

list = list(qs)

然后我们可以对该列表进行排序。并非所有服务器在每个网络中都有ip,因此我们需要检查ip是否不是None:

list.sort(key=lambda x: x.ip_set.filter(network=net).first().ip if x.ip_set.filter(network=net).first() is not None else 0)