高级应用三

高级应用

一、Admin后台管理

1、概述

什么是admin?

admin是后台可视化界面管理系统 方便模型的操作与维护

2、配置

  • settings.py
    INSTALLED_APPS = [
    'django.contrib.admin',
    ]
    汉化
    LANGUAGE_CODE = 'zh-Hans'

    TIME_ZONE = 'Asia/Shanghai'
    
  • 创建用户进行访问
    python manage.py createsuperuser
    依次输入用户名 邮箱 密码

  • 路由访问
    127.0.0.1:8000/admin/

3、配置后台

班级与学生模型类

  • models.py
    from django.db import models

    # 创建班级模型
    class Grade(models.Model):
        gname = models.CharField(max_length=10, default='python36')
        gnum = models.SmallIntegerField(default=30)
        gboynum = models.SmallIntegerField(default=15)
        ggirlnum = models.SmallIntegerField(default=15)
        def __str__(self):
            return self.gname
        class Meta:
            db_table = 'grade'
    
    
    # 创建学生模型
    class Student(models.Model):
        sname = models.CharField(max_length=10, default='张三')
        sage = models.SmallIntegerField(default=18)
        ssex = models.BooleanField(default=True)
        # 一对多外键关系 从表随着主表而删除
        # sgrade = models.ForeignKey(Grade, on_delete=models.CASCADE)
        # sgrade = models.ForeignKey(Grade, on_delete=models.SET_NULL, null=True)
        # sgrade = models.ForeignKey(Grade, on_delete=models.PROTECT)
        sgrade = models.ForeignKey(Grade, on_delete=models.SET_DEFAULT, default=1)
    
        def __str__(self):
            return self.sname
        class Meta:
            db_table = 'student'
    
  • 设置为中文显示(字段在后台进行中文显示)
    class Grade(models.Model):
    ...
    ggirlnum = models.SmallIntegerField(default=15, verbose_name='女生人数')
    class Meta:
    db_table = 'grade'
    verbose_name = '班级'
    class Student(models.Model):
    ...

  • admin.py
    from django.contrib import admin
    from App.models import Grade, Student

    # class StudentInfo(admin.StackedInline):  # 竖着
    class StudentInfo(admin.TabularInline):  # 横着
        model = Student
        extra = 2
    
    @admin.register(Grade)
    class GradeAdmin(admin.ModelAdmin):
        inlines = [StudentInfo]
        # 字段显示
        list_display = ['pk', 'gname', 'gnum', 'gboynum', 'ggirlnum']
        # 过滤字段
        list_filter = ['gname']
        # 搜索字段
        search_fields = ['gname']
        # 分页
        list_per_page = 5  # 每页显示五条数据
        # 更改添加修改样式
        # fields = ['gname', 'gnum', 'gboynum', 'ggirlnum']
        # 添加修改分组(fieldsets和fields不能同时存在)
        fieldsets = [
            ('组一', {'fields':['gboynum', 'ggirlnum']}),
            ('组二', {'fields':['gname', 'gnum']})
        ]
    
    
    
    @admin.register(Student)
    class StudentAdmin(admin.ModelAdmin):
        def show_sex(self):
            if self.ssex:
                return '男'
            else:
                return '女'
    
        show_sex.short_description = '性别'
        list_display = ['pk', 'sname', 'sage', show_sex, 'sgrade']
    
    
    # Register your models here.
    # admin.site.register(Grade, GradeAdmin)
    # admin.site.register(Student, StudentAdmin)
    

二、邮件发送

https://docs.djangoproject.com/zh-hans/3.2/topics/email/#django.core.mail.send_mass_mail

1、配置

基础阶段里面的邮箱配置

2、发送邮件

def test_send_mail(req):
    from django.core.mail import send_mail
    send_mail(
        '主体',
        '邮件内容',
        settings.EMAIL_HOST_USER,
        ['793390457@qq.com'],
        fail_silently=False,
    )
    return HttpResponse('发送邮件')

3、群发

from django.core.mail import send_mass_mail
message1 = ('Subject here', 'Here is the message', 'from@example.com', ['first@example.com', 'other@example.com'])
message2 = ('Another Subject', 'Here is another message', 'from@example.com', ['second@test.com'])
send_mass_mail((message1, message2), fail_silently=False)

send_mass_mail()和send_mail()之间的主要区别在于,send_mail()每次执行时都会打开到邮件服务器的连接,而send_mass_mail()对其所有邮件使用单个连接。这使得send_mass_mail()的效率略微提高。

4、使用文本和html发送

from django.core.mail import EmailMultiAlternatives

subject, from_email, to = 'hello', 'from@example.com', 'to@example.com'
text_content = 'This is an important message.'
html_content = '<p>This is an <strong>important</strong> message.</p>'
msg = EmailMultiAlternatives(subject, text_content, from_email, [to])
msg.attach_alternative(html_content, "text/html")
msg.send()

5、使用html发送

from django.core.mail import send_mass_mail, EmailMessage
msg = EmailMessage('主体', '<b>邮件内容</b>', settings.EMAIL_HOST_USER, ['793390457@qq.com','948807313@qq.com'])
    msg.content_subtype = "html"  # Main content is now text/html
    msg.send()

三、分页

1、Paginator对象

  • 创建对象
    Paginator()
  • 属性
    count 对象总数
    num_pages 页面总数
    page_range 页码列表
  • 方法
    page(num)

2、page对象

通过Paginator的方法page 得到page对象

  • 属性
    object_list 当前页上所有数据
    number 当前页的页码值
    paginator 获取paginator 对象
  • 方法
    has_next 是否有下一页
    has_previous 是否有上一页
    next_page_num 返回下一页页码
    previous_page_num 返回上一页页码

3、实例

  • views.py
    def index(req):
    nowPage = req.GET.get('page',1)
    stu = Student.objects.all()
    p = Paginator(stu, 2)
    # print(p)

        # 通过页码获取当前页的对象
        try:
            # 判断页码是否合法
            if int(nowPage) >= int(p.num_pages):
                nowPage = p.num_pages
            page = p.page(nowPage)
        except:
            page = p.page(p.num_pages)
    
        return render(req, 'index.html', {'page': page})
    
  • index.html




    Title



    首页

    <ol>
        {% for s in page.object_list   %}
            <li>{{ s.sname }}</li>
        {% endfor %}
    </ol>
    
    <nav aria-label="Page navigation">
      <ul class="pagination pagination-lg">
        <li>
          <a {% if page.has_previous %}href="{% url 'App:index' %}?page={{ page.previous_page_number }}"{% endif %} aria-label="Previous">
            <span aria-hidden="true">&laquo;</span>
          </a>
        </li>
          {% for index in page.paginator.page_range %}
              <li {% if index == page.number %}class="active"{% endif %}><a href="{% url 'App:index' %}?page={{ index }}">{{ index }}</a></li>
          {% endfor %}
    
    {#    <li><a href="#">2</a></li>#}
        <li>
          <a {% if page.has_next %}href="{% url 'App:index' %}?page={{ page.next_page_number }}"{% endif %} aria-label="Next">
            <span aria-hidden="true">&raquo;</span>
          </a>
        </li>
      </ul>
    </nav>
    </body>
    </html>
    

四、中间件

1、说明

中间件就是在请求与响应过程中 进行安全验证的功能 每个中间件组件都会负责做一些特定的功能

2、本质

python类

3、使用场景

  • 白名单、黑名单
  • url访问过滤
  • 缓存

浏览器->中间件->url路由地址分发->中间件->视图函数->中间件->响应->

4、方法

  • process_request(self, req)
    在执行视图之前被调用(分配url匹配视图) 每个请求都会被调用 返回None或者response对象
  • process_view(self, req, view_func, view_args, view_kwargs)
    调用视图之前进行调用 每个表请求都会调用 返回None或者response对象
  • process_response(self, req, response)
    所有响应在返回浏览器之前都会被调用 返回response
  • process_exception(self, req, exception)
    当视图抛出异常时进行调用

5、自定义中间件

  • App同级创建middleware文件夹
    App/
    middleware/
    myMiddly.py

  • myMiddly.py中创建MyMiddle类
    from django.utils.deprecation import MiddlewareMixin
    from django.shortcuts import HttpResponse, redirect

    class MyMiddle(MiddlewareMixin):
        def process_request(self, req):
            print(req.path)
            print(req.method)
            print(req.META['REMOTE_ADDR'])
            # if req.META['REMOTE_ADDR'] == '127.0.0.1':
            #     return HttpResponse('您被拦截了')
    
        def process_exception(self, req, exception):
            print(exception)
            return redirect('/a/')
    
  • settings.py
    middleware中添加
    'middleware.myMiddle.MyMiddle',

五、用户认证

1、说明

auth_user 是用来维护用户信息的关系模式

2、auth_user

CREATE TABLE `auth_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `password` varchar(128) NOT NULL,
  `last_login` datetime(6) DEFAULT NULL,
  `is_superuser` tinyint(1) NOT NULL,
  `username` varchar(150) NOT NULL,
  `first_name` varchar(150) NOT NULL,
  `last_name` varchar(150) NOT NULL,
  `email` varchar(254) NOT NULL,
  `is_staff` tinyint(1) NOT NULL,
  `is_active` tinyint(1) NOT NULL,
  `date_joined` datetime(6) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

3、用户模型属性方法

  • is_staff
    boolean 用户是否可以访问后台界面 默认False
  • is_active
    boolean 用户是否活跃 是否当前删除用户 默认True
  • is_authenticated()
    用户是否通过验证 (是否登录)
    request.user.is_authenticated()
  • make_password()
    密码加密 django自带的hash加密
  • check_password()
    验证密码是否正确
  • set_password()
    修改密码
  • authenticated()
    验证用户名和密码是否正确
    authenticated(username=username, password=password) 结果bool
  • create_user() 创建用户
    User.objects.create_user(username, email, password)
  • request.user
    获取当前用户登录对象
  • login_required
    设置当前视图只能登录后进行访问
  • login()
    处理登录
    login(req, user)
  • logout()
    退出登录
    logout(req)

4、注册

  • register.html



    注册页面



    {{ msg }}




    {% csrf_token %}




    *(为必填)

                    <div class="menu">密码:</div>
                        <div class="kong">
                            <input id="text2" type="password" name="userpass" onblur="check()">
                            <span id="div2" class="tian" style="margin-top: 5px">*(为必填)</span>
                        </div>
                    <div class="menu">确认密码:</div>
                        <div class="kong">
                            <input id="text3" type="password" name="01" onblur="check()">
                            <span id="div3" class="tian" style="margin-top: 5px">*(为必填)</span>
                        </div>
                    <div class="menu">邮箱地址:</div>
                        <div class="kong">
                            <input id="text4" type="text" name="email" onblur="check()" required>
                            <span id="div4" class="tian" style="margin-top: 5px">*(为必填)</span>
                        </div>
            </div>
            <div class="can">
                <input id="i111" type="submit" name="002" value="注  册">
                <p style="width: 200px;display: inline-block;"></p>
                <input id="i222" type="button" name="004" value="取  消">
            </div>
        </form>
        <script type="text/javascript">
                //刷新or取消
                document.getElementById('i77').onclick = function(){
                    location.reload();
                }
                document.getElementById('i222').onclick = function(){
                    location.reload();
                }
    
                //用户名验证
                function checkname(){
                    var div = document.getElementById("div1");
                    div.innerHTML = "";
                    var name1 = document.tijiao.text1.value;
                    if (name1 == "") {
                    div.innerHTML = "用户名不能为空!";
                    document.tijiao.text1.focus();
                    return false;
                }
                    if (name1.length < 4 || name1.length > 16) {
                    div.innerHTML = "长度4-16个字符";
                    document.tijiao.text1.select();
                    return false;
                }
                    var charname1 = name1.toLowerCase();
                    for (var i = 0; i < name1.length; i++) {
                    var charname = charname1.charAt(i);
                    if (!(charname >= 0 && charname <= 9) && (!(charname >= 'a' && charname <= 'z')) && (charname != '_')) {
                        div.innerHTML = "用户名包含非法字符";
                        document.form1.text1.select();
                        return false;
                    }
                }
                    return true;
            }
    
                //密码验证
                function checkpassword(){
                    var div = document.getElementById("div2");
                    div.innerHTML = "";
                    var password = document.tijiao.text2.value;
                    if (password == "") {
                    div.innerHTML = "密码不能为空";
                    {#document.tijao.text2.focus();#}
                    return false;
                }
                    if (password.length < 4 || password.length > 16) {
                    div.innerHTML = "密码长度为4-16位";
                    document.tijiao.text2.select();
                    return false;
                    }
                    return true;
            }
    
                function checkrepassword(){
                    var div = document.getElementById("div3");
                    div.innerHTML = "";
                    var password = document.tijiao.text2.value;
                    var repass = document.tijiao.text3.value;
                    if (repass == "") {
                    div.innerHTML = "密码不能为空";
                    document.tijiao.text3.focus();
                    return false;
                    }
                    if (password != repass) {
                    div.innerHTML = "密码不一致";
                    document.tijiao.text3.select();
                    return false;
                    }
                    return true;
                }
            //邮箱验证
            function checkEmail(){
                var div = document.getElementById("div4");
                div.innerHTML = "";
                var email = document.tijiao.text4.value;
                var sw = email.indexOf("@", 0);
                var sw1 = email.indexOf(".", 0);
                var tt = sw1 - sw;
                if (email.length == 0) {
                div.innerHTML = "邮箱不能为空";
                document.tijiao.text5.focus();
                return false;
                }
    
                if (email.indexOf("@", 0) == -1) {
                div.innerHTML = "必须包含@符号";
                document.tijiao.text5.select();
                return false;
                }
    
                if (email.indexOf(".", 0) == -1) {
                div.innerHTML = "必须包含.符号";
                document.tijiao.text5.select();
                return false;
                }
    
                if (tt == 1) {
                    div.innerHTML = "@和.不能一起";
                    document.tijiao.text5.select();
                    return false;
                }
    
                if (sw > sw1) {
                    div.innerHTML  = "@符号必须在.之前";
                    document.tijiao.text5.select();
                    return false;
                }
                else {
                    return true;
                }
                return ture;
                }
    
                function check(){
                if (checkname() && checkpassword() && checkrepassword() && checkEmail()) {
                return true;
                }
                else {
                return false;
            }
        }
        </script>
    </body>
    </html>
    
  • views.py
    # 注册
    def register(req):
    message = ''
    if req.method == 'POST':
    username = req.POST.get('username')
    email = req.POST.get('email')
    userpass = req.POST.get('userpass')
    u = User.objects.filter(username=username).exists()
    if not u:
    User.objects.create_user(username=username, email=email, password=userpass)
    return redirect('/login/')
    else:
    message = '该用户以存在'
    return render(req, 'register.html', {'msg': message})
    自己完善python正则验证用户名 密码 邮箱
    完善正则验证

5、登录

  • views.py
    from django.contrib.auth import authenticate, login

    # 登录
    def user_login(req):
        if req.method == 'POST':
            username = req.POST.get('username')
            userpass = req.POST.get('userpass')
            u = authenticate(username=username, password=userpass)
            if u:
                login(req, u)
                return redirect('/')
            else:
                return redirect('/login/')
        return render(req, 'login.html')
    
  • login.html



    登录页面





    {% csrf_token %}




    *(为必填)

                    <div class="menu">密码:</div>
                        <div class="kong">
                            <input id="text2" type="password" name="userpass" onblur="check()">
                            <span id="div2" class="tian" style="margin-top: 5px">*(为必填)</span>
                        </div>
                   {% comment %} <div class="menu">确认密码:</div>
                        <div class="kong">
                            <input id="text3" type="password" name="01" onblur="check()">
                            <span id="div3" class="tian" style="margin-top: 5px">*(为必填)</span>
                        </div>
                    <div class="menu">邮箱地址:</div>
                        <div class="kong">
                            <input id="text4" type="text" name="email" onblur="check()" required>
                            <span id="div4" class="tian" style="margin-top: 5px">*(为必填)</span>
                        </div>
            {% endcomment %}
            </div>
            <div class="can">
                <input id="i111" type="submit" name="002" value="注  册">
                <p style="width: 200px;display: inline-block;"></p>
                <input id="i222" type="button" name="004" value="取  消">
            </div>
        </form>
        <script type="text/javascript">
                //刷新or取消
                document.getElementById('i77').onclick = function(){
                    location.reload();
                }
                document.getElementById('i222').onclick = function(){
                    location.reload();
                }
    
                //用户名验证
                function checkname(){
                    var div = document.getElementById("div1");
                    div.innerHTML = "";
                    var name1 = document.tijiao.text1.value;
                    if (name1 == "") {
                    div.innerHTML = "用户名不能为空!";
                    document.tijiao.text1.focus();
                    return false;
                }
                    if (name1.length < 4 || name1.length > 16) {
                    div.innerHTML = "长度4-16个字符";
                    document.tijiao.text1.select();
                    return false;
                }
                    var charname1 = name1.toLowerCase();
                    for (var i = 0; i < name1.length; i++) {
                    var charname = charname1.charAt(i);
                    if (!(charname >= 0 && charname <= 9) && (!(charname >= 'a' && charname <= 'z')) && (charname != '_')) {
                        div.innerHTML = "用户名包含非法字符";
                        document.form1.text1.select();
                        return false;
                    }
                }
                    return true;
            }
    
                //密码验证
                function checkpassword(){
                    var div = document.getElementById("div2");
                    div.innerHTML = "";
                    var password = document.tijiao.text2.value;
                    if (password == "") {
                    div.innerHTML = "密码不能为空";
                    {#document.tijao.text2.focus();#}
                    return false;
                }
                    if (password.length < 4 || password.length > 16) {
                    div.innerHTML = "密码长度为4-16位";
                    document.tijiao.text2.select();
                    return false;
                    }
                    return true;
            }
    
                function checkrepassword(){
                    var div = document.getElementById("div3");
                    div.innerHTML = "";
                    var password = document.tijiao.text2.value;
                    var repass = document.tijiao.text3.value;
                    if (repass == "") {
                    div.innerHTML = "密码不能为空";
                    document.tijiao.text3.focus();
                    return false;
                    }
                    if (password != repass) {
                    div.innerHTML = "密码不一致";
                    document.tijiao.text3.select();
                    return false;
                    }
                    return true;
                }
            //邮箱验证
            function checkEmail(){
                var div = document.getElementById("div4");
                div.innerHTML = "";
                var email = document.tijiao.text4.value;
                var sw = email.indexOf("@", 0);
                var sw1 = email.indexOf(".", 0);
                var tt = sw1 - sw;
                if (email.length == 0) {
                div.innerHTML = "邮箱不能为空";
                document.tijiao.text5.focus();
                return false;
                }
    
                if (email.indexOf("@", 0) == -1) {
                div.innerHTML = "必须包含@符号";
                document.tijiao.text5.select();
                return false;
                }
    
                if (email.indexOf(".", 0) == -1) {
                div.innerHTML = "必须包含.符号";
                document.tijiao.text5.select();
                return false;
                }
    
                if (tt == 1) {
                    div.innerHTML = "@和.不能一起";
                    document.tijiao.text5.select();
                    return false;
                }
    
                if (sw > sw1) {
                    div.innerHTML  = "@符号必须在.之前";
                    document.tijiao.text5.select();
                    return false;
                }
                else {
                    return true;
                }
                return ture;
                }
    
                function check(){
                if (checkname() && checkpassword() && checkrepassword() && checkEmail()) {
                return true;
                }
                else {
                return false;
            }
        }
        </script>
    </body>
    </html>
    
  • index.html




    Title


    首页





    {% if request.user.is_authenticated %}
    欢迎:{{ request.user.username }}|退出登录
    {% else %}
    登录|注册
    {% endif %}



6、退出登录

  • views.py
    from django.contrib.auth import logout

    # 退出登录
    def user_logout(req):
        logout(req)
        return redirect('/')
    

7、修改密码

@login_required(login_url='/login/')
def update_password(req):
    if req.method == 'POST':
        old_userpass = req.POST.get('old_userpass')
        new_userpass = req.POST.get('new_userpass')
        username = req.user.username
        u = authenticate(username=username, password=old_userpass)
        if u:
            # 修改密码
            u.set_password(new_userpass)
            u.save()
            return redirect('/logout/')
        else:
            return redirect('/update_password/')
    return render(req, 'update_password.html')

配置全局login_url

settings.py

LOGIN_URL = '/login/'

views.py

@login_required
def update_password(req):
    return redirect('/update_password/')

8、配置优美前端页面

安装扩展库:

  • pip install django-bootstrap3

bootstrap官网:https://www.bootcss.com/

9、message组件(消息闪现)

  • 说明
    当某个动作处理完进行消息通知
  • 方法
    • message.debug
    • message.info
    • message.success
    • message.warning
    • message.error
  • 导入
    from django.contrib import messages
  • 使用
    def index(req):
    messages.success(req, 'index的消息')
    return render(req, 'index.html')

10、自定义用户表

  • 给auth_user表 添加字段

  • models.py
    from django.contrib.auth.models import AbstractUser
    from django.db import models
    # Create your models here.

    class User(AbstractUser):
        iphone = models.CharField(max_length=11, default='111111')
        icon = models.CharField(max_length=20, default='default.jpg')
        class Meta:
            db_table = 'user'
    
  • 配置 将模型类设置为自定义的模型
    AUTH_USER_MODEL = 'App.User'

  • 执行迁移
    python manage.py makemigrations
    python manage.py migrate

  • 添加自定义认证(可以使用用户名和手机号码都能登录)
    App下创建auth.py
    from django.contrib.auth.backends import ModelBackend
    from django.db.models import Q
    from App.models import User

    class MyBackend(ModelBackend):
        def authenticate(self, request, username=None, password=None, **kwargs):
            try:
                u = User.objects.get(Q(username=username)|Q(iphone=username)|Q(email=username))
            except:
                return None
            if u.check_password(password):
                return u
    
  • settings.py
    AUTHENTICATION_BACKENDS = ['App.auth.MyBackend']

  • views.py
    from App.models import User
    User.objects.create_user(username=username, email=email, password=userpass, iphone='15611833906')

六、文件上传

1、概述

文件上传到服务器端 存储在request.FILES中

2、注意

3、配置文件上传路径

  • 在settings.py
    STATICFILE_DIRS = [os.path.join(BASE_DIR, 'static')] # (前面模板中配置静态资源文件时就进行配置的)
    # 文件上传路径
    MEDIA_ROOT = os.path.join(BASE_DIR, r'App/static/upload')

4、文件上传的属性和方法

属性

  • file.name 文件名称
  • file.size 文件大小

方法

  • file.read() 读取文件上传的所有数据 当前方法适合于小文件
  • file.chunks() 按块返回文件 在循环迭代中 将大块文件拆分成小块写入到文件中
  • file.multiple_chunks()
    当前方法根据文件大小返回True或False 当fileSize大于2.5M 返回True 否则返回False 大小可调整

5、原始文件上传(单文件上传)

  • views.py
    # 原始单文件上传
    def upload_one(req):
    if req.method == 'POST':
    # 获取文件上传对象
    file = req.FILES.get('file')
    # print(file.name)
    # print(file.size)
    path = os.path.join(settings.MEDIA_ROOT, file.name)
    try:
    with open(path, 'wb') as f:
    if file.multiple_chunks():
    for ff in file.chunks():
    f.write(ff)
    else:
    f.write(file.read())
    messages.success(req, '文件上传成功!')
    except:
    messages.success(req, '文件上传失败!')

  • upload.html
    {% extends 'common/base.html' %}
    {% block title %}
    文件上传
    {% endblock %}
    {% block content %}

    文件上传



    {% csrf_token %}




    {% endblock %}
    

6、完整上传

  • views.py
    # 文件类型限制
    def allowed_file(suffix):
    return suffix in settings.ALLOWED_FILES

    # 文件名称随机 uuid
    def random_name(suffix):
        u = str(uuid.uuid4())
        return u+'.'+suffix
    
    
    #  缩放  pillow
    def img_zoom(path, perfix='s_', w=200, h=150):
        img = Image.open(path)
        img2 = img.resize((w, h))
        # 拆分新路径 拼凑新名字
        fileList = os.path.split(path)
        new_path = os.path.join(fileList[0], perfix + fileList[1])
        img2.save(new_path)
    
    
    
    # 完整上传
    # 作业: 文件存储路径为/年/月/日/a.jpg
    def upload_one(req):
        if req.method == 'POST':
            # 获取文件上传对象
            file = req.FILES.get('file')
            # print(file.name)
            # print(file.size)
            # 后缀获取
            suffix = file.name.split('.')[-1]
            # 类型限定
            if not allowed_file(suffix):
                messages.error(req, '文件类型不允许')
                return redirect('/upload_one/')
            # 生成随机文件名
            name = random_name(suffix)
            # 拼凑地址
            path = os.path.join(settings.MEDIA_ROOT, name)
            try:
                with open(path, 'wb') as f:
                    if file.multiple_chunks():
                        for ff in file.chunks():
                            f.write(ff)
                    else:
                        f.write(file.read())
                # 处理图片缩放
                img_zoom(path)
                img_zoom(path, 'm_', 400, 200)
                messages.success(req, '文件上传成功!')
            except:
                messages.success(req, '文件上传失败!')
    
        return render(req, 'own_center/upload.html')
    

7、多文件上传

  • views.py
    def upload_many(req):
    if req.method == 'POST':
    file_list = req.FILES.getlist('file')
    try:
    for file in file_list:
    path = os.path.join(settings.MEDIA_ROOT, file.name)
    with open(path, 'wb') as fw:
    if file.multiple_chunks():
    for ff in file.chunks():
    fw.write(ff)
    else:
    fw.write(file.read())
    messages.success(req, '文件上传成功!')
    except:
    messages.success(req, '文件上传失败!')
    return render(req, 'own_center/upload_many.html')

  • upload_many.html
    {% extends 'common/base.html' %}
    {% block title %}
    文件上传
    {% endblock %}
    {% block content %}

    多文件上传



    {% csrf_token %}




    {% endblock %}
    
posted @ 2022-03-01 10:08  寻月隐君  阅读(21)  评论(0编辑  收藏  举报