零、创建django项目
一、默认项目文件介绍
创建app命令
python manage.py startapp app001
django_project:
·
二、创建APP
python manage.py startapp app001
- app001
- migrations 【不动】【数据库字段变更】
- 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这个类
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app001.apps.App001Config'
]
2.编写urls与视图函数对应关系[urls.py]
3.编写视图函数[views.py]
注意路由关系 点击某个按钮 触发a标签(一定是个路由 而不是.html的文件)->urls.py找到对应的视图函数->views.py找到对应的html->显示出来
4启动django
命令行启动
python manage.py runserver
停止django
ctrl+c
四、tempalate模板
模板中禁止函数的括号(for i in dict.keys)
1.templates的作用
tempalates用于html的显示 在views.py请求html时 静态文件处理 在APP下必须叫static
2.static的作用 引用静态文件
static(开发过程一般将js css 图片 作为静态文件) 在.html中 使用下面的方法来指定路径
{% load static %}
<script src={% static 'js/jquery-3.6.0.min.js' %}></script>
样式连接
https://v3.bootcss.com/css/
需要导入的资源
<link rel="stylesheet" href="{% static 'plugins/bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">
<script src="{% static 'js/jquery-3.6.0.min.js' %}"></script>
<script src="{% static 'plugins/bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script>
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="{% static 'plugins/bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">
<style>
.navbar {
border-radius: 0;
}
</style>
</head>
<body>
<script src="{% static 'js/jquery-3.6.0.min.js' %}"></script>
<script src="{% static 'plugins/bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script>
</body>
</html>
五、模板语法
本质:在html中写一些占位符,有数据对这些占位符号进行替换和处理 给用户的可没有啥子if_else,是一个纯的html 在html的语法
- 若在models.py 有对应的choices 可在html使用 get_字段名_display 显示对应的注释
get_level_display
六、请求与响应
def something(request):
print(request.method)
print(request.GET)
print(request.POST)
"""7.1浏览器地址栏中输入URL
7.2 <a href=“地址?参数=值&参数=值” >
7.3 form表单的method为get"""
重定向是让浏览器访问第三方网站 而不是我们访问了三方网站把HTMl给浏览器如下图第二种方式所示
七、数据库操作
7.1 安装第三方sql库 mysqlclient django底层对mysqlclient更友好相比pymysql
pip install mysqlclient
- ORM可以帮我们做两件事
- 创建、修改、删除数据库中的表(不用写sql)【无法创建数据库 自己手动创建】
- 操作表中的数据(不用写SQL语句)
7.2 将settings.py的名为DATABASES字典进行替换 这就是连接的数据库
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'dbname',
'USER': 'root',
'PASSWORD': 'xxx',
'HOST': '',
'PORT': '',
}
}
7.3 django操作表 进入models.py(会自动创建自增id的列)
from django.db import models
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;
"""
数据库default值字段不会生效 有些注释也不会生效但是实际插入过程中会生效的
depart = models.ForeignKey(to=Department",to_field="id",null=True,blank=True,on_delete=models.SET_NUL)
创建、修改、删除表之后都必须在根目录执行命令如下(不执行不会生效)
python manage.py makemigrations
python manage.py migrate
7.4 操作表中的数据
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.id, i.name)
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="王五")
datalist 为 QuerySet类型 相当于一个列表里面存储了很多对象 [对象1,对象2...] 每个对象都是一行数据
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.get_gender_display())
7.6 orm一些条件操作
字段="三"
字段__contains="三"
字段__startswith="三"
字段__startswith="三"
字段__isnull=True
字段__isnull=False
字段__in=[1,2,3]
字段__gt=1
字段__gte=1
字段__lt=1
字段__lte=1
日期字段__year=2020
日期字段__month=3
日期字段__day=4
日期字段__gt|lt|...="2020-10-10"
import datetime
日期字段__gt|lt|...=datetime.date(2020,10,10)
日期字段__range=("2020-01-01","2020-06-01")
日期字段__range=(datetime.date(2020,1,1),datetime.date(2020,6,1))
八、模板继承
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>标题</h1>
<div>
<h3>这个" block content endblock 这之间自定义的内容"</h3>
{% block content %} {% endblock %}
<h2>底部</h2>
</div>
</body>
</html>
- 继承模板 语法如下 首页这两个字 会在 标题 和 底部之间
{% extends 'layout.html'%}
{% block content %}
<h1>首页 在标题和底部之间</h1>
{% endblock %}
九 、初识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):
"""从数据表取字段"""
model = models.UserInfo
fields = ["name", "password", "age", "gender"]
def user_add(request):
"""添加用户基于modelform"""
form = UserModelForm
return render(request, "user_add.html", {"form": form})
form.name.label 指的是 models.py的中文注释 form.name 则指的是字段名称
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</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>
9.2.2 定义样式
- model form 也可以再代码里定义样式 如下面的widgets
class UserModelForm(forms.ModelForm):
"""从数据表取字段"""
class Meta:
model = models.UserInfo
fields = ["name", "password", "age", "gender"]
widgets = {
"name": forms.TextInput(attrs={"class": "form-control"})
}
fields = ["name", "password", "age", "gender"]
fields = "__all__"
- 不使用某些字段 exclude = [“admin”]
exclude = ["admin"]
fields = "__all__"
- 使某些字段不可编辑 需要在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="借阅人")
- moder form 批量定义 注意缩进 重写了__init__
class UserModelForm(forms.ModelForm):
"""从数据表取字段"""
class Meta:
model = models.UserInfo
fields = ["name", "password", "age", "gender","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}
html中对应代码
{% for field in form %}
<div class="form-group">
<label>{{ field.label }}</label>
{{ field }}
</div>
{% endfor %}`
9.2.3校验字段是否合法
代码层面 校验失败时 返回此页面而不是 重定向 返回可以保留之前的数据
return render(request, "user_add.html", {"form": form, "department_list": department_list})
关闭浏览器自己做的校验 在相应表单上填写 novalidate
<form method="post" novalidate>
- 加上语句 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 %}
-
提示是英文的 下面我们改成中文 进入settings.py 找到LANGUAGE_CODE = ‘en-us’ 注释掉 改成 -
LANGUAGE_CODE = ‘zh-hans’ -
若要添加特定的规则进行校验 需要在相应的model form下添加规则 name = forms.CharField(label=“员工名称”,min_length=2))
class UserModelForm(forms.ModelForm):
"""从数据表取字段"""
name = forms.CharField(label="员工名称",min_length=2)
class Meta:
model = models.UserInfo
fields = ["name", "password", "age", "gender", "account", "create_time"]
十 、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()
10.2 查 和model form 没有啥关系
models.Department.objects.all()
10.3 改
增加了一个参数 instance 这样才知道更改哪条数据 即先实例化 再赋给modelform 提交时需要添加参数data=request.POST
a = models.UserInfo.objects.filter(id=nid).first()
form = UserModelForm(data=request.POST,instance=a)
- 对于在UserModelForm中没有使用字段但是model中拥有的字段想要入库时可以采取此写法
form.instance.depart_id = department_id.id
form.save()
10.4 删 和model form 没有啥关系
def user_deldete(request):
nid = request.GET.get("nid")
models.UserInfo.objects.filter(id=nid).delete()
return redirect("/user/list")
10.5 查看数据库中是否存在此字段 exist() 存在 true 不存在 false
is_exist = models.PrettyNumber.objects.filter(mobile=mobile_number).exists()
10.6 校验model form里的字段 在model form 里定义函数 clean_字段名 可以自动校验传过来的字段
def clean_mobile(self):
mobile_number = self.cleaned_data["mobile"]
if len(mobile_number) <= 11:
raise ValidationError("号码不足11位")
return mobile_number
10.7 sql排除某些字段
is_exist = models.PrettyNumber.objects.exclude(id=self.instance.pk).filter(mobile=mobile_number).exists()
十一.搜索模糊查询
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>
11.2 django可以通过字典的方式为filter赋值 **解包成 id=1,moblie=2这种形式
如果是空 data_dict[“mobile__contains”] = “” 则原生sql没有对应的where
data_dict={}
value = request.GET.get(key="query",default="")
if value:
data_dict["mobile__contains"] = value
pretty_data = models.PrettyNumber.objects.filter(**data_dict).order_by("-level")
若有多个搜索框继续在后面加即可如下图的value1如果存在就加到字典中
def pretty_list(request):
data_dict = {}
value = request.GET.get(key="query", default="")
value1 = request.GET.get(key="level", default="")
if value:
data_dict["mobile__contains"] = value
if value1:
data_dict["level"] = value1
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})
在界面上回显输入的搜索值 给input框内 赋值给value即可
<input type="text" name="query" class="form-control " placeholder="请输入号码" value="{{ value }}">
十二、登录
10.1登录页面获得表单数据
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"]
两种方法都可以用了 注意若在视图函数里使用form.cleaned_data 需要在form.is_valid
if form.is_valid():
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"]
- 在数据库进行查找 如果验证不通过则返回账号名或密码错误 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})
10.2 鉴权 cookie和sessions
- 因为http协议是短连接(网站是短连接的)的无状态的 为了让服务器知道是哪位用户在进行访问因此使用session来判断用户
- 加上 request.session[“user_info”] = {“id”: is_login.id, “name”: is_login.username}
is_login = models.Admin.objects.filter(**data_list).first()
if is_login:
request.session["user_info"] = {"id": is_login.id, "name": is_login.username}
return redirect("/admin/list")
- 然后登录重新登录数据库的django_session表就会写入session_key(session_id) 和 session_data 这种({“id”: is_login.id, “name”: is_login.username})
浏览器会记录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
10.3 django 中间件
- 释义:从发起请求到命中视图函数 一个请求会经过很多中间件(在django里面是一些类) 每个中间件都有 request 和 response如果哪个部分没有通过直接返回那个类的response 先进(指request)后出(指相应的response)
- 因此在中间件进行鉴权最合适 每个接口都要进行鉴权
- 中间件的执行顺序 在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',
]
- 中间件的实现 在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/":
return
user_info_dict = request.session.get("user_info")
print(user_info_dict)
if user_info_dict:
return
return redirect("/login/")
- 注册中间件 在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',
]
- 每次清除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):
request.session.clear()
return redirect("/login")
layout.html中此处路由写成logout就可以了
<li><a href="/logout/">退出</a></li>
- 可见是传了session_id的
- 数据库的session_data 变了 导致无法验证通过
13.2 右上角显示登录的账号
在相应的地方如母版中layout.html写入session的内容 就可以显示了 之前在登录的时候写入了 就能拿到
{{ request.session.user_info.name }}
十四、图片验证码
14.1 安装pillow
pip3 install pillow
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__':
img, code = check_code()
十五、上传图片
15.1 启用media文件夹 在根目录下创建media文件夹(固定写法)
15.1.1 在settings.py 配置
import os
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
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<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}),
]
15.1.3 在html的form 表单进行配置
- novalidate是浏览器不进行验证 enctype=“multipart/form-data” 是为了读到二进制文件
<form method="post" novalidate enctype="multipart/form-data">
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
15.2 上传实现
- 15.2.1 启用FileField 启用 upload_to 指定上传的文件夹
class Book(models.Model):
"""书籍表"""
book_cover = models.FileField(verbose_name="书籍封面",upload_to="media/")
-
三种上传方式 -
手动去写
file_object = request.FILES.get ( "exc")
- Form组件(表单验证)
request.POST
file_object = request.FILES.get ( "exc" )
具体文件操作还是手动自己做。
- ModelForm(表单验证+自动保存数据库+自动保存文件)
- Media文件夹
- Models.py定义类文件要
img = models.FileField(verbose_name="Logo", max_length=128,upload_to='city l ' )
十六、项目部署(腾讯云CentOS7.9 先开放3306端口)
16.0 安装MySQL
16.0.1 卸载MariaDB
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目录
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版本
16.0.3 创建用户群组
groupadd mysql # 创建一个用户组:mysql
useradd -r -g mysql mysql # 创建一个系统用户:mysql,指定用户组为mysql
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 # 更改模式
16.0.5 初始化MySQL
-
创建my.cnf配置文件,用于初始化MySQL数据库 touch /usr/local/mysql8/mysql-8.0.20-linux-glibc2.12-x86_64/my.cnf # 创建配置文件
-
写入下面数据 特别注意路径问题啊!!!很重要!!!
[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
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
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
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:初始化无密码
- 去/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
systemctl status nginx.service
systemctl start nginx.service
systemctl stop nginx.service
systemctl restart nginx.service
systemctl reload nginx.service
16.3 django项目打包到服务器上
16.4 为django创建虚拟环境
pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple virtualenv
virtualenv --version
virtualenv 20.16.4 from /usr/local/python3.9/lib/python3.9/site-packages/virtualenv/__init__.py
virtualenv django_employee_system
- 激活虚拟环境在env(激活后前面会有虚拟环境的(venv))
cd /env
source django_employee_system/bin/activate
- 本地项目根目录执行生成requirements.txt
pip freeze > requirements.txt
- 在激活的服务器上的虚拟环境进入代码目录执行(先安装mysql不然mysql_client会报错)
pip3 install -r requirements.txt
pip3 list
deactivate
16.5 uWSGI的安装与配置
16.5.1 释义
uWSGI(WEB SERVER GATEWAY INTERFACE)是Python Web服务器,实现了WSGI通信规范和uwsgi协议
16.5.2 下载和配置
pip3 install uWSG
-
查看是否安装成功 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 #虚拟环境位置
16.5.3 启动与关闭uwsgi
cd /env&&source django_employee_system/bin/activate
uwsgi --ini employee_uwsgi.ini
import sys
sys.path.append("/usr/local/python3.9/lib/python3.9/site-packages")
ps -ef | grep employee_uwsgi.ini
kill -9 [pid]
uwsgi --ini employee_uwsgi.ini
nohup uwsgi --ini employee_uwsgi.ini &
uwsgi --reload uwsgi.pid
uwsgi --stop uwsgi.pid
kill -9 pid
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的端口
}
-16.6.2 所有发给nginx的请求都给django
location / {
uwsgi_pass django;
include uwsgi_params; # 从github上下载的uwsgi_params 文件路径
}
-
特别注意文件路径和缩进 启动 -
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
- 在项目根目录下创建.gitignore文件 此文件在git提交时 里面所写的文件不会改变 写入
local_settings.py
wsgi.py
DEBUG = True
ALLOWED_HOSTS = ['*']
DEBUG = True
ALLOWED_HOSTS = ['*']
STATIC_ROOT = "/data/djangp_emplyee_system_static"
修改nginx.cnf
cd /usr/local/nginx/conf
location /media {
alias /data/django_employee_system/media/; # 指向django的media目录
}
location /static {
alias /data/djangp_emplyee_system_static/; # 指向django的static目录
}
- 通过listen确定端口号如果是80端口则需如公网地址即可
16.8 配置数据库
|