栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

Django快速入门

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

文章目录
  • Django学习
    • 1、项目创建
    • 2、默认项目介绍
    • 3、app的创建和说明
    • 4、启动运行Django
      • 4.1**确保app已注册**
      • 4.2 **编写URL和视图函数的对应关系【urls.py】**
      • 4.3**编写视图函数【views.py】**
      • 4.4**启动Django项目**
      • 4.5、templates模板
      • 4.6、静态文件
    • 5、模板语法
      • **案例:伪联通新闻中心**
    • 6、请求和响应
      • 案例:用户登录
    • 7、数据库操作
      • 7.1、安装mysqlclient
      • 7.2、orm创建数据库
        • 1、创建数据库
        • 2、Django连接数据库
        • 3、Django操作表
        • 3.1、创建表
        • 3.2、执行命令
        • 3.3、操作表中的数据
        • 案例:用户管理
          • 1.、展示用户列表
          • 2、添加用户
          • 3、删除用户
      • 8、员工管理系统
        • 8.1、创建项目
        • 8.2、创建app,终端运行 **python manage.py startapp xxx**
        • 8.3、注册app
        • 8.4、设计表结构
        • 8.5、配置数据库
        • 8.6、生成表
        • 8.7、创建静态文件和模板文件
        • 8.8、部门管理
          • 8.8.1、urls
          • 8.8.2、views
    • 9、html继承
    • 10、用户管理
      • 10.2、用户列表
      • 10.3、添加用户
        • 10.3.1、初识Form
          • 1、views.py
          • 2、user_add.html
        • 10.3.2、ModelForm(最简便)
          • 1、models.py
          • 2、views.py
        • 10.3.3、添加用户
          • 1、views.py
          • 2、html
      • 10.4、编辑用户
    • 11、总结-1
    • 12、 靓号管理
      • 搜索
      • 分页
    • 13、管理员操作
    • 14、用户登录
      • 14.1、session登录
      • 14.2、Django的中间件
      • 14.3、编写登录中间件
      • 14.4、注销
      • 14.5、模板登录信息
      • 14.5、图片验证码
        • 5.1、生成图片
        • 5.2、函数
        • 5.3、urls路径
        • 5.4、视图
        • 5.5、前端
      • 14.6、完整的登录
        • 6.1 urls
        • 6.2 视图
        • 6.3、页面
    • 15、Ajax
      • 15.1、get请求
      • 15.2、post请求
      • 15.3、关闭绑定事件
      • 15.4、Ajax请求的返回值
    • 16、订单
        • html
        • 视图
    • 17、文件上传
      • 17.1、基本操作
      • 17.2、Excel批量上传
      • 17.3、混合数据(form)
      • 17.4、启用media,存数据
      • 17.5、混合数据(ModelForm)
    • Django 函数+知识点
      • 分页 --类
      • bootstrap样式-父类
      • 封装
      • md5加密
      • 数据库中获取数据
      • 柱状图
    • 总结

Django学习 1、项目创建

pycharm:

  • 新建项目

  • 删除templates

  • 删除settings里的。。为了不在根目录寻找而是创建的目录下寻找templates目录

  • 修改__ init __.py

import pymysql

pymysql.install_as_MySQLdb()
2、默认项目介绍
djangostudy
	manage.py		【项目的管理,启动项目、创建app、数据管理】【不要动】
    djangostudy
    	__init__.py
        settings.py	【项目配置】	        【**常常操作**】
        urls.py		【url和函数的对应关系】【**常常操作**】
        asgi.py		【接收网络请求】【不要动】
        wsgi.py		【接收网络请求】【不要动】

3、app的创建和说明

说明

-项目
	-app,用户管理【表结构、函数、html模板、css】
    -app,订单管理【表结构、函数、html模板、css】
    -app,后台管理【表结构、函数、html模板、css】
    -app,网站【表结构、函数、html模板、css】
    -app,api【表结构、函数、html模板、css】
    。。。

创建:

app01
	__init__.py
    admin.py		【固定,不用动】Django默认提供了admin后台管理
    apps.py			【固定,不用动】app启动类
    migrations		【固定,不用动】数据库变更记录
    	__init__.py
    models.py		【**重要**】对数据库操作
    tests.py		【固定,不用动】单元测试
    views.py		【**重要**】,函数
4、启动运行Django 4.1确保app已注册

4.2 编写URL和视图函数的对应关系【urls.py】

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z8jJ9pAL-1654077355201)(https://gitee.com/cool-dada/blog_img/raw/master/tree/master/img_markdown/202206011745585.png)]

4.3编写视图函数【views.py】

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iR3AT8Nb-1654077355201)(https://gitee.com/cool-dada/blog_img/raw/master/tree/master/img_markdown/202206011745336.png)]

4.4启动Django项目

4.5、templates模板

4.6、静态文件

在开发过程中一般将 图片、css、js都会当做静态文件处理

static文件夹下存放静态文件

  • plugins:用于存放插件

插件使用+引入

{% static ‘路径’ %}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XXMKjNKJ-1654077355204)(https://gitee.com/cool-dada/blog_img/raw/master/tree/master/img_markdown/202206011746076.png)]

5、模板语法

本质上:在html中写一些占位符,由数据对这些占位符进行替换和处理。

views

def tpl(request):
    name = '李锦彪'
    roles = ['李锦彪', '黄欣宇', '锦欣宇']  # 列表
    user_info = {'name': '李锦彪', 'salary': 26000, 'role': 'ceo'}  # 字典
    data_list = [  # 列表里套字典
        {'name': '李锦彪', 'salary': 26000, 'role': 'ceo'},
        {'name': '李锦彪', 'salary': 26000, 'role': 'ceo'},
        {'name': '李锦彪', 'salary': 26000, 'role': 'ceo'}
    ]

    return render(request,
                  'tpl.html',   # 传入html
                  {  # 传入一个字典,html通过{{ key }}获取value
                      'n1': name,
                      'n2': roles,
                      'n3': user_info,
                      'n4': data_list,
                  }
            )

html

{#  获取传入的值  #}

{{ n1 }}

============================================ {# 获取传入的列表值 #} {# 一个一个拿 #}

{{ n2.0 }}

{{ n2.1 }}

{{ n2.2 }}

{# 循环拿 #}
{% for item in n2 %}

{{ item }}

{% endfor %}

{# 加条线 #} ============================================== {# 获取字典的值 #} {{ n3 }} {# 根据字典的键获取值 #} {{ n3.name }} {{ n3.salary }} {{ n3.role }} {# 循环获取 #}
{# 第一种 #} {# {% for item in n3 %}#} {#
  • {{ item }}
  • #} {# {% endfor %}#} {# 第二种 #} {% for k, v in n3.items %}
  • {{ k }}={{ v }}
  • {% endfor %}

    =============================================== {% if n1 == '李锦彪' %}

    哈哈哈哈

    {% else %}

    黑恶hi诶嘿二哈IE

    {% endif %}

    视图函数的render内部:

    1. 读取含有模板语法的html文件
    2. 内部进行渲染(模板语法执行并替换数据),最终得到只包含html标签的字符串
    3. 将渲染(替换)完成的字符串返还给用户浏览器
    案例:伪联通新闻中心

    **第一步:**urls.py中创建路径

    第二步:views.py中创建函数news

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tvSZ7kfc-1654077355206)(https://gitee.com/cool-dada/blog_img/raw/master/tree/master/img_markdown/202206011746481.png)]

    第三步:编写html文件

    联通新闻中心

      {% for item in news_list %}
    • {{ item.news_title }}
    • {% endfor %}
    6、请求和响应

    关于重定向:当前的页面请求访问其他的页面。其他的页面不同意并且会返回一个值,告诉当前的页面去访问这个值

    # request 是一个对象,封装了用户发送过来的所有请求相关数据
    # 1.【请求】获取请求方式  get/post
    print(request.method)
    
    # 2.【请求】在URL上传递值   http://127.0.0.1:8000/something/?n=100
    print(request.GET)  # 拿到传递的值
    
    # 3.【请求】post请求,在请求体中传递数据
    print(request.POST)
    
    # 4.【响应】HttpResponse('返回内容'),内容字符串返回给请求者
    # return HttpResponse('返回内容')
    
    # 5.【响应】读取html内容  + 渲染(替换) -> 字符串,返回内容给用户浏览器
    # return render(request, 'something.html', {'title': '李锦彪'})
    
    # 6.【响应】让浏览器重定向到其他的页面redirect('https://www.baidu.com')
    return redirect('https://www.baidu.com')
    
    案例:用户登录

    问题:安全机制校验

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cKuj760e-1654077355207)(https://gitee.com/cool-dada/blog_img/raw/master/tree/master/img_markdown/202206011752654.png)]

    解决办法:form表单里加 {% csrf_token %}

    第一步:views.py

    def login(request):
        if request.method == 'GET':
    
            return render(request, 'login.html')
        # 如果是post请求,获取用户提交的数据
        # print(request.POST)
        usr = request.POST.get('username')
        pwd = request.POST.get('password')
        if usr == '15751083927' and pwd == '123':
            # return HttpResponse('登录成功')
            return redirect('https://www.baidu.com')  # 登录成功重定向跳转页面
        else:
            # return HttpResponse('登录失败')
            return render(request, 'login.html', {'error_msg': '登录失败'})
    

    第二步:html

    
    
    
        
        Title
    
    
    
    

    用户登录

    {% csrf_token %} {{ error_msg }}
    7、数据库操作

    Django开发操作数据库,内部提供了orm框架

    7.1、安装mysqlclient 7.2、orm创建数据库

    orm可以帮助我们做两件事:

    • 创建、修改、删除数据库中的表(不用写SQL语句)(无法创建数据库)
    • 操作表中的数据(不用写SQL语句)
    1、创建数据库
    • 启动数据库
    • 自带工具创建数据库
    2、Django连接数据库

    在setting.py文件中,进行配置和修改

    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'ljb',  # 数据库名字
            'USER': 'root',  # 账号
            'PASSWORD': '187365',  # 密码
            'HOST': '127.0.0.1',  # 主机
            'PORT': 3306,  # 端口号
        }
    }
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-18oVfvWK-1654077355208)(https://gitee.com/cool-dada/blog_img/raw/master/tree/master/img_markdown/202206011746040.png)]

    3、Django操作表
    • 创建表
    • 修改表
    • 删除表
    3.1、创建表

    在models.py文件中

    # 创建表
    class Userinfo(models.Model):
        name = models.CharField(max_length=32)  # varchar(32)
        password = models.CharField(max_length=64)
        age = models.IntegerField()  # int 类型
    
    ==相当于
    # create table app01_userinfo(  # 表明为:app01+类名首字母小写
    #     id bigint auto_increment primary key ,  # Django自动加这一行
    #     name varchar(32),
    #     password varchar(64),
    #     age int
    # );
    
    3.2、执行命令

    在终端执行:

    python manage.py makemigrations
    python manage.py migrate
    

    注意:app先注册(settings)

    新增列的时候,由于已经在列中可能已有数据,所以新增列必须要指定新增列对应的数据

    • 手动输入一个值
    • 设置默认值
    age = models.IntegerField(default=2)
    
    • 允许为空
    age = models.IntegerField(null=True, blank=True)
    

    以后在开发中如果想要操作对表结构进行调整

    • 在models.py文件中操作即可

    • 在终端执行命令

      python manage.py makemigrations
      python manage.py migrate
      
    3.3、操作表中的数据

    在views.py中

    def orm(request):
        from app01 import models  # 导入models文件
        # 测试orm表操作表中的数据
    
        
        # #########新建表数据##########
        # models.Userinfo.objects.create(name='李锦彪', password='187365', age=18)
        # models.Userinfo.objects.create(name='黄欣宇', password='187365', age=18)
        # models.Userinfo.objects.create(name='锦欣宇', password='187365', age=18)
    
        
        # ############删除表数据#############
        # 先筛选 filter(xx=xx)
        # 再删除 delete()
        # models.Userinfo.objects.filter(name='李锦彪').delete()
        # all全部删除
        # models.Userinfo.objects.all()
    
        
        # ############获取表数据#############
        # data_list = [行,行。。。]  QuerySet类型的数据
        
        # 拿到所有数据#############
        # data_list = models.Userinfo.objects.all()
        # print(data_list)
        # for obj in data_list:
        #     print(obj.name, obj.password, obj.age)
        
        # 筛选数据#############
        # data_row = models.Userinfo.objects.filter(name='黄欣宇')[0]  # [0]可以改为.first()
        # print(data_row.name, data_row.password, data_row.age)
    
        
        # ############更新表数据#############
        models.Userinfo.objects.filter(name='黄欣宇').update(age=28)
        
        return HttpResponse('成功!')
    
    案例:用户管理 1.、展示用户列表
    • url
    • 函数
      • 获取所有用户的信息
      • html渲染
    def info_list(request):
        # 1.获取数据库中所有用户的信息
        from app01.models import Userinfo
        data_list = Userinfo.objects.all()
        print(data_list)
        # 2.渲染获取到数据
        return render(request, 'info_list.html', {'data_list': data_list})
    
    
    
    
        
        Title
    
    
    

    info_list

    {% for obj in data_list %} {% endfor %}
    ID 姓名 性别 年龄
    {{ obj.id }} {{ obj.name }} {{ obj.password }} {{ obj.age }}
    2、添加用户
    • url
    • 函数
      • get ,看到页面,输入内容
      • post,提交->写入到数据库
    def info_add(request):
        if request.method == "GET":
            return render(request, 'info_add.html')
        # 获取用户提交的数据
        user = request.POST.get("user")
        pwd = request.POST.get("pwd")
        age = request.POST.get("age")
    
        # 加入到数据库
        from app01.models import Userinfo
        Userinfo.objects.create(name=user, password=pwd, age=age)
        # 自动跳转
        return redirect('/info/list')
    
    
    
    
        
        Title
    
    
    

    添加用户

    {% csrf_token %}
    3、删除用户
    • url
    • 函数
    def info_delete(request):
        nid = request.GET.get('nid')
        from app01.models import Userinfo
        Userinfo.objects.filter(id=nid).delete()
        return redirect('/info/list')
    
    
    
    
        
        Title
    
    
    

    info_list

    添加 {% for obj in data_list %} {% endfor %}
    ID 姓名 性别 年龄 操作
    {{ obj.id }} {{ obj.name }} {{ obj.password }} {{ obj.age }} 删除
    8、员工管理系统 8.1、创建项目

    删除templates文件夹,删除

    8.2、创建app,终端运行 python manage.py startapp xxx 8.3、注册app 8.4、设计表结构
    from django.db import models
    
    
    class Department(models.Model):
        """部门表"""
        title = models.CharField(verbose_name='标题', max_length=32)
    
    
    class Userinfo(models.Model):
        """员工表"""
        name = models.CharField(verbose_name='姓名', max_length=32)
        password = models.CharField(verbose_name='密码', max_length=64)
        age = models.IntegerField(verbose_name='密码')
        sex_choice = (
            (True, '男'),
            (False, '女')
        )
        sex = models.BooleanField(verbose_name='性别', choices=sex_choice)
        
        account = models.DecimalField(verbose_name='账户余额', max_digits=10, decimal_places=2, default=0)
        create_time = models.DateTimeField(verbose_name='入职时间')
        # title_id = models.BigIntegerField(verbose_name='部门ID')  无约束
        # 1.有约束(外键)
        #   to:与哪张表关联
        #   to_field:表中的某一列关联
        #   生成列;depart_id
        # depart = models.ForeignKey(to="Department", to_field="id")
        # 2.部门表被删除
        # 2.1  级联删除
        # depart = models.ForeignKey(to="Department", to_field="id", on_delete=models.CASCADE)
        # 2.2  置空
        depart = models.ForeignKey(verbose_name='部门', to="Department", to_field="id", 
                                   null=True, blank=True, on_delete=models.CASCADE)
    
    
    8.5、配置数据库
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'ljb',  # 数据库名字
            'USER': 'root',  # 账号
            'PASSWORD': '187365',  # 密码
            'HOST': '127.0.0.1',  # 主机
            'PORT': 3306,  # 端口号
        }
    }
    
    8.6、生成表
    python manage.py makemigrations
    python manage.py migrate
    

    注意:

    报错:

    解决:

    原因:PyMySQL 是在 Python3.x 版本中用于连接 MySQL 服务器的一个库,Python2中则使用mysqldb。
    MySQLdb并不支持Python3.

    8.7、创建静态文件和模板文件

    8.8、部门管理 8.8.1、urls
    urlpatterns = [
        # path('admin/', admin.site.urls),
        path('depart/list/', views.depart_list),
        path('depart/delete/', views.depart_delete),
    
        # http://127.0.0.1:8000/depart/12/edit/
        # http://127.0.0.1:8000/depart/1/edit/
        # http://127.0.0.1:8000/depart/16/edit/
        path('depart//edit/', views.depart_edit),
    
    ]
    
    8.8.2、views

    重定向:要引入 redirect

    from django.shortcuts import render, redirect
    from Employee import models
    
    
    def depart_list(request):
        if request.method == "GET":
            # 1.去数据库中获得所有的列表
            data_list = models.Department.objects.all()
            return render(request, 'depart_list.html', {'data_list': data_list})
        # 2.添加部门
        # 获取对象
        data_department = request.POST.get('department')
        # 添加对象
        models.Department.objects.create(title=data_department)
        # 重定向
        return redirect('/depart/list/')
    
    
    def depart_delete(request):
        """删除部门"""
        # 获取id
        # http://127.0.0.1:8000/depart/delete/?nid=1
        nid = request.GET.get('nid')
        # 删除id
        models.Department.objects.filter(id=nid).delete()
        # 重定向返回部门列表
        return redirect('/depart/list/')
    
    
    def depart_edit(request, nid):
        """编辑部门"""
        if request.method == "GET":
            row_data = models.Department.objects.filter(id=nid).first()
            return render(request, 'depart_edit.html', {'row_data': row_data})
        # 获取表单内容
        title = request.POST.get('department')
        # 根据id更新
        models.Department.objects.filter(id=nid).update(title=title)
        return redirect('/depart/list/')
    
    9、html继承
    • 可以有多个block

    母版:

    {% load static %}
    
    
    
        
        Title
        
    	{% block css %}{% endblock %}
    
    
    
    {% block content %}{% endblock %}
    {% block js %}{% endblock %}

    继承母版:

    {% extends 'layout.html' %}
    
    {% block css %}
    {% endblock %}
    
    
    
    {% block content %}
    {% endblock %}
    
    
    
    
    
    {% block js %}
    {% endblock %}
    
    10、用户管理

    Django中对于一些选项的元组存元组形式获取元组中的值:对象.get_属性_display()

    例:

    sex_choice = (
        (0, '男'),
        (1, '女')
    )
    sex = models.SmallIntegerField(verbose_name='性别', choices=sex_choice)
    

    取法:

    obj.get_sex_display()
    

    html中

    外键获取另一个表的值

    {% for obj in user_lists %}
        
            {{ obj.id }}
            {{ obj.name }}
            {{ obj.password }}
            {{ obj.get_sex_display }}
            {{ obj.age }}
            {{ obj.depart.title }}  # 外键获取另一个表的值
            {{ obj.account }}
            {{ obj.create_time }}
        
    {% endfor %}
    
    10.2、用户列表

    时间输出格式

    {% for obj in user_lists %}
        
            {{ obj.id }}
            {{ obj.name }}
            {{ obj.password }}
            {{ obj.get_sex_display }}
            {{ obj.age }}
            {{ obj.depart.title }}
            {{ obj.account }}
            {{ obj.create_time|date:"Y-m-d" }}  # 时间输出格式
            
                {# 编辑#}
                
                    
                
    
                {# 删除#}
                
                    
                
            
        
    {% endfor %}
    
    10.3、添加用户
    • 原始方式思路:不会采用(本质)【麻烦】
    - 用户提交数据没有校验
    - 错误,页面应该有提示
    - 页面上每一个字段都需要重新写
    - 关联的数据,手动去获取并展示在页面
    
    
    • Django组件
      • Form组件(小简便)
      • ModelForm组件(最简便)
    10.3.1、初识Form 1、views.py
    class MyForm(Form):
        user = forms.CharFiled(widget=forms.Input)
        pwd = forms.CharFiled(widget=forms.Input)
        email = forms.CharFiled(widget=forms.Input)
        
        
    
    def user_list(request):
        if request.method == "GET":
            form = MyForm()  # 实例化
            return render(request, 'user_list.html', {'form': form})
    
    2、user_add.html
    {{form.user}} # 自动生成html input标签 {{form.pwd}} {{form.email}} #

    或:

    {% for field in form %} {{ field }} {% endfor %}
    10.3.2、ModelForm(最简便) 1、models.py
    class Userinfo(models.Model):
        """员工表"""
        name = models.CharField(verbose_name='姓名', max_length=32)
        password = models.CharField(verbose_name='密码', max_length=64)
        age = models.IntegerField(verbose_name='密码')
        sex_choice = (
            (0, '男'),
            (1, '女')
        )
        sex = models.SmallIntegerField(verbose_name='性别', choices=sex_choice)
        account = models.DecimalField(verbose_name='账户余额', max_digits=10, decimal_places=2, default=0)
        create_time = models.DateField(verbose_name='入职时间')
        # 2.1  级联删除
        depart = models.ForeignKey(to="Department", to_field="id", on_delete=models.CASCADE)
    
    2、views.py
    class MyForm(ModelForm):
        class Meta:
            model = UserInfo
            fields = ["name", "password", "age"]
        
        
    
    def user_list(request):
        if request.method == "GET":
            form = MyForm()  # 实例化
            return render(request, 'user_list.html', {'form': form})
    
    10.3.3、添加用户 1、views.py
    #  ###################################  ModelForm  实例 ###############
    from django import forms
    
    
    class UserModelForm(forms.ModelForm):
        # 添加其他的判断
        name = forms.CharField(min_length=2, max_length=12, label="用户名")
        
        class Meta:
            model = models.Userinfo
            fields = ["name", "password", "age", "sex", "account", "depart", "create_time"]  # 添加表中的字段
    
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)  # 继承
            # 循环找到所有,添加样式
            for name, field in self.fields.items():
                field.widget.attrs = {"class": "form-control", "placeholder": field.label}
    
    
    def user_add(request):
        """添加用户 ModelForm版本"""
        if request.method == "GET":
            form = UserModelForm()  # 实例化一个对象
            return render(request, 'user_modelform.html', {"form": form})
        # 用户 post 提交数据,数据校验
        form = UserModelForm(data=request.POST)
        if form.is_valid():  # 判断数据是否合法
            # 如果数据合法,提交数据
            form.save()  # 自动保存,定义哪个,保存哪个
            return redirect('/user/list/')
        # 校验失败(在页面上提示信息)
        return render(request, 'user_modelform.html', {"form": form})
    
    2、html
    {% csrf_token %} {% for field in form %}
    {{ field }} {{ field.errors.0 }}
    {% endfor %} {# 提交 #}
    10.4、编辑用户
    • 点击编辑,跳转到编辑页面(将编辑的id携带过去)

    • 编辑页面(默认数据,根据id获取并设置到页面中)

    • 提交:

      • 错误提示
      • 数据校验
      • 再数据库更新
    def user_edit(request, nid):
        """编辑用户"""
        # 根据id获取要编辑的哪一行数据
        row_object = models.Userinfo.objects.get(id=nid)
        if request.method == 'GET':
            form = UserModelForm(instance=row_object)
            return render(request, 'user_edit.html', {'form': form})
        # 保存数据
        form = UserModelForm(data=request.POST, instance=row_object)
        if form.is_valid():
            form.save()
            return redirect('/user/list/')
        # 错误信息提示
        return render(request, 'user_edit.html', {'form': form})
    

    html和添加一样

    11、总结-1
    ModelForm  针对数据库中的某个表
    Form
    
    12、 靓号管理 搜索
    # 字典
    data_dict = {'id': 12}
    row_data = models.Mobile.objects.filter(**data_dict)
    
    # 数字
    models.Mobile.objects.filter(id=12)  # 等于12
    models.Mobile.objects.filter(id__gt=12)  # 大于12
    models.Mobile.objects.filter(id__gte=12)  # 大于等于12
    models.Mobile.objects.filter(id__lt=12)  # 小于12
    models.Mobile.objects.filter(id__lte=12)  # 小于等于12
    data_dict = {'id__lte': 12}
    row_data = models.Mobile.objects.filter(**data_dict)
    # 字符串
    models.Mobile.objects.filter(mobile__startwith='12')  # 以 12 开头
    models.Mobile.objects.filter(mobile__endwith='12')  # 以 12 结尾
    models.Mobile.objects.filter(mobile__contains='12')  # 包含 12
    models.Mobile.objects.filter(mobile='12')  # 等于 12
    
    分页
    # 分页查询:根据用户想要访问的页码,计算出起始位置
    page = int(request.GET.get('page', 1))
    page_size = 8  # 每页想显示多少条数据
    start = (page - 1) * page_size
    end = page * page_size
    
    # 总数据
    data_count = models.Mobile.objects.filter(**data_dict).count()  # 获得一共有多少条数据
    total_page_count, div = divmod(data_count, page_size)  # 求总页码数
    if div:
        total_page_count += 1  # 总页码
    
    # 计算出,显示当前页的前几个,后几个
    plus = 2
    if total_page_count <= 2 * plus + 1:
        # 数据库中的数据比较少
        start_page = 1
        end_page = total_page_count
    else:
        # 数据库中的数据比较多 > 5页
        if page <= plus:  # 当前页 < 2 时(极小值)
            start_page = 1
            end_page = 2 * plus + 1
        else:  # 当前页大于 2
            if (page + plus) > total_page_count:  # 判断最后的极大值
                start_page = total_page_count - 2 * plus
                end_page = total_page_count
            else:  # 中间情况
                start_page = page - plus
                end_page = page + plus
    
    # 页码
    page_str_list = []  # 储存html页码数 "
  • 1
  • " # 上一页 if page > 1: prev = '
  • 'aria-label="Previous">«
  • '.format(page-1) else: prev = '
  • 'aria-label="Previous">«
  • '.format(page) page_str_list.append(prev) for i in range(start_page, end_page+1): if i == page: ele = '
  • {}
  • '.format(i, i) else: ele = '
  • {}
  • '.format(i, i) page_str_list.append(ele) """
  • 1
  • 2
  • 3
  • 4
  • 5
  • """ # 下一页 if page < total_page_count: next_page = '
  • ' '»
  • '.format(page+1) else: next_page = '
  • ' '»
  • '.format(total_page_count) page_str_list.append(next_page) page_string = mark_safe("".join(page_str_list)) # 转义为html # data_dict为空时,全部查询 # 以level 排序,data_list存储获取的值 data_list = models.Mobile.objects.filter(**data_dict).order_by('level')[start:end]
    13、管理员操作

    admin.py

    from django.shortcuts import render, redirect
    
    from Employee import models
    from Employee.utils.form import AdminModel, AdminEditModel
    from Employee.utils.pagination import Pagination
    
    
    def admin_list(request):
        """管理员列表"""
        # 搜索
        data_dict = {}
        search_data = request.GET.get('q', "")
        if search_data:
            data_dict["username__contains"] = search_data
        data_list = models.Admin.objects.filter(**data_dict)
        queryset_object = Pagination(request, data_list)
    
        dic_context = {
            "data_list": queryset_object.page_queryset,  # 数据
            "page_string": queryset_object.html(),  # 页码
            "search_data": search_data,  # 搜索得数据
        }
    
        if search_data and not queryset_object.page_queryset:  # 搜索了,但没有符合的
            dic_context.update({'error': '对不起,号码不存在'})
            return render(request, 'mobile_list.html', dic_context)
        return render(request, 'admin_list.html', dic_context)
    
    
    def admin_add(request):
        """添加管理员"""
        title = '新建管理员'
        if request.method == 'GET':
            form = AdminModel()
            dic_context = {
                'form': form,
                'title': title,
            }
            return render(request, 'add.html', dic_context)
        form = AdminModel(data=request.POST)
        if form.is_valid():
            # form.cleaned_data  获得所有输入的值
            form.save()
            return redirect('/admin/list/')
        dic_context = {
            'form': form,
            'title': title,
        }
        return render(request, 'add.html', dic_context)
    
    
    def admin_edit(request, nid):
        """编辑管理员"""
        # 对象/None
        row_data = models.Admin.objects.filter(id=nid).first()
        if not row_data:  # 判断数据是否存在
            # return render(request, 'error.html', {'error': '数据不存在'})
            return redirect('/admin/list/')
    
        title = '修改密码'  # 标题名
        if request.method == "GET":  # get请求显示页面
            form = AdminEditModel(instance=row_data, pwd=row_data.password)
            username = row_data.username
            return render(request, "add.html", {'form': form, 'title': title, 'username': username, 'user_name': '用户名:'})
        form = AdminEditModel(instance=row_data, data=request.POST, pwd=row_data.password)
        if form.is_valid():  # 判断输入是否合理
            form.save()
            return redirect('/admin/list/')
        return render(request, "add.html", {'form': form, 'title': title})
    
    
    def admin_delete(request):
        nid = request.GET.get('nid')
        models.Admin.objects.filter(id=nid).delete()
        return redirect('/admin/list/')
    

    form.py

    class AdminModel(BootStrapModelForm):
        confirm_password = forms.CharField(
            label="确认密码",
            # widget=forms.PasswordInput(render_value=True),  # (render_value=True)  密码不同时,不会置空,默认是False置空
            widget=forms.PasswordInput
        )
    
        class Meta:
            model = models.Admin
            fields = ["username", "password", "confirm_password"]
            widgets = {
                # (render_value=True)  密码不同时,不会置空,默认是False置空
                # 'password': forms.PasswordInput(render_value=True)
                'password': forms.PasswordInput
            }
    
        def clean_password(self):
            password = self.cleaned_data.get('password')  # 获得输入的password
            return md5(password)  # 返回md5加密后的值
    
        def clean_confirm_password(self):
            password = self.cleaned_data.get('password')  # 获得的password是 上面 返回的值
            confirm_password = self.cleaned_data.get('confirm_password')
            if password != md5(confirm_password):
                raise ValidationError('密码不一致,请重新输入!')
            return confirm_password  # return 什么,保存到数据库的值就是什么
    
    
    class AdminEditModel(AdminModel):
        # class AdminEditModel(BootStrapModelForm):
        edit_password = forms.CharField(label='新密码', widget=forms.PasswordInput)
    
        class Meta:
            model = models.Admin
            fields = ["password", 'edit_password', "confirm_password"]  # 添加谁出现谁
            widgets = {
                'password': forms.PasswordInput
            }
    
        def clean_password(self):
            password = self.cleaned_data.get('password')  # 获得输入的password
            if self.pwd != md5(password):
                raise ValidationError('密码输入错误')
            return md5(password)  # 返回md5加密后的值
    
        def clean_edit_password(self):
            edit_password = self.cleaned_data.get('edit_password')  # 获得输入的password
            return md5(edit_password)
    
        def clean_confirm_password(self):
            edit_password = self.cleaned_data.get('edit_password')  # 获得的password是 上面 返回的值
            confirm_password = self.cleaned_data.get('confirm_password')
            if edit_password != md5(confirm_password):
                raise ValidationError('密码不一致,请重新输入!')
            return confirm_password  # return 什么,保存到数据库的值就是什么
    
        def __init__(self, pwd, *args, **kwargs):
            super().__init__(*args, **kwargs)  # 继承
            # 循环ModelForm中的所有字段,给每个字段的插件设置
            for name, field in self.fields.items():
                # 字段中有属性,保留原来的属性,没有属性,才增加
                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}
                self.pwd = pwd
    
    14、用户登录

    什么是cookie和session?

    http、https

    session存储在数据库或Redis或文件

    14.1、session登录

    在其他需要登录才能访问的页面中,都需要加入:

    def index(request):
        # 检查用户是否已经登录,已登录继续往下走,没有跳转到登录界面
        # 获取请求用户的随机字符串,看看session中有没有
        # request.session['info']
        info = request.session.get('info')
        if not info:
            return redirect('/login/')
        ......
    

    目标:在所有视图前面加上 上面判断

    14.2、Django的中间件

    中间件存方在 django_session 数据库中

    • 定义中间件

    from django.utils.deprecation import MiddlewareMixin
    
    
    class M1(MiddlewareMixin):
        """中间件1"""
    
        def process_request(self, request):
            # 如果方法中没有返回值(None),意味着可以继续往下走
            # 如果有返回值 HttpResponse   render  redirect
            print('m1, 进来了')
    
        def process_response(self, request, response):
            print('m1.走了')
            return response
    
    
    class M2(MiddlewareMixin):
        """中间件2"""
    
        def process_request(self, request):
            print('m2, 进来了')
    
        def process_response(self, request, response):
            print('m2.走了')
            return response
    
    • 注册中间件

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I6nggq39-1654077355213)(https://gitee.com/cool-dada/blog_img/raw/master/tree/master/img_markdown/202206011747008.png)]

    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',
        'Employee.middleware.auth.M1',
        'Employee.middleware.auth.M2',
    
    ]
    
    • 在中间件中的process_request()方法
    # 如果方法中没有返回值(None),意味着可以继续往下走
    # 如果有返回值 HttpResponse   render  redirect
    
    14.3、编写登录中间件
    from django.shortcuts import redirect
    from django.utils.deprecation import MiddlewareMixin
    
    
    class AuthMiddlewareMixin(MiddlewareMixin):
        """登录"""
    
        def process_request(self, request):
            # 排除不需要登录,就能访问的页面
            # request.path_info  获取用户请求的url  /login/
            if request.path_info == '/login/':
                return
    
            # 1,读取当前访问的用户的session信息,如果能读到,说明已经登录过,就可以继续向后走
            info_dict = request.session.get('info')
            if info_dict:  # 正确继续往后走
                return  # 返回空就是可以继续往后走
            # 2,如果没有登录,回到登录页面
            return redirect('/login/')
    
    14.4、注销
    def logout(request):
        """注销"""
        request.session.clear()  # 清除当前的session
        return redirect('/login/')
    
    14.5、模板登录信息

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-imF7gHiL-1654077355213)(https://gitee.com/cool-dada/blog_img/raw/master/tree/master/img_markdown/202206011747603.png)]

    14.5、图片验证码 5.1、生成图片
    pip install pillow
    
    
    5.2、函数
    from PIL import Image, ImageDraw, ImageFont, ImageFilter
    
    import random
    
    
    def check_code(width=100, height=32, char_length=5, font_file=r'Employee/static/plugins/font-text/Monaco.ttf', font_size=28):
        code = []
        img = Image.new(mode='RGB', size=(width, height), color=(255, 255, 255))
        draw = ImageDraw.Draw(img, mode='RGB')
    
        def rndChar():
            """
            生成随机字母
            :return:
            """
            return chr(random.randint(65, 90))
    
        def rndColor():
            """
            生成随机颜色
            :return:
            """
            return random.randint(0, 255), random.randint(10, 255), random.randint(64, 255)
    
        # 写文字
        font = ImageFont.truetype(font_file, font_size)
        for i in range(char_length):
            char = rndChar()
            code.append(char)
            h = random.randint(0, 4)
            draw.text([i * width / char_length, h], char, font=font, fill=rndColor())
    
        # 写干扰点
        for i in range(30):
            draw.point([random.randint(0, width), random.randint(0, height)], fill=rndColor())
    
        # 写干扰圆圈
        for i in range(30):
            draw.point([random.randint(0, width), random.randint(0, height)], fill=rndColor())
            x = random.randint(0, width)
            y = random.randint(0, height)
            draw.arc((x, y, x + 4, y + 4), 0, 90, fill=rndColor())
    
        # 画干扰线
        for i in range(3):
            x1 = random.randint(0, width)
            y1 = random.randint(0, height)
            x2 = random.randint(0, width)
            y2 = random.randint(0, height)
    
            draw.line((x1, y1, x2, y2), fill=rndColor())
    
        img = img.filter(ImageFilter.EDGE_ENHANCE_MORE)
        return img, ''.join(code)  # 返回图片和验证码
    
    
    # if __name__ == '__main__':
    #     img, strs = check_code()
    #     with open('code.png', 'wb') as f:
    #         img.save(f, format='png')
    #     print(strs)
    #     # 1. 直接打开
    #     # img,code = check_code()
    #     # img.show()
    #     #
    #     # 2. 写入文件
    #     # img,code = check_code()
    #     # with open('code.png','wb') as f:
    #     #     img.save(f,format='png')
    #     #
    #     # 3. 写入内存(Python3)
    #     # from io import BytesIO
    #     # stream = BytesIO()
    #     # img.save(stream, 'png')
    #     # stream.getvalue()
    #     #
    #     # 4. 写入内存(Python2)
    #     # import StringIO
    #     # stream = StringIO.StringIO()
    #     # img.save(stream, 'png')
    #     # stream.getvalue()
    
    5.3、urls路径
    path('image/code/', account.image_code),
    
    5.4、视图

    BytesIO介绍:https://blog.csdn.net/Victor2code/article/details/105637945

    def image_code(request):
        """生成图片验证码"""
        # 调用pillow函数,生成图片
        img, code_str = check_code()
    
        # 写入到自己的session中(以便后获取验证码再进行校验)
        request.session['code_str'] = code_str
    
        # 给session设置60秒超时,后续成功登录后需要重新设置
        request.session.set_expiry(60)
    
        # 导入io模块将图片传给前段
        from io import BytesIO
    
        stream = BytesIO()
        img.save(stream, 'png')
        return HttpResponse(stream.getvalue())
    
    5.5、前端
    {#  验证码 #}
    

    {{ form.code }} {{ form.code.errors.0 }}
    14.6、完整的登录 6.1 urls
    # 登录
    path('login/', account.login),
    path('logout/', account.logout),
    # 图片验证码
    path('image/code/', account.image_code),
    
    6.2 视图
    from django.shortcuts import render, redirect, HttpResponse
    from django import forms
    
    from Employee import models
    from Employee.utils.createImg import check_code
    from Employee.utils.encrypt import md5
    
    
    class LoginForm(forms.Form):
        username = forms.CharField(label='用户名',
                                   widget=forms.TextInput,
                                   required=True,  # 不为空, 默认的
                                   )
        password = forms.CharField(label='密码', widget=forms.PasswordInput, required=True)
    
        code = forms.CharField(label='验证码', widget=forms.TextInput, required=True)
    
        def clean_password(self):
            password = self.cleaned_data.get('password')
            return md5(password)  # 返回加密后的值
    
    
    def login(request):
        """登录"""
        if request.method == 'GET':
            form = LoginForm()
            return render(request, 'login.html', {'form': form})
        form = LoginForm(data=request.POST)
        if form.is_valid():
            # 验证成功,获取到的用户名和密码
            # print(form.cleaned_data)  返回的是字典
    
            # 验证码校验
            user_input_code = form.cleaned_data.pop('code')  # 获取用户输入的code,并且删去;以防占用内存
            auth_image_code = request.session.get('code_str', '')  # 获取真正的图片验证码
            if auth_image_code.upper() != user_input_code.upper():  # 验证码不正确,返回错误数据
                form.add_error('code', '验证码错误')
                return render(request, 'login.html', {'form': form})
    
            # 去数据库校验
            # models.Admin.objects.filter(username=xxx, password=xxx).first()
            admin_object = models.Admin.objects.filter(**form.cleaned_data).first()  # 传入一个字典
            if not admin_object:
                form.add_error('password', '用户名或密码错误')
                return render(request, 'login.html', {'form': form})
    
            # 登录成功
            # session 存储用户名
            request.session['info'] = {'id': admin_object.id, 'username': admin_object.username}
            request.session.set_expiry(60 * 60 * 24 * 7)  # 重新设置登录超时7天;因为在获取验证码时设置了过期时间,所有需要重新设置
            return redirect('/admin/list/')
    
        return render(request, 'login.html', {'form': form})
    
    
    def logout(request):
        """注销"""
        request.session.clear()  # 清除当前的session
        return redirect('/login/')
    
    
    def image_code(request):
        """生成图片验证码"""
        # 调用pillow函数,生成图片
        img, code_str = check_code()
    
        # 写入到自己的session中(以便后获取验证码再进行校验)
        request.session['code_str'] = code_str
    
        # 给session设置60秒超时,后续成功登录后需要重新设置
        request.session.set_expiry(60)
    
        # 导入io模块将图片传给前段
        from io import BytesIO
    
        stream = BytesIO()
        img.save(stream, 'png')
        return HttpResponse(stream.getvalue())
    
    6.3、页面
    {% load static%}
    
    
    
    
        
        login
        
        
        
    
    
    
        
    {% csrf_token %}

    用户登录

    {{ form.username }} {{ form.username.errors.0 }}
    {{ form.password }} {{ form.password.errors.0 }} {# 验证码 #}

    {{ form.code }} {{ form.code.errors.0 }}




    15、Ajax

    浏览器向网站发送请求时:URL和表单的形式提交

    • GET
    • POST

    特点:页面刷新

    除此之外,基础Ajax向后台请求

    • 依赖jQuery
    • 编写jQuery代码
    $.ajax({
        url:"发送得地址",
        type:"get",
        data:{
            n1:123,
            n2:456
        },
        success:function(res){
            console.log(res);
        }
    })
    
    15.1、get请求
    {% extends 'layout.html' %}
    
    {% block content %}
        

    任务管理

    实例1 {% endblock %} {% block js %} {% endblock %}
    from django.http import HttpResponse
    from django.shortcuts import render
    
    
    def task_list(request):
        """任务列表"""
        return render(request, 'task_list.html')
    
    
    def task_ajax(request):
        print(request.GET)
        return HttpResponse('成功')
    
    # 任务管理
    path('task/list/', task.task_list),
    path('task/ajax/', task.task_ajax),
    
    15.2、post请求
    from django.http import HttpResponse
    from django.shortcuts import render
    from django.views.decorators.csrf import csrf_exempt
    
    
    def task_list(request):
        """任务列表"""
        return render(request, 'task_list.html')
    
    
    @csrf_exempt  # 免除post请求,就在可以获取Ajax post发送的内容
    def task_ajax(request):
        print(request.GET)
        print(request.POST)
        return HttpResponse('成功')
    
    15.3、关闭绑定事件
    {% extends 'layout.html' %}
    
    
    {% block content %}
        

    任务管理

    实例1 {% endblock %} {% block js %} {% endblock %}
    15.4、Ajax请求的返回值

    一般都会返回json格式

    前端:

    {% extends 'layout.html' %}
    
    
    {% block content %}
        

    任务管理

    实例1 实例2 实例3
    {% endblock %} {% block js %} {% endblock %}

    后端:

    from django.http import HttpResponse, JsonResponse
    from django.shortcuts import render
    from django.views.decorators.csrf import csrf_exempt
    
    
    def task_list(request):
        """任务列表"""
        return render(request, 'task_list.html')
    
    
    @csrf_exempt  # 免除post请求,就在可以获取Ajax post发送的内容
    def task_ajax(request):
        print(request.GET)
        print(request.POST)
        data_dict = {'status': True, 'name': '李锦彪'}
        return JsonResponse(data_dict)
    
    16、订单 html
    {% extends 'layout.html' %}
    {% block content %}
    
        

    {# 删除对话框 #}
    订单列表
    {% for obj in queryset %} {% endfor %}
    ID 订单号 商品名 价格 状态 用户 操作
    {{ obj.id }} {{ obj.oid }} {{ obj.title }} {{ obj.price }} {{ obj.get_status_display }} {{ obj.admin }} {# 编辑#} {# 删除 #}
      {{ page_string }}
    {% endblock %} {% block js %} {% endblock %}
    视图
    import random
    from datetime import datetime
    from django.http import JsonResponse
    from django.shortcuts import render, redirect
    from django.views.decorators.csrf import csrf_exempt
    
    from Employee import models
    from Employee.utils.form import OrderModelForm
    
    # 订单号生成
    from Employee.utils.pagination import Pagination
    
    random_oid = datetime.now().strftime('%Y%m%d%H%M%S') + str(random.randint(1000, 9999))
    
    
    def order_list(request):
        form = OrderModelForm()
        # 1、根据自己的情况去筛选自己的数据
        queryset = models.Order.objects.all()  # 获得所有数据
        # 2,、实例化分页对象
        page_object = Pagination(request, queryset)
        dic_context = {
            'queryset': page_object.page_queryset,  # 分完页的数据
            'page_string': page_object.html(),  # 生成页码
            'form': form,
        }
        return render(request, 'order_list.html', dic_context)
    
    
    @csrf_exempt
    def order_add(request):
        """新建订单(Ajax)"""
        form = OrderModelForm(request.POST)
        if form.is_valid():
            # 创建自定义订单号
            form.instance.oid = random_oid
    
            # 创建管理员(登录的是谁就是谁)
            form.instance.admin_id = request.session['info']['id']
    
            # 保存到数据库中
            form.save()
            context = {
                'status': True
            }
            return JsonResponse(context)
        # 返回错误信息
        return JsonResponse({'status': False, 'error': form.errors})
    
    
    def order_delete(request):
        """删除订单"""
        uid = request.GET.get('uid')
        if models.Order.objects.filter(id=uid).exists():  # 判断是否存在
            models.Order.objects.filter(id=uid).delete()
            return JsonResponse({'status': True})
        return JsonResponse({'status': False, 'error': '删除错误,数据不存在'})
    
    
    @csrf_exempt
    def order_edit(request):
        if request.method == 'GET':
            """根据id获取订单信息  get 请求"""
            eid = request.GET.get('eid')
            # row_object = models.Order.objects.filter(id=eid).filter()  # 对象
            if models.Order.objects.filter(id=eid).filter():
                # 获取到的是字典
                row_dict = models.Order.objects.filter(id=eid).values('title', 'price', 'status').first()
                return JsonResponse({'status': True, 'data': row_dict})
    
            return JsonResponse({'status': False, 'error': '数据不存在'})
        """编辑订单  POST请求"""
        eid = request.GET.get('eid')
        row_object = models.Order.objects.filter(id=eid).first()
        if not models.Order.objects.filter(id=eid).filter():
            return JsonResponse({'status': False, 'tips': '数据不存在,请刷新重试'})
        form = OrderModelForm(data=request.POST, instance=row_object)
        if form.is_valid():
            form.save()
            return JsonResponse({'status': True})
        # 返回错误信息
        return JsonResponse({'status': False, 'error': form.errors})
    
    17、文件上传 17.1、基本操作
    {#  enctype="multipart/form-data"   支持上传文件  #}
    
    {% csrf_token %}
    from django.shortcuts import render, HttpResponse
    
    
    def upload_list(request):
        if request.method == 'GET':
            return render(request, 'upload_list.html')
        # # 'username': ['15751083927']
        # print(request.POST)  # 请求体中的数据
        # # {'avater': []}
        # print(request.FILES)  # 发过来的文件  {}
        file_object = request.FILES.get('avater')
        print(file_object.name)  # 文件名
    
        f = open('a1.png', 'wb')
        for chunk in file_object.chunks():
            f.write(chunk)  # 读一点写入一点
        f.close()
        return HttpResponse('...')
    
    17.2、Excel批量上传
    def depart_multi(request):
        """批量添加"""
        from django.core.files.uploadedfile import InMemoryUploadedFile
        from openpyxl import load_workbook
        # 获取用户上传的文件对象
        file_object = request.FILES.get('exc')
    
        # 对象传递给openpyxl
        wb = load_workbook(file_object)   # 或者是文件路径
        sheet = wb.worksheets[0]
    
        # 循环获取每一行数据
        for row in sheet.iter_rows(min_row=2):
            text = row[0].value
            # 添加到数据库
            if not models.Department.objects.filter(title=text).exists():
                models.Department.objects.create(title=text)
        return redirect('/depart/list/')
    
    {% csrf_token %}
    17.3、混合数据(form)

    提交页面时:用户输入的数据+文件(输入不能为空、报错)。

    • form生成的html标签:type=file
    • 表单的验证
    • form.clean_data 获取数据 + 文件对象
    {% extends 'layout.html' %}
    {% block content %}
        

    {{ title }}

    {% csrf_token %} {% for field in form %}
    {{ field }} {{ field.errors.0 }}
    {% endfor %}
    {% endblock %}

    后端:

    class UpForm(forms.Form):
        name = forms.CharField(label='姓名')
        age = forms.IntegerField(label='年龄')
        img = forms.FileField(label='头像')
    
    
    def upload_form(request):
        """获取混合数据"""
        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():
            # {'name': '李锦彪', 'age': 23, 'img': }
            # print(form.cleaned_data)
            # 获取到的内容要自己处理
            # 1.读取图片内容,写入到文件夹中并获取文件的路径
            img_object = form.cleaned_data.get('img')
    
            # file_path = 'Employee/static/img/{}'.format(img_object.name)  /格式不同,所以使用os
            db_file_path = os.path.join('static', 'img', img_object.name)  # 数据库存取地址 方便网页拼接url获取
            file_path = os.path.join('Employee', db_file_path)
            f = open(file_path, 'wb')
            for chunk in img_object.chunks():
                f.write(chunk)
            f.close()
    
            # 2.将图片文件路径写入到数据库
            models.Boss.objects.create(
                name=form.cleaned_data['name'],
                age=form.cleaned_data['age'],
                img=db_file_path
            )
    
            return redirect('/upload/form/')
        return render(request, 'upload_form.html', {'form': form, 'title': title})
    

    注意:就目前而言,所有的静态文件都只能放在static目录

    在Django的开发过程中两个特殊的文件夹

    • static。存放静态文件
    • media:用户上传的数据目录
    17.4、启用media,存数据

    存储用户传来的数据

    在urls.py中进行配置:

    from django.conf import settings
    from django.urls import path, re_path
    from django.views.static import serve  # 加载静态文件
    urlpatterns = [
        re_path(r'^media/(?P.*)$', serve, {'document_root': settings.MEDIA_ROOT}, name='media')
    
    ]
    

    在settings.py中进行配置:

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

    media目录所在位置:

    在浏览器中直接访问:

    后端存储

    def upload_form(request):
        """获取混合数据"""
        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():
            # {'name': '李锦彪', 'age': 23, 'img': }
            # print(form.cleaned_data)
            # 获取到的内容要自己处理
            # 1.读取图片内容,写入到文件夹中并获取文件的路径
            img_object = form.cleaned_data.get('img')
    
            media_path = os.path.join('media', img_object.name)  # media/xxxx
            
            f = open(media_path, 'wb')
            for chunk in img_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 redirect('/upload/form/')
        return render(request, 'upload_form.html', {'form': form, 'title': title})
    
    17.5、混合数据(ModelForm)

    models.py

    class City(models.Model):
        """"城市"""
        title = models.CharField(verbose_name='城市', max_length=32)
        count = models.IntegerField(verbose_name='人口')
        # 本质上数据库也是CharField, 但是自动保存数据   路径 :media/city/xxx
        img = models.FileField(verbose_name='logo', max_length=128, upload_to='city/')
    

    定义ModelForm:

    class CityModelForm(forms.ModelForm):
        class Meta:
            model = models.City
            fields = '__all__'
    

    视图

    def upload_modelform(request):
        """获取混合数据modelform"""
        title = 'ModelForm'
        if request.method == 'GET':
            form = CityModelForm()
            queryset = models.City.objects.all()
            return render(request, 'upload_modelform.html', {'form': form, 'title': title, 'queryset': queryset})
        form = CityModelForm(data=request.POST, files=request.FILES)
        if form.is_valid():
            # 对于文件:自动保存
            # 字段+上传路径写入到数据库
            form.save()
            return redirect('/upload/modelform/')
        return render(request, 'upload_modelform.html', {'form': form, 'title': title})
    

    前段

    包括显示内容

    {% extends 'layout.html' %}
    {% block content %}
        

    {{ title }}

    {% csrf_token %} {% for field in form %}
    {{ field }} {{ field.errors.0 }}
    {% endfor %}
    管理员列表
    {% for obj in queryset %} {% endfor %}
    ID 城市名 人口 logo
    {{ obj.id }} {{ obj.title }} {{ obj.count }}
    {% endblock %}
    Django 函数+知识点
    Django转义总结:escape、autoescape、safe、mark_safe
    	https://blog.csdn.net/bbwangj/article/details/79992863
    
    分页 --类
    """
    自定义分页组件, 以后想使用这个分页组件,做一下几步
    后端:
    def mobile_list(request):
        1、根据自己的情况去筛选自己的数据
        queryset = models.Mobile.objects.all()  # 获得所有数据
        2,、实例化分页对象
        page_object = Pagination(request, queryset)
        dic_context = {
            'data_list': page_object.page_queryset,  # 分完页的数据
            'page_string': page_object.html(),  # 生成页码
        }
        return render(request, 'mobile_list.html', dic_context)
    前段:
    
            
                
                靓号列表
            
            
                {% for obj in queryset %}
                    
                {% endfor %}
                
    ID 号码 价格 等级 状态 操作
    {{ obj.id }} {{ obj.mobile }} {{ obj.price }} {{ obj.get_level_display }} {{ obj.get_status_display }} {# 编辑#} { obj.id }}/edit/" > {# 删除#} { obj.id }}/delete/" >
      {{ page_string }}
    """ from django.utils.safestring import mark_safe import copy class Pagination(object): def __init__(self, request, queryset, page_size=8, page_param="page", plus=2): """ :param request: 请求的对象 :param queryset: 符合条件的数据 :param page_size: 每页的数量 :param page_param: 在URL中传递的获取分页的参数,例如:/mobile/list/?page=12 :param plus: 导航页码 """ page = request.GET.get(page_param, "1") # 获取前段传来的page,默认值为1 # 拿到url参数 query_dict = copy.deepcopy(request.GET) query_dict._mutable = True self.query_dict = query_dict # 拿到url参数 例如:page=q=1&page=1 if page.isdecimal(): # 判断是否是数字 page = int(page) else: page = 1 self.page = page # 获取哪一页 self.page_size = page_size # 页面展示的数据有几条 self.page_param = page_param # 页面 self.start = (page - 1) * page_size # 展示首页 self.end = page * page_size # 展示尾页 self.page_queryset = queryset[self.start:self.end] data_count = queryset.count() # 获得一共有多少条数据 total_page_count, div = divmod(data_count, self.page_size) # 求总页码数 if div: total_page_count += 1 # 总页码 self.total_page_count = total_page_count # 总页码 self.plus = plus # 只显示多少页 2*plus+1 def html(self): # 计算出,显示当前页的前几个,后几个 if self.total_page_count <= 2 * self.plus + 1: # 数据库中的数据比较少 start_page = 1 end_page = self.total_page_count else: # 数据库中的数据比较多 > 5页 if self.page <= self.plus: # 当前页 < 2 时(极小值) start_page = 1 end_page = 2 * self.plus + 1 else: # 当前页大于 2 if (self.page + self.plus) > self.total_page_count: # 判断最后的极大值 start_page = self.total_page_count - 2 * self.plus end_page = self.total_page_count else: # 中间情况 start_page = self.page - self.plus end_page = self.page + self.plus # 页码 page_str_list = [] # 储存html页码数 "
  • 1
  • " # 首页 self.query_dict.setlist(self.page_param, [1]) head_page = '
  • 首页
  • '.format(self.query_dict.urlencode()) page_str_list.append(head_page) # 上一页 if self.page > 1: self.query_dict.setlist(self.page_param, [self.page - 1]) prev = '
  • 'aria-label="Previous">«' '
  • '.format(self.query_dict.urlencode()) else: self.query_dict.setlist(self.page_param, [self.page]) prev = '
  • 'aria-label="Previous">«
  • ' ''.format(self.query_dict.urlencode()) page_str_list.append(prev) # 页面 for i in range(start_page, end_page + 1): self.query_dict.setlist(self.page_param, [i]) if i == self.page: ele = '
  • {}
  • '.format(self.query_dict.urlencode(), i) else: ele = '
  • {}
  • '.format(self.query_dict.urlencode(), i) page_str_list.append(ele) """
  • 1
  • 2
  • 3
  • """ # 下一页 if self.page < self.total_page_count: self.query_dict.setlist(self.page_param, [self.page + 1]) next_page = '
  • ' '»
  • '.format(self.query_dict.urlencode()) else: self.query_dict.setlist(self.page_param, [self.total_page_count]) next_page = '
  • ' '»
  • '.format(self.query_dict.urlencode()) page_str_list.append(next_page) # 尾页 self.query_dict.setlist(self.page_param, [self.total_page_count]) tail_page = '
  • 尾页
  • '.format(self.query_dict.urlencode()) page_str_list.append(tail_page) page_string = mark_safe("".join(page_str_list)) # 转义为html return page_string
    bootstrap样式-父类
    from django import forms
    
    
    class BootStrapModelForm(forms.ModelForm):
    
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)  # 继承
            # 循环ModelForm中的所有字段,给每个字段的插件设置
            for name, field in self.fields.items():
                # 字段中有属性,保留原来的属性,没有属性,才增加
                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}
    
    封装

    md5加密
    from django.conf import settings
    import hashlib
    
    
    def md5(data_string):  # md5加密
        obj = hashlib.md5(settings.SECRET_KEY.encode('utf-8'))
        obj.update(data_string.encode('utf-8'))
        return obj.hexdigest()
    
    数据库中获取数据

    对象/字典

    # 对象当前行的所有数据
    row_object = models.Order.objects.filter(id=eid).filter() 
    
    # 获取到的是字典
    row_dict = models.Order.objects.filter(id=eid).values('title', 'price', 'status').first()
    
    # queryset  = {obj,obj ..}
    queryset = models.Order.objects.all()
    
    # queryset = { {'xx': 'xx', 'xx': 'xxx'}, {'xx': 'xxx', 'xx': 'xxx'} }
    queryset = models.Order.objects.all().values('xx', 'xx')
    
    # queryset = {(1, 'xx'), (2, 'xx')....}
    queryset = models.Order.objects.all().values_list('id', 'title')
    
    柱状图
    {% extends 'layout.html' %}
    {% load static %}
    
    {% block content %}
        

    数据统计

    柱状图

    {% endblock %} {% block js %} {% endblock %}

    https://echarts.apache.org/zh/index.html

    总结
    • 创建Django项目
    • 修改__ init __.py
    import pymysql
    
    pymysql.install_as_MySQLdb()
    
    • settings.py中的DIR templates删除
    • 创建app和注册app
    python manage.py startapp xxx
    
    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'Employee.apps.EmployeeConfig',  # app注册
    
    ]
    
    • 配置静态文件路径 & 模板路径(放在app目录下)

    • 配置数据库相关操作

      • 第三方模块 mysqlclient
      • 自己先去数据库创建一个数据库
      • 配置数据库连接settings.py
      DATABASES = {
          'default': {
              'ENGINE': 'django.db.backends.mysql',
              'NAME': 'ljb',  # 数据库名字
              'USER': 'root',  # 账号
              'PASSWORD': '187365',  # 密码
              'HOST': '127.0.0.1',  # 主机
              'PORT': 3306,  # 端口号
          }
      }
      
      • 在app下的models.py中编写表
      from django.db import models
      
      
      class Department(models.Model):
          """部门表"""
          title = models.CharField(verbose_name='标题', max_length=32)
      
          def __str__(self):
              return self.title
      
      • 执行两个命令
      python manage.py makemigrations
      python manage.py migrate
      
    • 在urls.py,路由(url和函数的对应关系)

    • 在views,试图函数,编写业务逻辑

    • templates目录下编写html文件

    • ModelForm & Form组件,在我们开发增删改查功能

      • 生成html标签(生成默认值)
      • 请求数据进行校验
      • 保存到数据库(ModelForm)
      • 获取错误信息
    • Cookie和session用户信息保存起来

    • 中间件,基于中间件实现用户认证,基于:process_request

    • ORM操作

    models.User.objects.filter(id="")
    
    • 分页组件。

    {% endblock %}

    https://echarts.apache.org/zh/index.html
    
    
    
    
    
    
    
    
    
    
    
    ## 总结
    
    - 创建Django项目
    - 修改__ init __.py
    
    ```python
    import pymysql
    
    pymysql.install_as_MySQLdb()
    
    • settings.py中的DIR templates删除
    • 创建app和注册app
    python manage.py startapp xxx
    
    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'Employee.apps.EmployeeConfig',  # app注册
    
    ]
    
    • 配置静态文件路径 & 模板路径(放在app目录下)

    • 配置数据库相关操作

      • 第三方模块 mysqlclient
      • 自己先去数据库创建一个数据库
      • 配置数据库连接settings.py
      DATABASES = {
          'default': {
              'ENGINE': 'django.db.backends.mysql',
              'NAME': 'ljb',  # 数据库名字
              'USER': 'root',  # 账号
              'PASSWORD': '187365',  # 密码
              'HOST': '127.0.0.1',  # 主机
              'PORT': 3306,  # 端口号
          }
      }
      
      • 在app下的models.py中编写表
      from django.db import models
      
      
      class Department(models.Model):
          """部门表"""
          title = models.CharField(verbose_name='标题', max_length=32)
      
          def __str__(self):
              return self.title
      
      • 执行两个命令
      python manage.py makemigrations
      python manage.py migrate
      
    • 在urls.py,路由(url和函数的对应关系)

    • 在views,试图函数,编写业务逻辑

    • templates目录下编写html文件

    • ModelForm & Form组件,在我们开发增删改查功能

      • 生成html标签(生成默认值)
      • 请求数据进行校验
      • 保存到数据库(ModelForm)
      • 获取错误信息
    • Cookie和session用户信息保存起来

    • 中间件,基于中间件实现用户认证,基于:process_request

    • ORM操作

    models.User.objects.filter(id="")
    
    • 分页组件。
    转载请注明:文章转载自 www.mshxw.com
    本文地址:https://www.mshxw.com/it/948667.html
    我们一直用心在做
    关于我们 文章归档 网站地图 联系我们

    版权所有 (c)2021-2022 MSHXW.COM

    ICP备案号:晋ICP备2021003244-6号