【问题标题】:How to correctly query to a Foreign Key in Django?如何正确查询 Django 中的外键?
【发布时间】:2023-03-14 20:52:01
【问题描述】:

我有一组模型ClusterServerService,通过 ForeignKey,一对多,如下 sn-p:

class Server(models.Model):
    cluster = models.ForeignKey(Cluster, null=True, on_delete=models.PROTECT)
    shortname = models.CharField(max_length=20, null=False)
    .
    .
    .


class Service(models.Model):
    host_server = models.ForeignKey(Server, null=False, on_delete=models.PROTECT)
    name = models.CharField(max_length=20, null=False)
    technology = models.CharField(max_length=20, null=False)
    .
    .
    .

现在我正在尝试在查询中获取一组Servers,以及相关的Services 使用

def infra(request, cluster_name):

    cluster = Cluster.objects.get(name__iexact=cluster_name)
    servers = Server.objects.filter(cluster_id=cluster.id).order_by('shortname')
    services = Service.objects.filter(host_server__in=servers).order_by('id')

    template = 'webapp/infra.html'
    context = {
        'cluster':cluster,
        'servers':servers,
        'services':services,
        }
    return render(request, template, context)

但是,在视图中,我在单个 QuerySet 中获取所有服务,而不是每个 Server 的 QuerySet,其中仅包含与之关联的 Services

作为解决方法,我使用了以下方法:

<h5>Services</h5>
  <ul class="list-group">
    {% for service in services %}
      {% if service.host_server_id == server.id %}
        <li class="list-group-item">{{ service.name }}</li>
      {% endif %}
    {% endfor %}
  </ul>

但我有一种感觉,必须有一种方法可以更优雅地遍历每个服务器的服务,而不是每次都遍历所有服务,然后决定是否应该取消显示。

是否有可能改进或者这种初始方法是否正确?

谢谢!

【问题讨论】:

    标签: django foreign-keys django-queryset


    【解决方案1】:

    为您的host_server 字段定义一个related_name,并利用Django's Reverse ForeignKey Manager 为每个服务器获取关联的服务。

    注意:如果没有 related_name,则可以从 service_set 访问反向管理器

    models.py

    class Service(models.Model):
        host_server = models.ForeignKey(Server, null=False, on_delete=models.PROTECT, related_name="services")
    

    views.py

    def infra(request, cluster_name):
    
        cluster = Cluster.objects.get(name__iexact=cluster_name)
        # we use `prefetch_related` to speedup the query
        servers = Server.objects.filter(cluster_id=cluster.id).prefetch_related('services').order_by('shortname')
        return render(request, 'webapp/infra.html', {
            'cluster':cluster,
            'servers':servers,
        })
    

    infra.html

    
      <ul class="list-group">
        {% for server in servers %}
          <li class="list-group-item">{{ server.name }}
            <ul>
            {% for service in server.services.all %}
              <li class="list-item">{{ service.name }}</li>
            {% endfor %}
            </ul>
          </li>
        {% endfor %}
      </ul>
    

    【讨论】:

    • 谢谢!这绝对是我想要达到的目标。我什至浏览了你提到的参考资料,但这个例子没有你的那么清楚。
    猜你喜欢
    • 2014-02-04
    • 2011-02-01
    • 2018-09-01
    • 2020-07-18
    • 2015-03-09
    • 1970-01-01
    • 1970-01-01
    • 2021-06-03
    • 1970-01-01
    相关资源
    最近更新 更多