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

Django新手求助:如何按序将多模型数据渲染至HTML不同板块?

问题说明

首次开发Django项目,页面使用Bootstrap折叠面板,现有关联模型、模板及视图代码如下,需实现不同案例对应数量不同的折叠面板,并从各模型取数据对应展示到HTML板块,需求包括:

  1. 为各数据表创建对象的方法
  2. 页面动态展示各表存储的数据

现有模型代码

class CaseStudy_list(models.Model):
    CaseStudy_id = models.IntegerField(primary_key=True)
    title = models.CharField(max_length=255)
    
    def __str__(self):
        return self.title

class CaseStudy_parts(models.Model):   # 对应折叠面板
    case_study = models.ForeignKey(CaseStudy_list, on_delete=models.CASCADE)
    CaseStudy_part_id = models.AutoField(primary_key=True)
    CaseStudy_order = models.IntegerField(default="")
    CaseStudy_title_accordian = models.CharField(max_length=255)
    
    def __str__(self):
        return self.CaseStudy_title_accordian

class CaseStudy_content(models.Model):   # 左侧文本区
    case_study = models.ForeignKey(CaseStudy_list, on_delete=models.CASCADE)
    content_title = models.CharField(max_length=255, default="")
    content_text = models.TextField(blank=True)
    content_link = models.TextField(blank=True)
    
    def __str__(self):
        return self.content_title

class CaseStudy_Media(models.Model):    # 右侧媒体区
    case_study = models.ForeignKey(CaseStudy_list, on_delete=models.CASCADE)
    content_img = models.ImageField(upload_to='casestudy/images', default="")

class CaseStudy_buttons(models.Model):
    content = models.ForeignKey(CaseStudy_content, on_delete=models.CASCADE)
    button_id = models.CharField(max_length=255)
    button_label = models.CharField(max_length=255)

解决方案

一、模型关联优化(可选但逻辑更合理)

当前CaseStudy_content、CaseStudy_Media直接关联CaseStudy_list,但实际每个折叠面板(CaseStudy_parts)应对应专属内容和媒体,建议调整外键关联:

# 修改CaseStudy_content外键
class CaseStudy_content(models.Model):
    case_study_part = models.ForeignKey(CaseStudy_parts, on_delete=models.CASCADE)
    content_title = models.CharField(max_length=255, default="")
    content_text = models.TextField(blank=True)
    content_link = models.TextField(blank=True)
    
    def __str__(self):
        return self.content_title

# 修改CaseStudy_Media外键
class CaseStudy_Media(models.Model):
    case_study_part = models.ForeignKey(CaseStudy_parts, on_delete=models.CASCADE)
    content_img = models.ImageField(upload_to='casestudy/images', default="")

二、视图层:正确获取并传递数据

修改视图,获取当前案例下所有折叠面板,同时预加载关联数据减少数据库查询:

from django.shortcuts import get_object_or_404, render

def casestudy(request, CaseStudy_id ):
    # 获取当前案例
    casestudy_object = get_object_or_404(CaseStudy_list, CaseStudy_id=CaseStudy_id)
    # 获取该案例下所有折叠面板,按顺序排序并预加载关联内容、媒体
    casestudy_parts = CaseStudy_parts.objects.filter(case_study=casestudy_object)\
        .order_by('CaseStudy_order')\
        .prefetch_related('casestudy_content_set', 'casestudy_media_set')
    
    context = {
        'casestudy_object': casestudy_object,
        'casestudy_parts': casestudy_parts,  # 传递查询集而非模型类
    }
    return render(request, 'casestudy.html', context)

三、模板层:动态渲染折叠面板

使用Django模板标签循环生成折叠面板,避免硬编码:

<div class="page-layout">
    <div class="accordion" id="accordionPanelsStayOpenExample">
        {% for part in casestudy_parts %}
        <div class="accordion-item">
            <h6 class="accordion-header">
                <button class="accordion-button {% if forloop.first %}show{% else %}collapsed{% endif %}" 
                        type="button" 
                        data-bs-toggle="collapse"
                        data-bs-target="#panelsStayOpen-collapse{{ forloop.counter }}" 
                        aria-expanded="{% if forloop.first %}true{% else %}false{% endif %}"
                        aria-controls="panelsStayOpen-collapse{{ forloop.counter }}">
                    {{ part.CaseStudy_title_accordian }}
                </button>
            </h6>
            <div id="panelsStayOpen-collapse{{ forloop.counter }}" 
                 class="accordion-collapse collapse {% if forloop.first %}show{% endif %}">
                <div class="accordion-body">
                    <div class="container-area">
                        <!-- 左侧内容区 -->
                        <div class="col-content">
                            {% for content in part.casestudy_content_set.all %}
                            <div class='introduction-content'>
                                <h3>{{ content.content_title }}</h3>
                                <p>{{ content.content_text }}</p>
                                {% if content.content_link %}
                                <a href="{{ content.content_link }}" target="_blank">查看详情</a>
                                {% endif %}
                                <!-- 渲染对应按钮 -->
                                {% for button in content.casestudy_buttons_set.all %}
                                <button type="button" id="{{ button.button_id }}" class="process-btn btn btn-info">
                                    {{ button.button_label }}
                                </button>
                                {% endfor %}
                            </div>
                            {% endfor %}
                        </div>
                        <!-- 右侧媒体区 -->
                        <div class="col-data">
                            {% for media in part.casestudy_media_set.all %}
                            {% if media.content_img %}
                            <img src="{{ media.content_img.url }}" alt="案例媒体图">
                            {% endif %}
                            {% endfor %}
                        </div>
                    </div>
                </div>
            </div>
        </div>
        {% endfor %}
    </div>
</div>

模板说明:

  • 用{% for %}循环遍历所有折叠面板,动态生成唯一ID避免重复
  • 第一个面板默认展开,其余默认折叠
  • 通过反向关联part.casestudy_content_set.all获取当前面板的内容,同理获取媒体和按钮

四、创建数据表对象的方法

方法1:Django Admin后台创建

  1. 在admin.py中注册所有模型:
from django.contrib import admin
from .models import CaseStudy_list, CaseStudy_parts, CaseStudy_content, CaseStudy_Media, CaseStudy_buttons

admin.site.register(CaseStudy_list)
admin.site.register(CaseStudy_parts)
admin.site.register(CaseStudy_content)
admin.site.register(CaseStudy_Media)
admin.site.register(CaseStudy_buttons)
  1. 运行python manage.py createsuperuser创建管理员账号,登录后台即可手动添加数据。

方法2:脚本批量创建

编写populate_data.py脚本(放在app目录下):

import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE', '你的项目名.settings')
import django
django.setup()

from 你的app名.models import CaseStudy_list, CaseStudy_parts, CaseStudy_content, CaseStudy_Media, CaseStudy_buttons

# 创建案例
case1 = CaseStudy_list.objects.create(CaseStudy_id=1, title="Iris数据集案例")
# 创建折叠面板
part1 = CaseStudy_parts.objects.create(case_study=case1, CaseStudy_order=1, CaseStudy_title_accordian="项目概述")
# 创建内容
content1 = CaseStudy_content.objects.create(case_study_part=part1, content_title="项目目标", content_text="分析Iris数据集特征,实现分类模型")
# 创建按钮
CaseStudy_buttons.objects.create(content=content1, button_id="load-data-btn", button_label="加载数据")
# 创建媒体
CaseStudy_Media.objects.create(case_study_part=part1, content_img="casestudy/images/iris-full-img.png")

运行脚本:python manage.py shell < populate_data.py


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 08:59:51