【Django】开发日报_14_Day:手机号码管理系统-实现上传文件功能

文件上传

(1)基本操作

初始化样例
urls,py

    # ------------------上传文件---------------------------------------------------
    path('upload/list/', upload.upload_list),

upload.py

from django.shortcuts import render,HttpResponse
def upload_list(request):
    """上传文件"""
    if request.method == "GET":
        return render(request,"upload_list.html")
    print(request.POST)#请求体中的数据<QueryDict: {'csrfmiddlewaretoken': ['rUgQC4CEdv3vHiWc1v6z8M23TdYHYRNsy6mRqEeYA5HbhJWWz4lXaZNZQCHMAaN7'], 'username': ['123'], 'avator': ['a50f4bfbfbedab643b8ac351f636afc378311ea2.jpg']}>
    print(request.FILES)#请求体发送过来的文件{<MultiValueDict: {}>}
    return HttpResponse("---")

upload_list.html

{
    
    % extends 'template.html' %}
{
    
    % block content %}
    <div class="container">
        <form method="post">
            {
    
    % csrf_token %}
            <input type="text" name="username">
            <input type="file" name="avator">
            <input type="submit" value="提交">
        </form>
    </div>
{
    
    % endblock %}

访问页面
在这里插入图片描述
普通表单只能上传文件名称,不能上传文件内容
在这里插入图片描述

我们要在form标签中新加一个属性enctype="multipart/form-data,才能上传图片文件
在这里插入图片描述
看到文件内容了
在这里插入图片描述
将上传的文件保存到本地

def upload_list(request):
    """上传文件"""
    if request.method == "GET":
        return render(request, "upload_list.html")
    #print(request.POST)  # 请求体中的数据<QueryDict: {'csrfmiddlewaretoken': ['rUgQC4CEdv3vHiWc1v6z8M23TdYHYRNsy6mRqEeYA5HbhJWWz4lXaZNZQCHMAaN7'], 'username': ['123'], 'avator': ['a50f4bfbfbedab643b8ac351f636afc378311ea2.jpg']}>
    #print(request.FILES)  # 请求体发送过来的文件{<MultiValueDict: {}>}
    file_object = request.FILES.get("avator")
    #print(file_object.name)  # 文件名
    f = open(file_object.name, mode='wb')
    #将文件分块读取并保存在本地文件a1.png中
    for chunk in file_object.chunks():
        f.write(chunk)
    f.close()
    return HttpResponse("---")

可以看到项目文件已经写入了一张上传图片了
在这里插入图片描述
基本操作总结:
前端
在这里插入图片描述

后端
在这里插入图片描述

(2)上传Excel
案例1:批量上传

以部门模块为例进行修改
要进行Excel操作需要下载第三方库

 pip install openpyxl

下面将会把Excel中的数据批量传到数据库中
1、准备一张Excel表格
在这里插入图片描述
前端添加
depart_list.html

<div class="panel panel-default">
                <!-- 上传面板 -->
                <div class="panel-heading">
                    <span class="glyphicon glyphicon-th-list" aria-hidden="true"></span>
                    批量上传
                </div>
                <div class="panel-body">
                    <form method="post" enctype="multipart/form-data" action="/depart/multi/">
                        {
    
    % csrf_token %}
                        <div class="form-group">
                            <input type="file" name="exc">
                        </div>
                        <input type="submit" value="上传" class="btn btn-info btn-sm">
                    </form>
                </div>

            </div>

后端
depart.py

def depart_multi(request):
    """批量上传Excel文件"""
    #1、获取用户上传的文件对象
    file_object = request.FILES.get("exc")
    #print(type(file_object))
    #直接打开Excel并读取内容
    #from openpyxl import load_workbook

    #2、对象传递给openpyxl,由openpyxl读取文件的内容
    #wb = load_workbook("本地文件路径")
    wb = load_workbook(file_object)
    sheet = wb.worksheets[0]
    #cell = sheet.cell(2,2)#获取sheet的一行一列
    #print(cell.value)

    #3、循环获取每行数据并添加到数据库
    #sheet.rows()从第一行开始取
    #sheet.iter_rows(min_row=2)#从第二行开始取(排除标题)
    for row in sheet.iter_rows(min_row=2):
        # print(row)
        # (< Cell 'Sheet1'.A2 >,)
        # (< Cell 'Sheet1'.A3 >,)
        # (< Cell 'Sheet1'.A4 >,)
        text = row[0].value
        # print(text)
        # 技术部
        # 运营部
        # 策划部
        exists = models.Department.objects.filter(title=text).exists()
        if not exists:
            models.Department.objects.create(title=text)
    return redirect("/depart/list/")

页面测试
在这里插入图片描述
上传文件
在这里插入图片描述
Excel批量上传总结
在这里插入图片描述
在这里插入图片描述

(3)Form上传
案例2:混合上传

适合
在这里插入图片描述
urls.py

path('upload/form/', upload.upload_form),

创建数据表
model.py

class Boss(models.Model):
    """老板"""
    name = models.CharField(verbose_name="姓名",max_length=32)
    age = models.IntegerField(verbose_name="年龄")
    img = models.CharField(verbose_name="头像",max_length=128)


修改样式
BootStrap,py

class BootStrap:
    #将不需要加BootStrap样式的排除掉
    bootstrap_exclude_fields = [""]
    def __init__(self, *args, **kwargs):
        # 引用父类的ini方法
        super().__init__(*args, **kwargs)
        # 循环ModelForm中的字段,给每个字段的插件设置
        for name, field in self.fields.items():
            if name in self.bootstrap_exclude_fields:
                continue
            # 字段中有属性,保留原来属性,没有属性增加属性
            if field.widget.attrs:
                field.widget.attrs["class"] = "form-control"
                field.widget.attrs["placeholder"] = field.label
            else:
                field.widget.attrs = {
    
    
                    "class": "form-control",
                    "placeholder": field.label
                }

form.py

class UpForm(BootStrapForm):
    #将img加入bootstrap_exclude_fields列表可以排除它的样式
    bootstrap_exclude_fields = ['img']

    name = forms.CharField(label="姓名")
    age = forms.IntegerField(label="年龄")
    img = forms.FileField(label="头像")

upload.py

def upload_form(request):
    """Form上传"""
    title = "Form上传"
    if request.method == "GET":
        form = UpForm()
        return render(request, 'upload_form.html', {
    
    'form': form, "title": title})

    form = UpForm(data=request.POST, files=request.FILES)  # 提交的数据既有文件还有表单
    if form.is_valid():
        # print(form.cleaned_data)
        # {'name': '刘备', 'age': 123, 'img': <InMemoryUploadedFile: 黑曼巴.jpg (image/jpeg)>}

        # 1、读取图片内容,写入到文件夹中并获取文件的路径。
        image_object = form.cleaned_data.get("img")
        # file_path = "app01/static/img/{}".format(image_object.name)
        #存储到项目静态文件(缺点:无法给用户查看)
        file_path = os.path.join("app01", "static", "img", image_object.name)
        f = open(file_path,mode='wb')
        for chunk in image_object.chunks():
            f.write(chunk)
        f.close()

        #为了将图片能让用户看到,不能将app01拼接到路径中,而路径应该是“域名/static/img/图片名”
        db_file_path = os.path.join("static", "img", image_object.name)
        # 2、将能让用户看到的图片文件的路径写入到数据库。
        models.Boss.objects.create(
            name=form.cleaned_data["name"],
            age=form.cleaned_data["age"],
            img=db_file_path,
        )

        imgtest = models.Boss.objects.filter(id=2).first().img
        return render(request, 'upload_form.html', {
    
    "form": form, "title": title,"imgtest":imgtest})
        #return HttpResponse("……")
    return render(request, 'upload_form.html', {
    
    "form": form, "title": title})

upload_form.html

{
    
    % extends 'template.html' %}
{
    
    % block content %}
    <div>
        <div class="container">
            <div class="panel panel-default">
                <div class="panel-heading">
                    <h3 class="panel-title"> {
    
    {
    
     title }} </h3>
                </div>
                <div class="panel-body">
                    <form method="post" enctype="multipart/form-data" novalidate>
                        {
    
    % csrf_token %}
                        {
    
    % for obj in form %}
                            <div class="form-group">
                                <label> {
    
    {
    
     obj.label }} </label>
                                {
    
    {
    
     obj }}
                                <span style="color:red"> {
    
    {
    
     obj.errors.0 }}</span>
                            </div>
                        {
    
    % endfor %}
                        <button type="submit" class="btn btn-primary"> 提交</button>
                    </form>
                </div>
            </div>

            <div class="container">
                <div class="page-header">
                    展示头像
                </div>
                <div class="panel-body">
                    <img src="http://127.0.0.1:8000/{
    
    { imgtest }}">
                </div>
            </div>
        </div>
    </div>
{
    
    % endblock %}

访问页面
在这里插入图片描述
数据库
在这里插入图片描述

案例2文件上传改进(使用media)

在这里插入图片描述

启用media
在这里插入图片描述

from django.urls import path,re_path
from django.conf import settings
from django.views.static import serve

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

在这里插入图片描述

import os

#这两句放在最下面
MEDIA_ROOT = os.path.join(BASE_DIR,"media")
MEDIA_URL = "/media/"

新建media目录
在这里插入图片描述
通过url可以直接访问到media下面的图片
在这里插入图片描述

在这里插入图片描述
对之前图片上传的路径进行修改
在这里插入图片描述
此时进行上传,数据库中存放的是绝对路径
在这里插入图片描述
修改项目相对路径

#media_path = os.path.join(settings.MEDIA_ROOT, image_object.name)
media_path = os.path.join("media", image_object.name)

重新上传
在这里插入图片描述
upload.py

def upload_form(request):
    """Form上传"""
    title = "Form上传"
    if request.method == "GET":
        form = UpForm()
        return render(request, 'upload_form.html', {
    
    'form': form, "title": title})

    form = UpForm(data=request.POST, files=request.FILES)  # 提交的数据既有文件还有表单
    if form.is_valid():
        # print(form.cleaned_data)
        # {'name': '刘备', 'age': 123, 'img': <InMemoryUploadedFile: 黑曼巴.jpg (image/jpeg)>}

        # 1、读取图片内容,写入到文件夹中并获取文件的路径。
        image_object = form.cleaned_data.get("img")

        #media_path = os.path.join(settings.MEDIA_ROOT, image_object.name)
        media_path = os.path.join("media", image_object.name)
        f = open(media_path,mode='wb')
        for chunk in image_object.chunks():
            f.write(chunk)
        f.close()
        # 2、将能让用户看到的图片文件的路径写入到数据库。
        models.Boss.objects.create(
            name=form.cleaned_data["name"],
            age=form.cleaned_data["age"],
            img=media_path,
        )
        return HttpResponse("……")
    return render(request, 'upload_form.html', {
    
    "form": form, "title": title})

(4)ModelForm上传
案例3:混合上传

修改一下导航栏
template.html

{
    
    % load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>
        {
    
    % block title_content %}
        {
    
    % endblock %}
    </title>
    <link rel="stylesheet" href="{% static 'plugins/bootstrap-3.4.1/css/bootstrap.min.css' %}">
</head>
<body>
<!--导航-->
<div class="bs-example" data-example-id="inverted-navbar">
    <nav class="navbar navbar-inverse">
        <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-9" 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="/pretty/list/">靓号管理系统</a>
            </div>

            <!-- Collect the nav links, forms, and other content for toggling -->
            <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-9">
                <ul class="nav navbar-nav">
                    <li class="dropdown">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
                           aria-expanded="false">功能管理 <span class="caret"></span></a>
                        <ul class="dropdown-menu">
                            <li><a href="/depart/list/">部门管理</a></li>
                            <li><a href="/user/list/">用户管理</a></li>
                            <li><a href="/pretty/list/">靓号管理</a></li>
                            <li><a href="/task/list/">任务管理</a></li>
                            <li><a href="/order/list/">订单管理</a></li>
                        </ul>
                    </li>
                    <li><a href="/admin/list/">管理员账户</a></li>
                    <li><a href="/chart/list/">数据统计</a></li>
                    <li><a href="/chart/highcharts/">highcharts示例</a></li>
                    <li><a href="/upload/list/">Excel上传</a></li>
                    <li><a href="/upload/form/">Form上传</a></li>
                    <li><a href="/upload/modelform/">ModelForm上传</a></li>

                </ul>
                <ul class="nav navbar-nav navbar-right">
                    <li><a href="/login/">登录</a></li>
                    <li class="dropdown">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
                           aria-expanded="false">{
    
    {
    
     request.session.info.name }} <span class="caret"></span></a>
                        <ul class="dropdown-menu">
                            <li><a href="#">个人资料</a></li>
                            <li><a href="#">我的信息</a></li>
                            <li role="separator" class="divider"></li>
                            <li><a href="/logout/">注销</a></li>
                        </ul>
                    </li>
                </ul>
            </div><!-- /.navbar-collapse -->

        </div><!-- /.container-fluid -->
    </nav>
</div>

{
    
    % block content %}{
    
    % endblock %}

<script src="{% static 'js/jquery-3.6.0.min.js' %}"></script>
<script src="{% static 'plugins/bootstrap-3.4.1/js/bootstrap.min.js' %}"></script>

{
    
    % block js %}{
    
    % endblock %}
</body>
</html>

在这里插入图片描述

urls,py

 path('upload/modelform/', upload.upload_modelform),

models.py

class City(models.Model):
    """城市"""
    name = models.CharField(verbose_name="名称",max_length=32)
    count = models.IntegerField(verbose_name="人口")
    #FileField本质上也是CharField,可以自动保存数据,还能自动上传到media目录(media/city)
    img = models.FileField(verbose_name="Logo",max_length=128,upload_to='city/')
makemigrations
migrate

form,py

class UpModelForm(BootStrapModelForm):
    bootstrap_exclude_fields = ['img']

    class Meta:
        model = models.City
        bootstrap_exclude_fields = ['img']
        fields = "__all__"

upload.py

def upload_modelform(request):
    """ModelForm上传文件和数据"""
    title="ModelForm上传"
    if request.method == "GET":
        form = UpModelForm()
        return render(request, 'upload_modelform.html',{
    
    "title":title,'form':form})
    form = UpModelForm(data=request.POST,files = request.FILES)
    if form.is_valid():
        #对应文件自动保存
        #字段+上传路径写入到数据库
        form.save()
        return HttpResponse("成功!")
    return render(request, 'upload_modelform.html', {
    
    "title": title, 'form': form})

upload_modelform.html

{
    
    % extends 'template.html' %}
{
    
    % block content %}
    <div>
        <div class="container">
            <div class="panel panel-default">
                <div class="panel-heading">
                    <h3 class="panel-title"> {
    
    {
    
     title }} </h3>
                </div>
                <div class="panel-body">
                    <form method="post" enctype="multipart/form-data" novalidate>
                        {
    
    % csrf_token %}
                        {
    
    % for obj in form %}
                            <div class="form-group">
                                <label> {
    
    {
    
     obj.label }} </label>
                                {
    
    {
    
     obj }}
                                <span style="color:red"> {
    
    {
    
     obj.errors.0 }}</span>
                            </div>
                        {
    
    % endfor %}
                        <button type="submit" class="btn btn-primary"> 提交</button>
                    </form>
                </div>
            </div>
        </div>
    </div>
{
    
    % endblock %}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
小结
在这里插入图片描述

添加显示页面

urls.py

    # 城市列表
    path('city/list/', city.city_list),
    path('city/add/', city.city_add),

city.py

from django.shortcuts import render, redirect
from app01.utils.pagination import Pagination
from app01 import models
from app01.utils.form import UpModelForm


def city_list(request):
    """城市列表"""
    queryset = models.City.objects.all()
    page_object = Pagination(request, queryset)
    context = {
    
    
        "queryset": page_object.page_queryset,
        "page_string": page_object.html(),
    }
    return render(request, "city_list.html", context)


def city_add(request):
    """添加城市"""
    title = "新建城市"
    if request.method == "GET":
        form = UpModelForm()
        return render(request, 'upload_modelform.html', {
    
    "title": title, 'form': form})
    form = UpModelForm(data=request.POST, files=request.FILES)
    if form.is_valid():
        # 对应文件自动保存
        # 字段+上传路径写入到数据库
        form.save()
        return redirect("/city/list/")
    return render(request, 'upload_modelform.html', {
    
    "title": title, 'form': form})

city_list.html

{
    
    % extends 'template.html' %}
{
    
    % block content %}
    <div>
        <div class="container">
            <div style="margin-bottom: 10px">
                <a class="btn btn-success" href="/city/add/">
                    <span class="glyphicon glyphicon-plus-sign" aria-hidden="true"></span>
                    新建城市
                </a>
            </div>
            <!--表格面板-->
            <div class="panel panel-default">
                <!-- Default panel contents -->
                <div class="panel-heading">
                    <span class="glyphicon glyphicon-th-list" aria-hidden="true"></span>
                    城市列表
                </div>
                <!-- Table -->
                <table class="table table-bordered">
                    <thead>
                    <tr>
                        <th>ID</th>
                        <th>Logo</th>
                        <th>名称</th>
                        <th>人口</th>
                    </tr>
                    </thead>
                    <tbody>
                    {
    
    % for obj in queryset %}
                        <tr>
                            <th>{
    
    {
    
     obj.id }}</th>

                            <td>
                                <img src="/media/{
    
    { obj.img }}" style="height: 60px;">
                            </td>

                            <td>{
    
    {
    
     obj.name }}</td>
                        <td>{
    
    {
    
     obj.count }}</td>
                        </tr>
                    {
    
    % endfor %}
                    </tbody>
                </table>
            </div>
            <ul class="pagination">
                {
    
    {
    
     page_string }}
            </ul>
        </div>
    </div>
{
    
    % endblock %}


访问页面
在这里插入图片描述

(5)完结散花

这个案例级项目终于跟着做完了,大概用了十五天时间,受益匪浅,有机会做几个企业级项目,在此真的非常非常感谢武老师!!!
视频链接

猜你喜欢

转载自blog.csdn.net/qq_51701007/article/details/127125844