You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django中如何在单个HTML表格展示站点过滤的多设备模型数据?

解决Django多模型数据在单个表格渲染的问题

问题根源

  1. 请求方式不匹配:模板1通过<a>标签跳转属于GET请求,但你的ReportView仅实现了post方法,无法处理该请求。
  2. 上下文变量覆盖:多次给context["site"]赋值会导致后续值覆盖前序值,最终仅保留打印机数据。
  3. 查询方法错误:get()仅能返回单个对象,若站点下存在多个同类型设备会抛出异常,应使用filter()获取查询集。
  4. 参数处理逻辑缺失:URL传入的是站点名称,需先找到对应的Site对象,再用该对象过滤关联设备。

修正后的代码

1. 视图层(ReportView)

from django.views.generic import TemplateView
from .models import Site, Workstation, Laptop, Printer

class ReportView(TemplateView):
    template_name = "mytestapp/report.html"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        # 从URL参数获取站点名称,匹配对应Site对象
        site_name = kwargs.get('sitename')
        target_site = Site.objects.get(site_name=site_name)
        
        # 获取该站点下所有设备并合并为列表
        workstations = Workstation.objects.filter(sitename=target_site)
        laptops = Laptop.objects.filter(sitename=target_site)
        printers = Printer.objects.filter(sitename=target_site)
        
        context['devices'] = list(workstations) + list(laptops) + list(printers)
        context['current_site'] = target_site  # 传递站点信息用于页面展示
        return context

2. 模板层(report.html)

首先在模板顶部加载自定义过滤器:

{% load device_tags %}

然后编写表格代码:

<h2>{{ current_site.site_name }} 设备清单</h2>
<table>
    <tr>
        <th>设备类型</th>
        <th>设备名称</th>
        <th>序列号</th>
        <th>型号</th>
    </tr>
    {% for device in devices %}
    <tr>
        <!-- 判断设备类型并显示 -->
        <td>
            {% if device|instanceof:"Workstation" %}工作站
            {% elif device|instanceof:"Laptop" %}笔记本电脑
            {% elif device|instanceof:"Printer" %}打印机
            {% endif %}
        </td>
        <td>{{ device.name }}</td>
        <td>{{ device.serial }}</td>
        <td>
            <!-- 显示对应型号字段 -->
            {% if device|instanceof:"Workstation" %}{{ device.workstation_model }}
            {% elif device|instanceof:"Laptop" %}{{ device.laptop_model }}
            {% elif device|instanceof:"Printer" %}{{ device.printer_model }}
            {% endif %}
        </td>
    </tr>
    {% empty %}
    <tr>
        <td colspan="4">该站点暂无设备记录</td>
    </tr>
    {% endfor %}
</table>

3. 自定义模板过滤器(instanceof)

在app目录下创建templatetags文件夹,添加以下两个文件:

  • templatetags/__init__.py(空文件即可)
  • templatetags/device_tags.py:
from django import template
from mytestapp.models import Workstation, Laptop, Printer

register = template.Library()

@register.filter
def instanceof(value, model_name):
    model_map = {
        'Workstation': Workstation,
        'Laptop': Laptop,
        'Printer': Printer
    }
    return isinstance(value, model_map.get(model_name))

可选优化:模型抽象基类

三个设备模型字段高度重复,可通过抽象基类减少代码冗余:

from django.db import models

class Device(models.Model):
    name = models.CharField(max_length=30, blank=True, null=True)
    serial = models.CharField(max_length=30, blank=True, null=True)
    sitename = models.ForeignKey(Site, on_delete=models.SET_NULL, blank=True, null=True, verbose_name="Site")
    
    class Meta:
        abstract = True

class Workstation(Device):
    workstation_model = models.CharField(max_length=30, blank=True, null=True, verbose_name="Workstation Model")
    
    def __str__(self):
        return self.name

class Laptop(Device):
    laptop_model = models.CharField(max_length=30, blank=True, null=True, verbose_name="Laptop Model")
    
    def __str__(self):
        return self.name

class Printer(Device):
    printer_model = models.CharField(max_length=30, blank=True, null=True, verbose_name="Printer Model")
    
    def __str__(self):
        return self.name

内容的提问来源于stack exchange,提问作者Jstnice

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 21:44:51