Django实现文件上传

发布于:2025-05-29 ⋅ 阅读:(16) ⋅ 点赞:(0)

文件上传

目录

1. 配置文件上传的路径

2. 实现上传文件功能

3.代码展示集合

这篇文章, 我们会讲到如何去上传文件。里面的细节点, 需要注意下, 博主就在配置文件上, 卡了很长时间的bug, 这篇文章里面也会讲到博主遇到bug的点。

一、配置文件上传的路径

我们打开settings.py:

在最后面加上两行代码:

import os
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
MEDIA_URL = "/media/"

这两行代码, 是用来设置将来文件上传玩以后, 把上传好的文件放到哪里, 我们在那两行代码的配置信息里面不难看出, 我们是将上传好的文件, 都存放在media文件夹里面。

我们在项目的根目录下新建一个media文件夹。

在这里插入图片描述

然后我们还需要文件上传的相应路由:

urls.py:

"""project_simple URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/4.1/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, re_path
from django.views.static import serve
from django.conf import settings
from project_one.views import depart, user, assets, admin_role, login, Ajax_data, task_data, perform

urlpatterns = [
    re_path(r"^media/(?P<path>.*)$", serve, {"document_root": settings.MEDIA_ROOT})
]

这里运用了正则表达式, 来匹配要访问文件的路由, 用正则表达式^media/(?P<path>.*)$ 来表示。

这里面需要导入以下包:

1.from django.urls import path, re_path

2.from django.views.static import serve

3.from django.conf import settings

以上两个步骤, 在做今天的项目之前, 一定要配置好, 不然到后面调试程序的时候, 都不清楚哪里报错了, 博主就是因为这个问题, 卡了很久。。。。。。

二、实现上传文件功能

创建数据库表格Perform(这个是记录业绩的表格):

models.py:

class Perform(models.Model):
    oid = models.CharField(verbose_name="订单号", max_length=32)
    source = models.CharField(verbose_name="销售", max_length=32)
    title = models.CharField(verbose_name="客户姓名", max_length=32)
    times = models.DateField(verbose_name="成交日期")
    price = models.CharField(verbose_name="成交金额", max_length=32)
    name = models.CharField(verbose_name="销售人员", max_length=32)
    image = models.CharField(verbose_name="详情", max_length=128)

我们先要实现页面展示功能:

perform_list.html:

{% extends "index/model_tmp.html" %}
{#{% load static %}#}

{% block content %}

    <div class="container">
        <a href="/perform/add/" class="btn btn-success">添加信息</a>
        <div class="panel panel-success">
            <div class="panel-heading">
                <h3 class="panel-title">绩效表</h3>
            </div>
            <div class="panel-body">
                <table class="table table-bordered">
                    <thead>
                        <tr>
                            <th>ID</th>
                            <th>订单号</th>
                            <th>客户来源</th>
                            <th>客户名称</th>
                            <th>成交时间</th>
                            <th>成交价格</th>
                            <th>销售人员</th>
                            <th>详情</th>
                            {% if request.unicom_role == 3 %}
                                <th>操作</th>
                            {% endif %}
                        </tr>
                    </thead>
                    <tbody>
                    {% for data in perform_list %}
                        <tr>
                            <th scope="row">{{ data.id }}</th>
                            <th>{{ data.oid }}</th>
                            <th>{{ data.source }}</th>
                            <th>{{ data.title }}</th>
                            <th>{{ data.times }}</th>
                            <th>{{ data.price }}</th>
                            <th>{{ data.name }}</th>
                            <th>
                                <div><a target="_blank" href="/{{ data.image }}/" style="width: 60px; height: 60px;"><img style="object-fit: cover; border-radius: 100px;" src="/{{ data.image }}/" width="60" height="60" alt="图片无法加载"></a></div>
                            </th>
                            {% if request.unicom_role == 3 %}
                                <td style="color: green">
                                    <a href="#"><span style="color: green;" class="glyphicon glyphicon-pencil" aria-hidden="true"></span></a>
                                    <a href="#"><span style="color: red;" class="glyphicon glyphicon-trash" aria-hidden="true"></span></a>
                                </td>
                            {% endif %}
                        </tr>
                    {% endfor %}
                    </tbody>
                </table>
            </div>
        </div>
        {# 实现分页查询 #}
        <ul class="pagination">
            {{ page_string }}
        </ul>
    </div>
{% endblock %}

PageData.py(这个代码之前写过, 这篇文章中需要用到此代码):

from copy import deepcopy
from django.utils.safestring import mark_safe


class PageData(object):
    def __init__(self, request, queryset, page_size=10, plus=2, page_param="page"):
        get_query_dict = deepcopy(request.GET)
        self.query_dict = get_query_dict
        self.page_param = page_param

        page = request.GET.get(self.page_param, "1")
        # 判段当前page首部是纯数字
        if page.isdecimal():
            page = int(page)
        else:
            page = 1

        self.page = page
        self.start = (self.page - 1) * page_size
        self.end = self.page * page_size
        self.page_queryset = queryset[self.start: self.end]
        page_count = queryset.count()
        page_count, div = divmod(page_count, page_size)
        if div:
            page_count += 1
        self.page_count = page_count
        self.plus = plus

    def page_html(self):
        if self.page_count <= 2 * self.plus + 1:
            start_page = 1
            end_page = self.page_count
        else:
            # 如果当前点击的页面是小于3的
            if self.page <= self.plus:
                start_page = 1
                end_page = 2 * self.plus + 1
            else:
                # 后五页
                if (self.page + self.plus) > self.page_count:
                    start_page = self.page_count - self.plus * 2
                    end_page = self.page_count
                else:
                    # 大于前五页,小于后五也的其他页面
                    start_page = self.page - self.plus
                    end_page = self.page + self.plus

        page_str_list = []
        # 首页
        self.query_dict.setlist(self.page_param, [1])
        page_str_list.append(f'<li><a href="?{self.query_dict.urlencode()}">首页</a></li>')
        # 上一页
        if self.page > 1:
            self.query_dict.setlist(self.page_param, [self.page - 1])
            page_str_list.append(
                f'<li><a href="?{self.query_dict.urlencode()}"><span aria-hidden="true">«</span></a></li>')
        else:
            page_str_list.append(f'<li class="disabled"><span aria-hidden="true">«</span></li>')
        for page_num in range(start_page, end_page + 1):
            if page_num == self.page:
                self.query_dict.setlist(self.page_param, [page_num])
                page_str_list.append(f'<li class="active"><a href="?{self.query_dict.urlencode()}">{page_num}</a></li>')
            else:
                self.query_dict.setlist(self.page_param, [page_num])
                page_str_list.append(f'<li><a href="?{self.query_dict.urlencode()}">{page_num}</a></li>')

        # 下一页
        if self.page < self.page_count:
            self.query_dict.setlist(self.page_param, [self.page + 1])
            page_str_list.append(
                f'<li><a href="?{self.query_dict.urlencode()}"><span aria-hidden="true">»</span></a></li>')
        else:
            page_str_list.append(f'<li class="disabled"><span aria-hidden="true">»</span></li>')

        # 尾页
        self.query_dict.setlist(self.page_param, [self.page_count])
        page_str_list.append(f'<li><a href="?{self.query_dict.urlencode()}">尾页</a></li>')
        search_page = """
            <li>
                <div style="float: right">
                    <form method="get">
                        <div class="input-group" style="width: 100px;float: right">
                            <input type="text" class="form-control" name="page">
                            <span class="input-group-btn">
                                <button class="btn btn-success" type="submit">跳转</button>
                            </span>
                        </div>
                    </form>
                </div>
            </li>
        """
        page_str_list.append(search_page)
        page_string = mark_safe("".join(page_str_list))
        return page_string

perform.py:

from datetime import datetime

from django.shortcuts import render, redirect
from django import forms
from project_one.utils.PageData import PageData
import os

from project_one import models


# Create your views here.
def perform_info(request):
    perform_list = models.Perform.objects.all()
    # 这个PageData分页, 在utils代码里面。
    page_object = PageData(request, perform_list)
    content = {
        "perform_list": page_object.page_queryset,
        "page_string": page_object.page_html()
    }
    return render(request, "perform/perform_list.html", content)
绩效数据添加功能:

我们先自定义form:

class PerformForm(forms.Form):
    oid = forms.CharField(label="订单号",
                          widget=forms.TextInput(attrs={"class": "form-control", "autocomplete": "off"}))
    source = forms.CharField(label="客户来源",
                             widget=forms.TextInput(attrs={"class": "form-control", "autocomplete": "off"}))
    title = forms.CharField(label="客户名称",
                            widget=forms.TextInput(attrs={"class": "form-control", "autocomplete": "off"}))
    price = forms.CharField(label="成交价格",
                            widget=forms.TextInput(attrs={"class": "form-control", "autocomplete": "off"}))
    image = forms.FileField(label="详情")

这里我们没有写class Meta这个类, 所以我们需要用到Form而不是ModelForm。

添加函数:

def add_perform(request):
    if request.method == "GET":
        title = "添加绩效"
        form = PerformForm()
        content = {"title": title, "form": form}
        return render(request, "perform/perform_add_modify.html", content)
   	
    # 如果要上传文件的话, request.FILES千万不能漏掉
    form = PerformForm(data=request.POST, files=request.FILES)
    if form.is_valid():
        # 获取提交过来的文件对象
        image_object = form.cleaned_data.get("image")
        # 拼接路径
        # image_object.name这个就是文件名字,
        # os.path.join("media", image_object.name)就代表用media文件夹拼接文件名字,
        # 也就是把路径变为:文件夹/文件名。
        # 但是最后的路径为:文件夹\文件名。所以需要把\替换成/, 注意要写成\\,
        # 因为反斜杠它在正则表达式里面本身就有自己的意义, 所以这里需要转义操作。
        print(os.path.join("media", image_object.name))
        file_path = os.path.join("media", image_object.name).replace("\\", "/")
        print(file_path)
        # 将文件存储在media目录当中
        with open(file_path, "wb") as file:
            for chunk in image_object.chunks():
                file.write(chunk)
        oid = form.cleaned_data.get("oid")
        source = form.cleaned_data.get("source")
        title = form.cleaned_data.get("title")
        times = datetime.now().strftime("%Y-%m-%d")
        price = form.cleaned_data.get("price")
        name = request.session['info']['username']
        models.Perform.objects.create(oid=oid, source=source, title=title, times=times, price=price, name=name, image=file_path)
        return redirect("/perform/list/")
    return render(request, "perform/perform_add_modify.html", {"form": form})

这里有些细节需要注意:

  1. files=request.FILES不能漏加, 因为我们在添加数据的时候, 要上传文件。
  2. 拼接路径的写法, 利用os.path.join来实现, 最后不要忘记用replace函数把反斜杠\替换成斜杠/。
  3. 将文件存储到media里面, 需要用到文件存储的代码, 里面用chunk来遍历存储, 因为只有request请求, 才具有.content存储, 那这里, 我们只能用chunk来解决。
  4. 添加数据, 需要获取到相关的所有数据, oid订单号, source客户来源, title客户名称, times成交时间(获取当前时间, 然后再用年-月-日的格式存储), price成交价格, name销售人员, image就是file_path(文件路径)。

perform_add_modify.html:

{% extends "index/model_tmp.html" %}
{% load static %}

{% block css %}
    <link rel="stylesheet" href="{% static 'css/layui.css' %}">
{% endblock %}

{% block content %}
    <div class="container">
        <h1>{{ title }}</h1>
        {# 由于我们enctype="multipart/form-data"必须要加 #}
        <form method="post" enctype="multipart/form-data">
            {% csrf_token %}
            {% for field in form %}
{#       field.label这里面就是获取我们在models.py里面创建表格里面的每一个字段里面有个verbose_name这个参数的值         #}
                <label for="exampleInputEmail1">{{ field.label }}</label>
                {{ field }}
                {#       展示错误信息         #}
                <span style="color: red">{{ field.errors.0 }}</span>
                <br>
            {% endfor %}
            <button type="submit" class="btn btn-success">提交</button>
        </form>
    </div>
{% endblock %}

这里面也有个细节需要注意下, 由于我们需要再添加数据的时候, 上传文件, 那我们就需要在form表单里面, 加上enctype="multipart/form-data"

最后我们不要忘记添加路由:

urls.py:

"""project_simple URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/4.1/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, re_path
from django.views.static import serve
from django.conf import settings
from project_one.views import depart, user, assets, admin_role, login, Ajax_data, task_data, perform

urlpatterns = [
    re_path(r"^media/(?P<path>.*)$", serve, {"document_root": settings.MEDIA_ROOT})
    path("perform/list/", perform.perform_info, name="perform_info"),
    path("perform/add/", perform.add_perform, name="add_perform")
]

还有, 不要忘记在model_tmp.html的header里面添加绩效那栏。

<ul class="nav navbar-nav">
    {% if request.unicom_role == 1 %}
    <li class="active"><a href="/depart/">部门页面</a></li>
    <li class="active"><a href="/user/">员工页面</a></li>
    {% elif request.unicom_role == 3%}
    <li class="active"><a href="/depart/">部门页面</a></li>
    <li class="active"><a href="/user/">员工页面</a></li>
    <li class="active"><a href="/assets_list/">资产页面</a></li>
    {% endif %}
    {#                <li class="active"><a href="/depart/">部门页面</a></li>#}
    {#                <li class="active"><a href="/user/">员工页面</a></li>#}
    {#                <li class="active"><a href="/assets_list/">资产页面</a></li>#}
    <li class="dropdown">
        {% if request.unicom_role == 3 %}
        <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
           aria-expanded="false">平台用户<span class="caret"></span></a>
        {% endif %}
        <ul class="dropdown-menu">
            <li><a href="/admin_list/">登录账号</a></li>
            <li><a href="/demo/list/">ajax请求</a></li>
        </ul>
    </li>
    <li class="active"><a href="/task/list/">任务列表</a></li>
    <li class="active"><a href="/perform/list/">绩效</a></li>
</ul>

运行结果:

我们登录管理员账号之后, 在上面的导航栏里面点击绩效:

在这里插入图片描述

然后点击添加信息:

文件的话, 自己随便从电脑里面选择一个文件。

在这里插入图片描述

提交(添加)数据:

数据添加成功!!!在这里插入图片描述

我们再点击一下详情:

在这里插入图片描述

会帮我们打开我们上传的文件, 我们这里上传的是图片。

三、代码展示合集

前端:

perform_list.html:

{% extends "index/model_tmp.html" %}
{#{% load static %}#}

{% block content %}

<div class="container">
    <a href="/perform/add/" class="btn btn-success">添加信息</a>
    <div class="panel panel-success">
        <div class="panel-heading">
            <h3 class="panel-title">绩效表</h3>
        </div>
        <div class="panel-body">
            <table class="table table-bordered">
                <thead>
                    <tr>
                        <th>ID</th>
                        <th>订单号</th>
                        <th>客户来源</th>
                        <th>客户名称</th>
                        <th>成交时间</th>
                        <th>成交价格</th>
                        <th>销售人员</th>
                        <th>详情</th>
                        {% if request.unicom_role == 3 %}
                        <th>操作</th>
                        {% endif %}
                    </tr>
                </thead>
                <tbody>
                    {% for data in perform_list %}
                    <tr>
                        <th scope="row">{{ data.id }}</th>
                        <th>{{ data.oid }}</th>
                        <th>{{ data.source }}</th>
                        <th>{{ data.title }}</th>
                        <th>{{ data.times }}</th>
                        <th>{{ data.price }}</th>
                        <th>{{ data.name }}</th>
                        <th>
                            <div><a target="_blank" href="/{{ data.image }}/" style="width: 60px; height: 60px;"><img style="object-fit: cover; border-radius: 100px;" src="/{{ data.image }}/" width="60" height="60" alt="图片无法加载"></a></div>
                        </th>
                        {% if request.unicom_role == 3 %}
                        <td style="color: green">
                            <a href="#"><span style="color: green;" class="glyphicon glyphicon-pencil" aria-hidden="true"></span></a>
                            <a href="#"><span style="color: red;" class="glyphicon glyphicon-trash" aria-hidden="true"></span></a>
                        </td>
                        {% endif %}
                    </tr>
                    {% endfor %}
                </tbody>
            </table>
        </div>
    </div>
    {# 实现分页查询 #}
    <ul class="pagination">
        {{ page_string }}
    </ul>
</div>
{% endblock %}

perform_add_modify:

{% extends "index/model_tmp.html" %}
{% load static %}

{% block css %}
<link rel="stylesheet" href="{% static 'css/layui.css' %}">
{% endblock %}

{% block content %}
<div class="container">
    <h1>{{ title }}</h1>
    {# 由于我们enctype="multipart/form-data"必须要加 #}
    <form method="post" enctype="multipart/form-data">
        {% csrf_token %}
        {% for field in form %}
        {#       field.label这里面就是获取我们在models.py里面创建表格里面的每一个字段里面有个verbose_name这个参数的值         #}
        <label for="exampleInputEmail1">{{ field.label }}</label>
        {{ field }}
        {#       展示错误信息         #}
        <span style="color: red">{{ field.errors.0 }}</span>
        <br>
        {% endfor %}
        <button type="submit" class="btn btn-success">提交</button>
    </form>
</div>
{% endblock %}

model_tmp.html

{% load static %}
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" href="{% static 'css/bootstrap.css' %}">
        {% block css %}
        {% endblock %}
    </head>
    <body>
        <div class="navbar navbar-default">
            <div class="container">
                <!-- Brand and toggle get grouped for better mobile display -->
                <div class="navbar-header">
                    <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
                            data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                        <span class="sr-only">Toggle navigation</span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                    </button>
                    <a class="navbar-brand" href="#">管理系统</a>
                </div>

                <!-- Collect the nav links, forms, and other content for toggling -->
                <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                    <ul class="nav navbar-nav">
                        {% if request.unicom_role == 1 %}
                        <li class="active"><a href="/depart/">部门页面</a></li>
                        <li class="active"><a href="/user/">员工页面</a></li>
                        {% elif request.unicom_role == 3%}
                        <li class="active"><a href="/depart/">部门页面</a></li>
                        <li class="active"><a href="/user/">员工页面</a></li>
                        <li class="active"><a href="/assets_list/">资产页面</a></li>
                        {% endif %}
                        {#                <li class="active"><a href="/depart/">部门页面</a></li>#}
                        {#                <li class="active"><a href="/user/">员工页面</a></li>#}
                        {#                <li class="active"><a href="/assets_list/">资产页面</a></li>#}
                        <li class="dropdown">
                            {% if request.unicom_role == 3 %}
                            <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
                               aria-expanded="false">平台用户<span class="caret"></span></a>
                            {% endif %}
                            <ul class="dropdown-menu">
                                <li><a href="/admin_list/">登录账号</a></li>
                                <li><a href="/demo/list/">ajax请求</a></li>
                            </ul>
                        </li>
                        <li class="active"><a href="/task/list/">任务列表</a></li>
                        <li class="active"><a href="/perform/list/">绩效</a></li>
                    </ul>

                    <ul class="nav navbar-nav navbar-right">

                        <li class="dropdown">
                            <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
                               aria-expanded="false">欢迎-->{{ request.session.info.username }}<span class="caret"></span></a>
                            <ul class="dropdown-menu">
                                <li><a href="/logout/">退出登录</a></li>
                            </ul>
                        </li>
                    </ul>
                </div><!-- /.navbar-collapse -->
            </div><!-- /.container-fluid -->
        </div>

        {% block content %}
        {% endblock %}
        <script src="{% static 'js/jquery3.7.1.js' %}"></script>
        <script src="{% static 'js/bootstrap.js' %}"></script>
        {% block js %}
        {% endblock %}
    </body>
</html>
后端:

models.py:

from django.db import models


# Create your models here.
class Department(models.Model):
    title = models.CharField(verbose_name="部门名称", max_length=255)

    def __str__(self):
        return self.title


class UserInfo(models.Model):
    name = models.CharField(verbose_name="姓名", max_length=255)
    gender_choices = (
        (1, "男"), (2, "女")
    )
    gender = models.SmallIntegerField(verbose_name="性别", choices=gender_choices)
    salary = models.IntegerField(verbose_name="薪水")
    age = models.IntegerField(verbose_name="年龄")
    create_time = models.DateField(verbose_name="入职时间")
    department = models.ForeignKey(verbose_name="部门", max_length=255, to="Department", to_field="id",
                                   on_delete=models.CASCADE, null=True, blank=True)

    def __str__(self):
        return self.name


class Assets(models.Model):
    mobile = models.CharField(verbose_name="手机号", max_length=11)
    status_code_choice = (
        (1, "已使用"),
        (2, "未使用")
    )
    status = models.SmallIntegerField(verbose_name="状态", choices=status_code_choice)
    create_time = models.DateField(verbose_name="创建时间")
    user = models.ForeignKey(to="UserInfo", to_field="id", verbose_name="使用者", on_delete=models.SET_NULL, null=True, blank=True)
    price = models.CharField(verbose_name="价格", max_length=10)


class AdminRole(models.Model):
    username = models.CharField(verbose_name="用户名", max_length=32)
    password = models.CharField(verbose_name="密码", max_length=64)
    password_choice = (
        (1, "员工"),
        (2, "领导"),
        (3, "管理员")
    )
    role = models.SmallIntegerField(verbose_name="角色", choices=password_choice)


class Task(models.Model):
    title = models.CharField(verbose_name="标题", max_length=64)
    level_choice = {
        (1, "临时任务"),
        (2, "普通任务"),
        (3, "重要任务"),
        (4, "紧急任务")
    }
    level = models.SmallIntegerField(verbose_name="任务级别", choices=level_choice)
    detail = models.TextField(verbose_name="任务内容")
    user = models.ForeignKey(verbose_name="负责人", to="UserInfo", on_delete=models.CASCADE, null=True, blank=True)
    times = models.DateField(verbose_name="开始时间")
    code_choices = {
        (1, "未完成"),
        (2, "正在处理"),
        (3, "已完成")
    }
    code = models.SmallIntegerField(verbose_name="任务状态", choices=code_choices)


class Perform(models.Model):
    oid = models.CharField(verbose_name="订单号", max_length=32)
    source = models.CharField(verbose_name="销售", max_length=32)
    title = models.CharField(verbose_name="客户姓名", max_length=32)
    times = models.DateField(verbose_name="成交日期")
    price = models.CharField(verbose_name="成交金额", max_length=32)
    name = models.CharField(verbose_name="销售人员", max_length=32)
    image = models.CharField(verbose_name="详情", max_length=128)

perform.py:

from datetime import datetime

from django.shortcuts import render, redirect
from django import forms
from project_one.utils.PageData import PageData
import os

from project_one import models


# Create your views here.
def perform_info(request):
    perform_list = models.Perform.objects.all()
    page_object = PageData(request, perform_list)
    content = {
        "perform_list": page_object.page_queryset,
        "page_string": page_object.page_html()
    }
    return render(request, "perform/perform_list.html", content)


class PerformForm(forms.Form):
    oid = forms.CharField(label="订单号",
                          widget=forms.TextInput(attrs={"class": "form-control", "autocomplete": "off"}))
    source = forms.CharField(label="客户来源",
                             widget=forms.TextInput(attrs={"class": "form-control", "autocomplete": "off"}))
    title = forms.CharField(label="客户名称",
                            widget=forms.TextInput(attrs={"class": "form-control", "autocomplete": "off"}))
    price = forms.CharField(label="成交价格",
                            widget=forms.TextInput(attrs={"class": "form-control", "autocomplete": "off"}))
    image = forms.FileField(label="详情")


def add_perform(request):
    if request.method == "GET":
        title = "添加绩效"
        form = PerformForm()
        content = {"title": title, "form": form}
        return render(request, "perform/perform_add_modify.html", content)

    # 如果要上传文件的话, request.FILES千万不能漏掉
    form = PerformForm(data=request.POST, files=request.FILES)
    if form.is_valid():
        # 获取提交过来的文件对象
        image_object = form.cleaned_data.get("image")
        # 拼接路径
        # image_object.name这个就是文件名字,
        # os.path.join("media", image_object.name)就代表用media文件夹拼接文件名字,
        # 也就是把路径变为:文件夹/文件名。
        # 但是最后的路径为:文件夹\文件名。所以需要把\替换成/, 注意要写成\\,
        # 因为反斜杠它在正则表达式里面本身就有自己的意义, 所以这里需要转义操作。
        print(os.path.join("media", image_object.name))
        file_path = os.path.join("media", image_object.name).replace("\\", "/")
        print(file_path)
        # 将文件存储在media目录当中
        with open(file_path, "wb") as file:
            for chunk in image_object.chunks():
                file.write(chunk)
        oid = form.cleaned_data.get("oid")
        source = form.cleaned_data.get("source")
        title = form.cleaned_data.get("title")
        times = datetime.now().strftime("%Y-%m-%d")
        price = form.cleaned_data.get("price")
        name = request.session['info']['username']
        models.Perform.objects.create(oid=oid, source=source, title=title, times=times, price=price, name=name, image=file_path)
        return redirect("/perform/list/")
    return render(request, "perform/perform_add_modify.html", {"form": form})

settings.py:

"""
Django settings for project_simple project.

Generated by 'django-admin startproject' using Django 4.1.3.

For more information on this file, see
https://docs.djangoproject.com/en/4.1/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/4.1/ref/settings/
"""

from pathlib import Path
import os

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-m@31x($s*0tgzm0$2(ct6izu)8oe$xa)@k7(&*7tkr*g(dbl)5'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'project_one.apps.ProjectOneConfig'
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'project_one.middleware.auth.AuthMiddleware'
]

ROOT_URLCONF = 'project_simple.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'project_simple.wsgi.application'


# Database
# https://docs.djangoproject.com/en/4.1/ref/settings/#databases

# DATABASES = {
#     'default': {
#         'ENGINE': 'django.db.backends.sqlite3',
#         'NAME': BASE_DIR / 'db.sqlite3',
#     }
# }

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': '28_class_03',
        'USER': 'root',
        'PASSWORD': '123456',
        'HOST': '127.0.0.1',
        'PORT': '3306',
    }
}


# Password validation
# https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/4.1/topics/i18n/

LANGUAGE_CODE = 'zh-hans'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_TZ = True

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.1/howto/static-files/

STATIC_URL = '/static/'

# Default primary key field type
# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

UNICOM_PERMISSION = {
    1: ["add_depart", "depart_modify", "del_depart", "user_add", "user_modify", "user_del", "user_add_modelform",
        "user_modify_modelform", "assets_add", "assets_modify", "assets_del", "admin_add", "admin_modify",
        "admin_reset_pwd", "admin_del"],
    2: [],
    3: []
}
# 这篇文章需要添加的代码
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
MEDIA_URL = "/media/"

注意, settings.py里面, 其他代码都不需要动, 我们也不要轻易修改配置文件里面的代码, 否则会导致整个项目崩溃。

urls.py:

"""project_simple URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/4.1/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, re_path
from django.views.static import serve
from django.conf import settings
from project_one.views import depart, user, assets, admin_role, login, Ajax_data, task_data, perform

urlpatterns = [
    # path('admin/', admin.site.urls),
    re_path(r"^media/(?P<path>.*)$", serve, {"document_root": settings.MEDIA_ROOT}),
    path("", depart.index, name="index"),
    path("depart/", depart.depart, name="depart"),
    path("depart/add/", depart.add_depart, name="add_depart"),
    path("depart/<int:nid>/modify/", depart.depart_modify, name="depart_modify"),
    path("depart/<int:nid>/del/", depart.del_depart, name="del_depart"),
    path("user/", user.user_info, name="user_info"),
    path("user/add/", user.user_add, name="user_add"),
    path("user/<int:nid>/modify/", user.user_modify, name="user_modify"),
    path("user/<int:nid>/del/", user.user_del, name="user_del"),
    path("user/add/modelform", user.user_add_modelform, name="user_add_modelform"),
    path("user/<int:nid>/modify/modelform", user.user_modify_modelform, name="user_modify_modelform"),
    path("assets_list/", assets.assets, name="assets"),
    path("assets/add/", assets.assets_add, name="assets_add"),
    path("assets/<int:nid>/modify/", assets.assets_modify, name="assets_modify"),
    path("assets/<int:nid>/del/", assets.assets_del, name="assets_del"),
    path("admin_list/", admin_role.admin, name="admin"),
    path("admin/add/", admin_role.admin_add, name="admin_add"),
    path("admin/<int:nid>/modify/", admin_role.admin_modify, name="admin_modify"),
    path("admin/<int:nid>/reset/pwd/", admin_role.admin_reset_pwd, name="admin_reset_pwd"),
    path("admin/<int:nid>/del/", admin_role.admin_del, name="admin_del"),
    path("login/", login.login, name="login"),
    path("logout/", login.logout, name="logout"),
    path("image/code/", login.image_code, name="image_code"),
    path("demo/list/", Ajax_data.demo_list, name="demo_list"),
    path("demo/one/", Ajax_data.demo_one, name="demo_one"),
    path("demo/two/", Ajax_data.demo_two, name="demo_two"),
    path("task/list/", task_data.task_list, name="task_list"),
    path("task/add/", task_data.task_add, name="task_add"),
    path('task/del/', task_data.task_delete, name="task_delete"),
    path('task/modify/', task_data.task_modify, name="task_modify"),
    path('task/modify/content/', task_data.task_modify_content, name="task_modify_content"),
    path("perform/list/", perform.perform_info, name="perform_info"),
    path("perform/add/", perform.add_perform, name="add_perform")
]

好了, 这篇文章关于文件上传功能就到此结束了!!!

以上就是Django的文件上传功能的所有内容了, 如果有哪里不懂的地方,可以把问题打在评论区, 欢迎大家在评论区交流!!!
如果我有写错的地方, 望大家指正, 也可以联系我, 让我们一起努力, 继续不断的进步.
学习是个漫长的过程, 需要我们不断的去学习并掌握消化知识点, 有不懂或概念模糊不理解的情况下,一定要赶紧的解决问题, 否则问题只会越来越多, 漏洞也就越老越大.
人生路漫漫, 白鹭常相伴!!!


网站公告

今日签到

点亮在社区的每一天
去签到