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

如何实现用户选择课程后展示对应自定义目录的所有文件?

解决课程文件筛选展示的问题

我来帮你搞定这个课程文件筛选的问题,先梳理下你的代码里几个关键的问题,然后一步步修正:

1. 课程选择值与数据库存储值不匹配

你的Document模型里courses字段用了choices,存储的是缩写(比如DB对应"data structure"),但前端<option>的value是{{ obj.courseName }}——也就是课程的全称。这就导致你用request.POST["course"]去过滤时,数据库里的缩写和POST过来的全称对不上,自然找不到对应文件。

修正方案二选一:

  • 方案A:统一存储全称。修改Document模型的courseChoices,让key和value一致:
courseChoices = (
    ("data structure", "data structure"),
    ("software enginering", "software enginering "),
    ("discrete structure", "discrete structure"),
    ("web dev", "web dev"),
    ("options", "options"),
)

这样POST过来的全称就能直接匹配数据库存储的值。

  • 方案B:前端传缩写值。如果Course模型有课程缩写字段(比如courseCode),就把<option>的value改成缩写:
<option value="{{ obj.courseCode }}">{{ obj.courseName }}</option>

如果没有,也可以在模板里手动映射:

{% for obj in courses %}
    {% if obj.courseName == "data structure" %}
        <option value="DB">{{ obj.courseName }}</option>
    {% elif obj.courseName == "software enginering" %}
        <option value="SF">{{ obj.courseName }}</option>
    {% endif %}
    <!-- 其他课程同理补充 -->
{% endfor %}

2. Views未实现文件筛选逻辑

你当前的views.py里,不管POST请求有没有匹配到课程,最后都传了Document.objects.all(),这就导致前端始终显示所有文件,完全没做过滤。

修正后的views.py:

def showDocuments(request):
    documents = Document.objects.all()
    courses = Course.objects.all()
    context_message = ""

    if request.method == "POST":
        selected_course = request.POST.get("course")
        # 筛选对应课程的文件
        documents = Document.objects.filter(courses__exact=selected_course)
        if not documents.exists():
            context_message = "there is no files for this course yet!"

    context = {
        "documents": documents,
        "courses": courses,
        "message": context_message
    }
    return render(request, 'dashboard.html', context)

调整后逻辑:默认显示所有文件,当用户提交课程选择时,筛选出对应课程的文件,同时把无文件的提示信息传到前端。

3. 前端缺少表单提交触发

你的HTML里只有<select>,没有表单包裹,用户选完课程根本没法触发请求。需要把select放进表单,加上提交按钮:

修正后的dashboard.html片段:

<div class="col-sm-4">
    <form method="POST" action="{% url 'showDocuments' %}">
        {% csrf_token %} <!-- Django必须加这个防止CSRF攻击 -->
        <select id="crs" class="custom-select custom-select-sm" name="course">
            <option selected>option</option>
            {% for obj in courses %}
                <option value="{{ obj.courseName }}">{{ obj.courseName }}</option>
                <!-- 用方案B的话,这里value改成对应缩写 -->
            {% endfor %}
        </select>
        <button type="submit" class="btn btn-sm btn-primary mt-2">查看课程文件</button>
    </form>
    <!-- 显示无文件提示 -->
    {% if message %}
        <p class="mt-2 text-warning">{{ message }}</p>
    {% endif %}
</div>

<!-- 在页面合适位置展示筛选后的文件 -->
<div class="mt-4">
    {% for doc in documents %}
        <div class="card mb-2">
            <div class="card-body">
                <h5 class="card-title">{{ doc.document.name }}</h5>
                <p class="card-text">{{ doc.description }}</p>
                <a href="{{ doc.document.url }}" class="btn btn-sm btn-outline-primary" target="_blank">下载文件</a>
            </div>
        </div>
    {% empty %}
        <p>{{ message }}</p>
    {% endfor %}
</div>

4. 修复文件上传路径方法

你的content_file_name方法参数写错了,Django的FileField的upload_to函数接收的是实例对象和文件名,不是courses。修正后才能保证文件上传到正确目录:

修正后的models.py片段:

def content_file_name(self, filename):
    file_path = "documents/{courses}/{filename}".format(
        courses=self.courses,
        filename=filename
    )
    return file_path

# 对应Document的file字段
document = models.FileField(upload_to=content_file_name)

现在测试一下:用户选择课程→点击提交→后端筛选对应文件→前端展示;如果课程无文件,会显示提示信息。

内容的提问来源于stack exchange,提问作者Hozayfa El Rifai

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:55:46