• Django的初步学习及线上部署


    零、创建django项目

    img

    一、默认项目文件介绍

    创建app命令

     python manage.py startapp app001
    
    • 1

    django_project:

    • manage.py 【项目的管理、启动项目、创建APP、数据管理】【不动】

    • django_project

      • init.py
      • settings.py 【项目配置文件】 【常用】
      • urls.py 【url和函数的对应关系】【常用】
      • asgi.py 【异步接收网络请求】【别动】
      • wsgi.py 【同步接收网络请求】【别动】

      在settings.py中的TEMPLATES的DIRS置为空 删除外面的templates文件夹 这里面表示模板文件去哪里找 一般模板(template)写在app里面

    ·

    二、创建APP

     python manage.py startapp app001
    
    • 1
    • app001
      • migrations 【不动】【数据库字段变更】
        • init.py
      • init.py
        • admin.py 【不动】【django默认提供的后台管理】
      • apps.py 【不动】【app启动类】
      • models.py 【重要】【对数据库进行操作】
      • tests.pt 【不动】【单元测试】
      • views.py 【重要】【url对应函数】

    三、启动APP

    1.注册APP[settings.py]

      在settings.py中的INSTALLED_APPS注册刚启动的app 如'app001.apps.App001Config'
      其实是注册apps.py的 App001Config这个类
    
    • 1
    • 2

    img.png

    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'app001.apps.App001Config'
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    2.编写urls与视图函数对应关系[urls.py]

    img.png

    3.编写视图函数[views.py]

    img.png

    注意路由关系 点击某个按钮 触发a标签(一定是个路由 而不是.html的文件)->urls.py找到对应的视图函数->views.py找到对应的html->显示出来
    
    • 1

    4启动django

    命令行启动

    python manage.py runserver
    
    • 1

    停止django

    ctrl+c
    
    • 1

    四、tempalate模板

    模板中禁止函数的括号(for i in dict.keys)

    1.templates的作用

    tempalates用于html的显示 在views.py请求html时
    img.png
    静态文件处理 在APP下必须叫static

    2.static的作用 引用静态文件

    static(开发过程一般将js css 图片 作为静态文件)
    在.html中 使用下面的方法来指定路径

    {% load static %}
    
    
    • 1
    • 2
    样式连接
    https://v3.bootcss.com/css/
    
    • 1
    • 2

    需要导入的资源

    
    
    
    
    • 1
    • 2
    • 3
    {% load static %}
    
    
    
        
        Title
        
        
    
    
    
    
    
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    五、模板语法

    本质:在html中写一些占位符,有数据对这些占位符号进行替换和处理 给用户的可没有啥子if_else,是一个纯的html
    img.png
    在html的语法
    img.png

    • 若在models.py 有对应的choices 可在html使用 get_字段名_display 显示对应的注释
    get_level_display
    
    • 1

    六、请求与响应

    def something(request):
        # request是一个对象,封装了用户发送过来的所有请求相关数据
    
        # 1.获取用户/客户端请求方式 GET/POST
        print(request.method)
    
        # 2.在URL传递值/something/?n1=123&n2=999
        print(request.GET)
    
        # 3.在请求体中提交数据
        print(request.POST)
    
        # 4【响应】 HttpResponse("欢迎")  内容字符串返回给请求者
        # return  HttpResponse("欢迎")
    
        # 5【响应】读取HTMl中的内容+渲染 替换成字符串
        # return render(request, "user_list.html")
    
        # 6【响应】浏览器重定向
        # return  redirect("https://www.baidu.com")
        # 7 如何发起get请求
        """7.1浏览器地址栏中输入URL
        7.2 
        7.3 form表单的method为get"""
    
    重定向是让浏览器访问第三方网站 而不是我们访问了三方网站把HTMl给浏览器如下图第二种方式所示
    
    • 1

    img

    七、数据库操作

    7.1 安装第三方sql库 mysqlclient django底层对mysqlclient更友好相比pymysql

    pip install mysqlclient
    
    • 1
    • ORM可以帮我们做两件事
      • 创建、修改、删除数据库中的表(不用写sql)【无法创建数据库 自己手动创建】
      • 操作表中的数据(不用写SQL语句)

    7.2 将settings.py的名为DATABASES字典进行替换 这就是连接的数据库

    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'dbname',
            'USER': 'root',
            'PASSWORD': 'xxx',
            'HOST': '',
            'PORT': '',
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    7.3 django操作表 进入models.py(会自动创建自增id的列)

    • 创建表
    from django.db import models
    
    
    # Create your models here.
    
    class UserInfo(models.Model):
        name = models.CharField(max_length=255)
        password = models.CharField(max_length=255)
        age = models.IntegerField()
    
    
    """
    内部会执行
    CREATE TABLE `app001_userinfo` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT,
      `name` varchar(255) NOT NULL,
      `password` varchar(255) NOT NULL,
      `age` int(11) NOT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
    """
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    数据库default值字段不会生效 有些注释也不会生效但是实际插入过程中会生效的
    
    • 1
    • 修改表

      • 修改表名称:直接在对应表的类中修改类名称
      • 修改表字段
      • 新增字段 在对应类新增字段即可 需要有默认值
    • 删除表 直接注释相应类的代码就在执行相应命令就可以

    • 外键约束

    #1.有约束
    # -  to 与哪张表关联 如 to=Department 就是部门表形成关联
    #- to_field,表中的那一列关联 to_field="id" 就是与ID列形成关联
    #2.django自动(写的depart 数局库里实际是depart_id)
    # -写的depart
    # -并生成数据列depart_id
    # 3.部门表被删除并鞋祥
    # 3.1级联删除(外键表相应字段被删除后主表也会被删除)
    # depart = models.ForeignKey(to="Department",to_field="id",on_delete=models.CASCADE)#辑祥
    #3.2_置空 外键表被删除后主表会置空 
    # blank=True、null=True。统一的表明了该字段(列)是可以为空的
    depart = models.ForeignKey(to=Department",to_field="id",null=True,blank=True,on_delete=models.SET_NUL)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    创建、修改、删除表之后都必须在根目录执行命令如下(不执行不会生效)

    python manage.py makemigrations
    python manage.py migrate
    
    • 1
    • 2

    7.4 操作表中的数据

    # 增 insert into app001_department(name) values (张三")
    models.Department.objects.create(name="张三")
    
    # 删除某条数据
    models.Department.objects.filter(id=2).delete()
    # 删除所有数据
    models.Department.objects.all().delete()
    
    # 查询所有数据
    datalist[每行都是对象每个对象都封装了相应参数]
    QuerySet类型
    datalist = models.Department.objects.all()
    for i in datalist:
      # print(i) # 
      print(i.id, i.name)  # 10 张三
    
    # 查询某一条数据 查询id=10的数据
    data = models.Department.objects.filter(id=10).first()
    print(data.name)
    
    # 更新一张表所有数据
    models.Department.objects.all().update(name="李四")
    models.Department.objects.filter(id=10).update(name="王五")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    datalist 为 QuerySet类型 相当于一个列表里面存储了很多对象 [对象1,对象2...] 每个对象都是一行数据
    
    • 1

    7.5 原生sql查询

     sql = """SELECT a.id,a.name,a.`password`,a.age,a.account,a.gender,a.depart_id,b.title FROM app01_userinfo a
    LEFT JOIN app01_department b on b.id=a.depart_id"""
    data = models.UserInfo.objects.raw(sql)
    print(data)
    for item in data:
        # 查看空间里的值
        # print(item.__dict__)
        print(item.get_gender_display())
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    7.6 orm一些条件操作

    # 包含三 
    字段="三"  # 原生SQL条件:where 字段 ="三"
    字段__contains="三" # 原生SQL条件:where 字段 like "%三%"
    # 以三开头
    字段__startswith="三" # 原生SQL条件:where 字段 like "三%"
    # 以三结尾
    字段__startswith="三" # 原生SQL条件:where 字段 like "%三"
    # 为空
    字段__isnull=True # 原生SQL条件:where 字段 IS NULL
    # 不为空
    字段__isnull=False # 原生SQL条件:where 字段 IS NOT NULL
    # in
    字段__in=[1,2,3] # 原生SQL条件:where 字段 IN (1, 2, 3)
    # >
    字段__gt=1 # 原生SQL条件:where 字段 > 1
    # >=
    字段__gte=1 # 原生SQL条件:where 字段 >= 1
    # <
    字段__lt=1 # 原生SQL条件:where 字段 < 1
    # <=
    字段__lte=1 # 原生SQL条件:where 字段 <= 1
    # 日期字段,年
    日期字段__year=2020 # 原生SQL条件:where 日期字段 BETWEEN 2020-01-01 AND 2020-12-31
    # 日期字段,月
    日期字段__month=3 # 原生SQL条件:where EXTRACT(MONTH FROM 表名.日期字段) = 3
    # 日期字段,天
    日期字段__day=4 # 原生SQL条件:where EXTRACT(DAY FROM 表名.日期字段) = 4
    # 时间比大小,|为或的意思
    日期字段__gt|lt|...="2020-10-10" # 原生SQL条件:where 日期字段 > 2020-10-10
    # 比大小还可以是时间类型
    import datetime
    日期字段__gt|lt|...=datetime.date(2020,10,10)# 同上
    # 时间范围筛选
    日期字段__range=("2020-01-01","2020-06-01") # 原生SQL条件:where 时间字段 BETWEEN 2020-01-01 AND 2020-06-01
    日期字段__range=(datetime.date(2020,1,1),datetime.date(2020,6,1)) # 同上
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    八、模板继承

    • 这就是模板
    DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Titletitle>
    head>
    <body>
    <h1>标题h1>
    <div>
        <h3>这个" block content endblock 这之间自定义的内容"h3>
        {% block content %} {% endblock %}
        <h2>底部h2>
    div>
    body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 继承模板 语法如下 首页这两个字 会在 标题 和 底部之间
    {% extends 'layout.html'%}
    {% block content %}
    <h1>首页 在标题和底部之间h1>
    {% endblock %}
    
    • 1
    • 2
    • 3
    • 4

    九 、初识form

    9.1 form 跳过 不够简单

    9.2 modelform

    9.2.1 初步使用

    • 要在views写个类 然后再使用类对象 注意 class Meta一定得是Meta, model fields等名称都不能变 如果是多张表 则写多个class,多个form即可
      fields = "all"表示取所有字段
    from django import forms
    
    
    class UserModelForm(forms.ModelForm):
        """从数据表取字段"""
        # 告诉Django这个form类和那个model类对应
        model = models.UserInfo
        # 取哪些字段
        fields = ["name", "password", "age", "gender"]  # 都是UserInfo表里的字段
    
    
    def user_add(request):
        """添加用户基于modelform"""
        form = UserModelForm  # object赋给form
        return render(request, "user_add.html", {"form": form})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    form.name.label 指的是 models.py的中文注释 form.name 则指的是字段名称
    img

    DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Titletitle>
    head>
    <body>
    <form method="post">
    
        {% csrf_token %}
        {{ form.name.label }}:{{ form.name }}
        {{ form.password.label }}:{{ form.password}}
        {{ form.age.label }}:{{ form.age}}
    form>
    
    body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    9.2.2 定义样式

    • model form 也可以再代码里定义样式 如下面的widgets
    class UserModelForm(forms.ModelForm):
        """从数据表取字段"""
    
        class Meta:
            # 告诉Django这个form类和那个model类对应
            model = models.UserInfo
            # 取哪些字段 就会校验哪些字段
            fields = ["name", "password", "age", "gender"]  # 都是UserInfo表里的字段
    
            # 每个字段样式都写的格式
            widgets = {
                "name": forms.TextInput(attrs={"class": "form-control"})
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • fields 里可以确定使用哪些字段
    fields = ["name", "password", "age", "gender"]
    
    • 1
    • 使用所有字段 “all
     fields = "__all__"
    
    • 1
    • 不使用某些字段 exclude = [“admin”]
    exclude = ["admin"]
    fields = "__all__"
    
    • 1
    • 2
    • 使某些字段不可编辑 需要在modelform里重新定义一下名称和数据库中一致 使用参数disabled=True
    • 使用了此参数 POST提交时不会提交相应字段
    class BookStatusModelForm(forms.ModelForm):
        book_cover = forms.FileField(disabled=True, label="书籍封面")
        book_name = forms.CharField(disabled=True, label="书籍名称")
        book_author = forms.CharField(disabled=True, label="作者")
        admin = forms.CharField(disabled=True, label="借阅人")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • moder form 批量定义 注意缩进 重写了__init__
    class UserModelForm(forms.ModelForm):
        """从数据表取字段"""
    
        class Meta:
            # 告诉Django这个form类和那个model类对应
            model = models.UserInfo
            # 取哪些字段
            fields = ["name", "password", "age", "gender","create_time"]  # 都是UserInfo表里的字段
    
            # 每个字段样式都写的格式
            # widgets = {
            #     "name": forms.TextInput(attrs={"class": "form-control"})
            # }
        # 注意缩进
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            for name, field in self.fields.items():
                # print(name)
                # print(field)
                # 字段定义的是什么框就是什么框
                field.widget.attrs = {"class": "form-control", "placeholder": field.label}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    html中对应代码

    {% for field in form %}
    <div class="form-group">
        <label>{{ field.label }}label>
        {{ field }}
    div>
    {% endfor %}`
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    9.2.3校验字段是否合法

    代码层面 校验失败时 返回此页面而不是 重定向 返回可以保留之前的数据

    return render(request, "user_add.html", {"form": form,  "department_list": department_list})
    
    • 1

    关闭浏览器自己做的校验 在相应表单上填写 novalidate

     <form method="post" novalidate>
    
    • 1
    • 加上语句 field.errors.0 其中 .0是指第一个错误
    {% for field in form %}
    <div class="form-group">
        <label>{{ field.label }}label>
        {{ field }}
        <span style="color: red;">{{ field.errors.0 }}span>
    div>
    {% endfor %}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 提示是英文的 下面我们改成中文 进入settings.py 找到LANGUAGE_CODE = ‘en-us’ 注释掉 改成

    • LANGUAGE_CODE = ‘zh-hans’
      img

    • 若要添加特定的规则进行校验 需要在相应的model form下添加规则 name = forms.CharField(label=“员工名称”,min_length=2))

    class UserModelForm(forms.ModelForm):
        """从数据表取字段"""
        # 若要添加特定的字段 那么在这里重新定义下才可以
        name = forms.CharField(label="员工名称",min_length=2)
        class Meta:
            # 告诉Django这个form类和那个model类对应
            model = models.UserInfo
            # 取哪些字段
            fields = ["name", "password", "age", "gender", "account", "create_time"] 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    十 、model form的增删改查

    10.1 增

    model form 增加数据 接收提交过来的数据并且保存到数据库中 post请求时要写 UserModelForm(data=request.POST)
    如果文件上传 还需要写files = request.FIELS

    a = models.UserInfo.objects.filter(id=nid).first()
    form = UserModelForm(data=request.POST)
    form.save()
    
    • 1
    • 2
    • 3

    10.2 查 和model form 没有啥关系

    models.Department.objects.all()
    
    • 1

    10.3 改

    增加了一个参数 instance 这样才知道更改哪条数据 即先实例化 再赋给modelform 提交时需要添加参数data=request.POST

    a = models.UserInfo.objects.filter(id=nid).first()
    form = UserModelForm(data=request.POST,instance=a)  # 接收数据
    
    • 1
    • 2
    • 对于在UserModelForm中没有使用字段但是model中拥有的字段想要入库时可以采取此写法
    form.instance.depart_id = department_id.id
    form.save()
    
    • 1
    • 2

    10.4 删 和model form 没有啥关系

    def user_deldete(request):
        # 获取ID
        nid = request.GET.get("nid")
        # 删除
        models.UserInfo.objects.filter(id=nid).delete()
        return redirect("/user/list")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    10.5 查看数据库中是否存在此字段 exist() 存在 true 不存在 false

    is_exist = models.PrettyNumber.objects.filter(mobile=mobile_number).exists()
    
    • 1

    10.6 校验model form里的字段 在model form 里定义函数 clean_字段名 可以自动校验传过来的字段

        def clean_mobile(self):
            mobile_number = self.cleaned_data["mobile"]
            # 判断是否存在此账号,返回的是真假值
            # is_exist = models.PrettyNumber.objects.filter(mobile=mobile_number).exists()
            # print(is_exist)
            # 如果存在就是真
            if len(mobile_number) <= 11:
                # if is_exist:
                raise ValidationError("号码不足11位")
            return mobile_number
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    10.7 sql排除某些字段

    # self.instance.pk 实例的主键ID
    is_exist = models.PrettyNumber.objects.exclude(id=self.instance.pk).filter(mobile=mobile_number).exists()
    
    • 1
    • 2

    十一.搜索模糊查询

    11.1 需要添加个表单 get方式提交搜索的数据

    <div style="float: right;width: 300px;">
                        <form method="get">
                            <div class="input-group">
                                <input type="text" name="query" class="form-control" placeholder="请输入号码" value="{{value}}">
                                <span class="input-group-btn">
                        <button class="btn btn-default" type="submit">
                             <span class="glyphicon glyphicon-search" aria-hidden="true">span>
                        button>
                                span>
                            div>
                        form>
                    div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    11.2 django可以通过字典的方式为filter赋值 **解包成 id=1,moblie=2这种形式

    如果是空 data_dict[“mobile__contains”] = “” 则原生sql没有对应的where

    data_dict={}
    value = request.GET.get(key="query",default="")  # 获得 query 如果key为空 默认空字符串
        if value:
            data_dict["mobile__contains"] = value
    pretty_data = models.PrettyNumber.objects.filter(**data_dict).order_by("-level")
    
    • 1
    • 2
    • 3
    • 4
    • 5

    若有多个搜索框继续在后面加即可如下图的value1如果存在就加到字典中

    def pretty_list(request):
        data_dict = {}
        value = request.GET.get(key="query", default="")  # 获得 query 如果key为空 默认空字符串
        value1 = request.GET.get(key="level", default="")
        if value:
            data_dict["mobile__contains"] = value
        if value1:
            data_dict["level"] = value1
        # - 代表desc
        pretty_data = models.PrettyNumber.objects.filter(**data_dict).order_by("-level")
        return render(request=request, template_name="pretty_list.html",
                      context={"pretty_data": pretty_data, "value": value, "value1": value1})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在界面上回显输入的搜索值 给input框内 赋值给value即可

    <input type="text" name="query" class="form-control " placeholder="请输入号码" value="{{ value }}">
    
    • 1

    十二、登录

    10.1登录页面获得表单数据

    # 建立ModelForm类
    class AdminModelForm(forms.ModelForm):
        class Meta:
            model = models.Admin
            fields = ["username", "password"]
    
    
    def login(request):
        if request.method == "GET":
            return render(request=request, template_name="login.html")
        if request.method == "POST":
            form = UserModelForm(data=request.POST) # 接收表单数据
            username = form.cleaned_data["username"]
            password = form.cleaned_data["password"]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    两种方法都可以用了 注意若在视图函数里使用form.cleaned_data 需要在form.is_valid

            if form.is_valid():
                print(form.cleaned_data)  # print(form.cleaned_data)
                print(request.POST)  # 
                这两种方法都可以拿到对应的值
                title = request.POST.get("username")
                print(title)
                username = form.cleaned_data["username"]
                print(username)
                password = form.cleaned_data["password"]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 在数据库进行查找 如果验证不通过则返回账号名或密码错误 form.add_error(“password”, “用户名或密码错误!”)
    if is_login:  # 成功则返回首页
        return redirect("/admin/list")
    else:  # 失败返回此页面并给予错误信息
        form.add_error("password", "用户名或密码错误!")
        return render(request=request, template_name="login.html",
                      context={"form": form})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    10.2 鉴权 cookie和sessions

    • 因为http协议是短连接(网站是短连接的)的无状态的 为了让服务器知道是哪位用户在进行访问因此使用session来判断用户
      img
    • 加上 request.session[“user_info”] = {“id”: is_login.id, “name”: is_login.username}
    is_login = models.Admin.objects.filter(**data_list).first()
    if is_login:
        # userinfo是自定义的字典 后面是要写入的东西
        request.session["user_info"] = {"id": is_login.id, "name": is_login.username}  # 鉴权 写到用户浏览器中 再写入session中
        return redirect("/admin/list")  # 成功则返回首页
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 然后登录重新登录数据库的django_session表就会写入session_key(session_id) 和 session_data 这种({“id”: is_login.id, “name”: is_login.username})
      img
      浏览器会记录session_id 然后去django_session找 找到了就有对应的session_data了
      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1tgtkFOq-1663057086903)(img_1.png)]
      每次发起请求时都会根据session_id 查找数据库 然后获得session_data
    	SELECT `django_session`.`session_key`, `django_session`.`session_data`, `django_session`.`expire_date` FROM `django_session` WHERE (`django_session`.`expire_date` > '2022-08-26 03:03:44.360293' AND `django_session`.`session_key` = 'h5q5zeeliqnsa2udh6f1h3dl1ryoqi89') LIMIT 21
    
    • 1

    10.3 django 中间件

    • 释义:从发起请求到命中视图函数 一个请求会经过很多中间件(在django里面是一些类) 每个中间件都有 request 和 response如果哪个部分没有通过直接返回那个类的response 先进(指request)后出(指相应的response)
    • 因此在中间件进行鉴权最合适 每个接口都要进行鉴权
      img
    • 中间件的执行顺序 在settings.py的MIDDLEWARE里
    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',
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 中间件的实现 在app下的auth文件夹下 建一个 auth.py
    from django.utils.deprecation import MiddlewareMixin
    from django.shortcuts import render, HttpResponse, redirect
    
    class AuthMiddleware(MiddlewareMixin):
        def process_request(self, request):
            if request.path_info == "/login/": # 如果是login目录则继续往下走防止无限递归
                return # 相当于直接往后走
            user_info_dict = request.session.get("user_info")
            print(user_info_dict)
            if user_info_dict:
                return 
            return redirect("/login/")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 注册中间件 在settings.py的MIDDLEWARE里加到最后
    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',
        'app01.auth.auth.AuthMiddleware',
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 每次清除cookies进行登录都会生成新的session_id
    • login的视图函数里写进去的关于session的东西 中间件可以取出来用来判断是否登录
      这request.session[“user_info”] = {“id”: is_login.id, “name”: is_login.username}
    • user_info_dict = request.session.get(“user_info”)

    十三、注销

    13.1

    • 视图函数 request.session.clear() 这会改变数据库里的值 让传过来的session_id没有正常的session_data值
    def logout(request):
        # 删除cookies 由于是的通用页面 集成到layout上 原因是中间件通过不了
        request.session.clear()
        # 返回登录页面
        return redirect("/login")
    
    • 1
    • 2
    • 3
    • 4
    • 5

    layout.html中此处路由写成logout就可以了

    <li><a href="/logout/">退出</a></li>
    
    • 1
    • 可见是传了session_id的
      img
    • 数据库的session_data 变了 导致无法验证通过
      img

    13.2 右上角显示登录的账号

    在相应的地方如母版中layout.html写入session的内容 就可以显示了 之前在登录的时候写入了 就能拿到

    {{ request.session.user_info.name }}
    
    • 1

    十四、图片验证码

    14.1 安装pillow

    pip3 install pillow
    
    • 1
    • 图片验证码代码
    import random
    from PIL import Image, ImageFont, ImageDraw, ImageFilter
    
    
    def check_code(width=120, height=30, char_length=5, font_file="Monaco.ttf", font_size=28):
        """
        :param width: 图片验证码宽度
        :param height: 图片验证码高度
        :param char_length: 图片验证码上的字符个数
        :param font_file: 图片验证码上的字体形状
        :param font_size: 图片验证码伤的字体大小
        :return:
        """
        code = []
        img = Image.new(mode='RGB', size=(width, height), color=(255, 255, 255))  # 白色的背景图片
        draw = ImageDraw.Draw(img, mode='RGB')  # 要对这张图片进行画笔操作
    
        def rndChar():
            """
            生成大写随机字母的ascii码
            :return:
            """
            return chr(random.randint(65, 90))
    
        def rnd_number():
            return chr(random.randint(48, 57))
    
        def rndColor():
            """
            生成随机颜色
            :return:
            """
            return (random.randint(0, 255), random.randint(10, 255), random.randint(64, 255))
    
        # 写文字
        font = ImageFont.truetype(font=font_file, size=font_size)
        # 中英文间隔
        for i in range(char_length):
            if i % 2 == 0:
                char = rnd_number()
                code.append(char)
            else:
                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(40):
            draw.point([random.randint(0, width), random.randint(0, height)], fill=rndColor())
    
        # 写干扰圆圈
        for i in range(40):
            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(5):
            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__':
        # 1. 直接打开
        img, code = check_code()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76

    十五、上传图片

    15.1 启用media文件夹 在根目录下创建media文件夹(固定写法)

    • 用户上传的图片放在media文件夹下
    15.1.1 在settings.py 配置
    import os
    MEDIA_URL = '/media/'
    MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
    
    • 1
    • 2
    • 3
    15.1.2 在 urls.py 配置
    from django.urls import re_path
    from django.views.static import serve
    from django.conf import settings
    
    urlpatterns = [
        re_path(r'media/(?P.*)$', serve, {'document_root': settings.MEDIA_ROOT}),
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    15.1.3 在html的form 表单进行配置

    • novalidate是浏览器不进行验证 enctype=“multipart/form-data” 是为了读到二进制文件
    <form method="post" novalidate enctype="multipart/form-data">
    
    • 1

    15.2 查看media中的文件

    • http://127.0.0.1:8000/media 加上media加图片路径即可
    http://127.0.0.1:8000/media/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20220610174930.png
    
    • 1

    15.2 上传实现

    • 15.2.1 启用FileField 启用 upload_to 指定上传的文件夹
    class Book(models.Model):
        """书籍表"""
            book_cover = models.FileField(verbose_name="书籍封面",upload_to="media/") # 数据库本质上也是CharField,可以自动保存
    
    • 1
    • 2
    • 3
    • 三种上传方式
      img

    • 手动去写

    file_object = request.FILES.get ( "exc")
    - Form组件(表单验证)
    
    • 1
    • 2
    request.POST
    file_object = request.FILES.get ( "exc" )
    
    • 1
    • 2

    具体文件操作还是手动自己做。

    - ModelForm(表单验证+自动保存数据库+自动保存文件)
    - Media文件夹
    - Models.py定义类文件要
    img = models.FileField(verbose_name="Logo", max_length=128,upload_to='city l ' )
    
    • 1
    • 2
    • 3
    • 4

    十六、项目部署(腾讯云CentOS7.9 先开放3306端口)

    16.0 安装MySQL

    16.0.1 卸载MariaDB
    • 卸载MariaDB(在CentOS中默认安装有MariaDB,是MySQL的一个分支,主要由开源社区维护。
      CentOS 7及以上版本已经不再使用MySQL数据库,而是使用MariaDB数据库。
      如果直接安装MySQL,会和MariaDB的文件冲突。
      因此,需要先卸载自带的MariaDB,再安装MySQL。

    • 查看版本

      rpm -qa|grep mariadb

    • 卸载

      rpm -e --nodeps 文件名

    • 检查是否卸载干净

      rpm -qa|grep mariadb
      img

    16.0.1 安装MySQL8.0下载和解压
    cd   /home                            #切换到家目录
    wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.20-linux-glibc2.12-x86_64.tar.xz #直接从官网下载压缩包到当前目录
    cd /usr/local               #切换到local目录
    mkdir mysql8                 #创建一个名为mysql8的目录
    tar -Jxvf /home/pwmysql-8.0.20-linux-glibc2.12-x86_64.tar.xz -C /usr/local/mysql8/   #将压缩包解压到mysql8目录
    
    • 1
    • 2
    • 3
    • 4
    • 5
    16.0.2 配置环境变量
    vim /etc/profile #进入环境变量 
    export PATH=$PATH:/usr/local/mysql8/mysql-8.0.20-linux-glibc2.12-x86_64/bin #按“i”进入编辑模式,在文件末尾添加一下内容在最后
    source /etc/profile #保存后用source命令是配置立即生效
    mysql --version # 查看MySQL版本
    
    • 1
    • 2
    • 3
    • 4
    16.0.3 创建用户群组
    groupadd mysql # 创建一个用户组:mysql
    useradd -r -g mysql mysql # 创建一个系统用户:mysql,指定用户组为mysql
    
    • 1
    • 2
    16.0.4 创建数据目录
    mkdir -p /usr/local/mysql8/mysql-8.0.20-linux-glibc2.12-x86_64/datas # 创建datas目录与bin同级 
    chown -R mysql:mysql /usr/local/mysql8/mysql-8.0.20-linux-glibc2.12-x86_64/datas # 更改指定用户合组和数组
    chmod -R 750 /usr/local/mysql8/mysql-8.0.20-linux-glibc2.12-x86_64/datas # 更改模式
    
    • 1
    • 2
    • 3
    16.0.5 初始化MySQL
    • 创建my.cnf配置文件,用于初始化MySQL数据库

      touch /usr/local/mysql8/mysql-8.0.20-linux-glibc2.12-x86_64/my.cnf # 创建配置文件
      
      • 1
    • 写入下面数据 特别注意路径问题啊!!!很重要!!!

    [mysql]
    # 默认字符集
    default-character-set=utf8mb4
    [client]
    port       = 3306
    socket     = /tmp/mysql.sock
    
    [mysqld]
    port       = 3306
    server-id  = 3306
    user       = mysql
    socket     = /tmp/mysql.sock
    # 安装目录
    basedir    = /usr/local/mysql8/mysql-8.0.20-linux-glibc2.12-x86_64
    # 数据存放目录
    datadir    = /usr/local/mysql8/mysql-8.0.20-linux-glibc2.12-x86_64/datas/mysql
    log-bin    = /usr/local/mysql8/mysql-8.0.20-linux-glibc2.12-x86_64/datas/mysql/mysql-bin
    innodb_data_home_dir      =/usr/local/mysql8/mysql-8.0.20-linux-glibc2.12-x86_64/datas/mysql
    innodb_log_group_home_dir =/usr/local/mysql8/mysql-8.0.20-linux-glibc2.12-x86_64/datas/mysql
    #日志及进程数据的存放目录
    log-error =/usr/local/mysql8/mysql-8.0.20-linux-glibc2.12-x86_64/datas/mysql/mysql.log
    pid-file  =/usr/local/mysql8/mysql-8.0.20-linux-glibc2.12-x86_64/datas/mysql/mysql.pid
    # 服务端使用的字符集默认为8比特编码
    character-set-server=utf8mb4
    lower_case_table_names=1
    autocommit =1
    
    [mysqld_safe]
    log-error =/usr/local/mysql8/mysql-8.0.20-linux-glibc2.12-x86_64/datas/mysql/mysql1.log
    pid-file  =/usr/local/mysql8/mysql-8.0.20-linux-glibc2.12-x86_64/datas/mysql/mysql1.pid
     
     ##################以上要修改的########################
    skip-external-locking
    key_buffer_size = 256M
    max_allowed_packet = 1M
    table_open_cache = 1024
    sort_buffer_size = 4M
    net_buffer_length = 8K
    read_buffer_size = 4M
    read_rnd_buffer_size = 512K
    myisam_sort_buffer_size = 64M
    thread_cache_size = 128
      
    #query_cache_size = 128M
    tmp_table_size = 128M
    explicit_defaults_for_timestamp = true
    max_connections = 500
    max_connect_errors = 100
    open_files_limit = 65535
       
    binlog_format=mixed
        
    binlog_expire_logs_seconds =864000
        
    # 创建新表时将使用的默认存储引擎
    default_storage_engine = InnoDB
    innodb_data_file_path = ibdata1:10M:autoextend
    innodb_buffer_pool_size = 1024M
    innodb_log_file_size = 256M
    innodb_log_buffer_size = 8M
    innodb_flush_log_at_trx_commit = 1
    innodb_lock_wait_timeout = 50
    transaction-isolation=READ-COMMITTED
          
    [mysqldump]
    quick
    max_allowed_packet = 16M
           
    [myisamchk]
    key_buffer_size = 256M
    sort_buffer_size = 4M
    read_buffer = 2M
    write_buffer = 2M
            
    [mysqlhotcopy]
    interactive-timeout
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    16.0.6 进行初始化
    yum -y install numactl # 安装依赖包
    mysqld --defaults-file=/usr/local/mysql8/mysql-8.0.20-linux-glibc2.12-x86_64/my.cnf --basedir=/usr/local/mysql8/mysql-8.0.20-linux-glibc2.12-x86_64/ --datadir=/usr/local/mysql8/mysql-8.0.20-linux-glibc2.12-x86_64/datas/mysql --user=mysql --initialize-insecure
    参数(重要)
    defaults-file:指定配置文件(要放在–initialize 前面)
    user: 指定用户
    basedir:指定安装目录
    datadir:指定初始化数据目录
    intialize-insecure:初始化无密码
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 去/usr/local/mysql8/mysql-8.0.20-linux-glibc2.12-x86_64/datas/mysql/mgsql.log看是否有报错,有报错处理下
    16.0.7 启动服务
    • 用于后台安全启动MySQL

      mysqld_safe --defaults-file=/usr/local/mysql8/mysql-8.0.20-linux-glibc2.12-x86_64/my.cnf &

    • 查看服务是否启动

      ps -ef|grep mysql
      看到有这么多就是成功了
      在这里插入图片描述

    • 如果mysqld起不起来

      find / -name mysql.server
      cp 文件路径 /etc/init.d/mysqld
      systemctl enable mysqld

    16.0.8 进入数据库配置
    # 修改密码
    ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '123456';
    # 刷新权限
    FLUSH PRIVILEGES;
    # 设置允许远程登录
    mysql> use mysql
    mysql> update user set user.Host='%'where user.User='root';
    mysql> flush privileges;
    mysql> quit
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 验证时使用navicat远程连接下

    • 一些命令

      mysql -u root -p
      systemctl start mysql.service # 启动MySQL
      systemctl restart mysql.service # 启动MySQL
      systemctl stop mysql.service

    16.1 下载nginx前置文件

    yum install gcc-c++                   #安装gcc
    yum install -y pcre pcre-devel        #安装PCRE
    yum install -y zlib zlib-devel        #安装zlib
    yum install -y openssl openssl-devel  #安装OpenSSL
    
    • 1
    • 2
    • 3
    • 4

    16.2 下载nginx压缩包并安装

    cd   /home                            #切换到家目录
    wget -c https://nginx.org/download/nginx-1.12.0.tar.gz    #直接从官网下载压缩包到当前目录
    ls                                    #查看一下当前目录有哪些文件和目录
    cd /usr/local               #切换到local目录
    mkdir nginx                 #创建一个名为nginx的目录
    tar xvfzC /home/nginx-1.12.0.tar.gz  /usr/local/nginx/   #将压缩包解压到nginx目录
    cd nginx                    #进入创建好的目录下
    cd nginx-1.12.0/            #进入解压出的新目录
    ./configure                 #配置环境
    make  &&  make install      #编译并安装程序
    cd /usr/local/nginx/sbin    #进入sbin目录
    ./nginx                     #启动nginx服务
    netstat -ntlp | grep nginx  #过滤查看是否开启了该服务
    ifconfig                    #查询IP地址
    有个inet的内网地址,如果部署在服务器上直接访问公网IP即可默认就是80端口
    浏览器中输入公网地址验证服务是否成功,成功就显示nginx默认页面
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这里插入图片描述

    • 一些命令
    systemctl status nginx.service
    #启动nginx服务
    systemctl start nginx.service
    #停止nginx服务
    systemctl stop nginx.service
    #重启nginx服务
    systemctl restart nginx.service
    #重新读取nginx配置(这个最常用, 不用停止nginx服务就能使修改的配置生效)
    systemctl reload nginx.service
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    16.3 django项目打包到服务器上

    • 本地执行若没有仓库先在github上建立个仓库

      git init
      git add .
      git -m commit “xxx”
      git push -u origin master

    • 服务器拉代码到相应的服务器上 进入相应目录

      git clone https:xxx

    16.4 为django创建虚拟环境

    • 在根目录下

      mkdir env

    • 进入env下安装虚拟环境包

    pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple virtualenv
    
    • 1
    • 查看是否安装完毕
    virtualenv --version 
    # 出现下列信息就是安装完毕(不是命令!)
    virtualenv 20.16.4 from /usr/local/python3.9/lib/python3.9/site-packages/virtualenv/__init__.py
    
    • 1
    • 2
    • 3
    • 创建虚拟环境
    virtualenv django_employee_system
    
    • 1
    • 激活虚拟环境在env(激活后前面会有虚拟环境的(venv))
    cd /env
    source django_employee_system/bin/activate
    
    • 1
    • 2

    --------------------------------------记录下windows下使用命令行启用虚拟环境读者可自行跳过 开始----------------------------------
    windows上如果pycharm的terminal用的是powershell则先需要让其可以执行脚本
    在这里插入图片描述
    需要输入

    set-ExecutionPolicy RemoteSigned
    
    • 1

    然后输入 y
    在这里插入图片描述

    • 创建虚拟环境
    virtualenv django_employee_system
    
    • 1
    • 进入虚拟环境
    cd F:\django_employee_system\env\django_employee_system\Scripts
    .\activate.bat
    
    • 1
    • 2

    在这里插入图片描述
    退出虚拟环境

    cd F:\django_employee_system\env\django_employee_system\Scripts
    .\deactivate.bat
    
    • 1
    • 2

    激活虚拟环境运行此时可以直接忽视pycharm的报错 也可以运行起来
    在这里插入图片描述

    • 如果powershell不能进入虚拟环境,直接使用cmd可以进入
      在这里插入图片描述

    --------------------------------------windows下使用命令行启用虚拟环境结束----------------------------------

    • 本地项目根目录执行生成requirements.txt
    pip freeze > requirements.txt
    
    • 1
    • 在激活的服务器上的虚拟环境进入代码目录执行(先安装mysql不然mysql_client会报错)
    pip3 install -r requirements.txt 
    
    • 1

    img

    • 查看有哪些包
    pip3 list
    
    • 1
    • 退出虚拟环境
    deactivate
    
    • 1

    16.5 uWSGI的安装与配置

    16.5.1 释义
     uWSGI(WEB SERVER GATEWAY INTERFACE)是Python Web服务器,实现了WSGI通信规范和uwsgi协议
    
    • 1
    16.5.2 下载和配置
    • 进入刚才的虚拟环境输入
    pip3 install uWSG
    
    • 1
    • 查看是否安装成功

      uwsgi --version

    • 编写uwsgi的ini配置文件 放到项目根目录下

    [uwsgi]
    socket = 127.0.0.1:8080  
    chdir = /data/django_employee_system #项目根目录
    wsgi-file = django_employee_system/wsgi.py # wsgi.py所在位置
    processes = 1 # 进程数
    threads = 4 # 线程数
    virtualenv = /env/django_employee_system #虚拟环境位置
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 上面的配置容易挂掉 10进程 4线程好多了没有出现挂掉的情况
    [uwsgi]
    socket = 127.0.0.1:8080
    chdir = /data/django_employee_system
    wsgi-file = django_employee_system/wsgi.py
    processes = 10
    threads = 4
    virtualenv = /env/django_employee_system
    PythonHome = /usr/local/python3.9/lib/python3.9/site-packages
    daemonize = /var/log/uwsgi.log
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    16.5.3 启动与关闭uwsgi
    • 启动(虚拟环境的相关目录下)
    cd /env&&source django_employee_system/bin/activate
    uwsgi --ini employee_uwsgi.ini
    
    • 1
    • 2
    • 故障处理对于wsgi.py
    import sys
    sys.path.append("/usr/local/python3.9/lib/python3.9/site-packages")
    
    • 1
    • 2
    • 关闭
    ps -ef | grep employee_uwsgi.ini
    kill -9 [pid]
    
    • 1
    • 2
    • 一些命令
    uwsgi --ini employee_uwsgi.ini
    nohup uwsgi --ini employee_uwsgi.ini &    # 后台启动uwsgi服务器
    uwsgi --reload uwsgi.pid  # 重启
    uwsgi --stop uwsgi.pid # 停止
    kill -9 pid   # 关闭服务,直接kill uwsgi的端口
    
    • 1
    • 2
    • 3
    • 4
    • 5

    16.6 uWSGI与nginx的结合配置(开启8080端口)

    -16.6.1 由于在uwsgi.ini的配置文件是 socket = 127.0.0.1:8080
    在/usr/local/nginx/conf的nginx.cnf增加 upstream django 并且端口号都配置为8080端口

    upstream django {
        # server unix:///path/to/your/mysite/mysite.sock; # 使用unix套接字
        server 127.0.0.1:8080; # 使用TCP端口请注释上一行,并取消本行注释,这里的端口指的是跑uwsgi的端口
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    -16.6.2 所有发给nginx的请求都给django

     location / {
            uwsgi_pass  django;
            include     uwsgi_params; # 从github上下载的uwsgi_params 文件路径
             }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 特别注意文件路径和缩进
      在这里插入图片描述
      启动

    • 16.6.3 重启nginx服务

    • 16.6.3.1 进入相关目录并验证nginx配置文件是否正确

      cd /usr/local/nginx/sbin # 进入相关目录
      ./nginx -t #先验证nginx配置文件是否正确 -t test的意思

    • 出现下列说明显示说明配置成功
      在这里插入图片描述

    • 一些命令

      cd /usr/local/nginx/sbin #(前提)
      ./nginx -c /usr/local/nginx/conf/nginx.conf # 启动nginx Nginx服务器指定启动配置文件命令
      ./nginx -s stop # 暴力停止Nginx服务器命令
      ./nginx -s reload # Nginx重新加载配置文件命令
      ps -ef | grep nginx
      kill -QUIT 主进程号 :从容停止Nginx
      kill -TERM 主进程号 :快速停止Nginx
      pkill -9 nginx :强制停止Nginx

    • 访问公网地址,出现此页面说明反向代理成功
      在这里插入图片描述

    16.7 django项目中的静态文件配置(基于local_settings.py)

    • 在settings.py同级目录下创建local_settings.py,同时在settings.py最后增加代码
    try:
        from .local_settings import *
    except ImportError:
        pass
    
    • 1
    • 2
    • 3
    • 4
    • 在项目根目录下创建.gitignore文件 此文件在git提交时 里面所写的文件不会改变 写入
    local_settings.py
    wsgi.py
    
    • 1
    • 2
    • 配置开发环境local_settings.py
    DEBUG = True
    ALLOWED_HOSTS = ['*']
    
    • 1
    • 2
    • 配置线上环境local_settings.py

      cd /data/django_employee_system/django_employee_system
      touch local_settings.py
      vim local_settings.py

    • 放入

    DEBUG = True
    ALLOWED_HOSTS = ['*']
    STATIC_ROOT = "/data/djangp_emplyee_system_static" 
    
    • 1
    • 2
    • 3
    • 线上执行收集静态文件

      cd env
      source django_employee_system/bin/activate

    • 进入manage.py的同级别目录下执行

      python3 manage.py collectstatic
      在这里插入图片描述

    修改nginx.cnf

    cd /usr/local/nginx/conf 
    
    • 1
            location /media  {
                alias  /data/django_employee_system/media/;  # 指向django的media目录
                 }
                 
            location /static {
            alias /data/djangp_emplyee_system_static/; # 指向django的static目录
                }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 通过listen确定端口号如果是80端口则需如公网地址即可
      在这里插入图片描述

    在这里插入图片描述

    • 重启nginx和uwsgi服务

      cd /usr/local/nginx/sbin
      ./nginx -s reload

      ps -ef | grep employee_uwsgi.ini
      kill -9 [pid]
      (虚拟环境)
      cd /env&&source django_employee_system/bin/activate
      killall uwsgi
      cd /data/django_employee_system&&nohup uwsgi --ini employee_uwsgi.ini &
      deactivate

    16.8 配置数据库

    • settings.py配置自己数据库就行
  • 相关阅读:
    Zeno节点系统中的C++最佳实践
    【技术视界】鸿蒙开发套件之DevEco Profiler助您轻松分析应用性能问题
    C和指针 第11章 动态内存分配 11.6 内存分配实例
    vue学习笔记21-组件传递数据_Props
    Python和BeautifulSoup库的魔力:解析TikTok视频页面
    【编程题】【Scratch三级】2021.12 分身术
    访问者模式
    uniapp vue国际化 i18n
    style=“width: ___“ VS width=“___“
    矩阵混乱度(熵值)代码计算
  • 原文地址:https://blog.csdn.net/weixin_44259638/article/details/126835939