[TOC]
一. 搭建基础模板
1.git 建仓库
github或gitee上创建项目厂库
2.clone仓库
git clone url
3.创建虚拟环境
python3 -m venv venv
source venv/bin/activate
注意: Ubuntu中 pycharm使用上面命令可能失效,
而且pycharm配置虚拟环境也可能失败,
原因是Ubuntu自带的Python中没有Virtualenv
pip install virtualenv 后就好
4.安装依赖项
amqp==2.4.2
billiard==3.6.0.0
celery==4.3.0 #芹菜(消息队列)
certifi==2019.3.9
chardet==3.0.4
Django==2.1.8 # django 主程序
django-cors-headers==3.0.1 # 跨域访问
django-debug-toolbar==1.11 # debug测试工具
django-filter==2.1.0 # 数据筛选
django-redis==4.10.0 # redis依赖库
djangorestframework==3.9.4 # rest 风格接口
drf-extensions==0.5.0
idna==2.8
kombu==4.5.0
Pillow==6.0.0 # pillow 图片处理
PyMySQL==0.9.3 # MySQL依赖
pytz==2019.1
qiniu==7.2.4 # 千牛上传(图片加速)
redis==3.2.1 # redis 依赖
requests==2.21.0 # http请求相应
sqlparse==0.3.0
urllib3==1.24.3
vine==1.3.0
xlrd==1.2.0 # excel 表格处理(读)
xlwt==1.3.0 # excel 表格处理(写)
- 前期Django==2.1.8 必须先安装 否则后面的就无法进行了
5.创建项目
django-admin startproject seeyoudjango .
- 注意: 最后的点 代表当前目录,不能省
6.创建应用
django-admin startapp api
- 注意: 没有点
7.运行测试
Python manage.py runserver
二. 配置
1. 配置时区和语言
settings.py
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Chongqing'
2. 配置数据库(sql)
- 依赖项: PyMySQL==0.9.3
- settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'qschool',
'HOST': '39.98.242.43',
'PORT': 3306,
'USER': 'root',
'PASSWORD': 'LiuLangPython',
'TIME_ZONE': 'Asia/Chongqing'
}
}
- _init_py
import pymysql
pymysql.install_as_MySQLdb()
- 数据库不要忘了建库
3. 配置redis 和缓存
- 依赖项: django-redis==4.10.0
- settings.py
CACHES = {
'default': {
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': ['redis://39.98.242.43:6379/0'],
'KEY_PREFIX': 'fangtx',
'OPTIONS': {
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
'CONNECTTON_POOL_KWARGS': {
'max_connections': 128,
},
'PASSWORD': '1qaz2wsx',
},
},
'session': {
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': ['redis://39.98.242.43:6379/1'],
'KEY_PREFIX': 'fangtx:session',
'OPTIONS': {
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
'CONNECTTON_POOL_KWARGS': {
'max_connections': 128,
},
'PASSWORD': '1qaz2wsx',
},
}
}
4. 配置session和cache(缓存)
- settings.py
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
SESSION_CACHE_ALIAS = 'session'
SESSION_COOKIE_AGE = 86400
5. 配置静态资源路径
- 创建静态资源目录(项目下创建)
static
media
- settings.py
STATICFILES_DIRS = [os.path.join(BASE_DIR, "static"), ]
STATIC_URL = '/static/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
- urls.py
from django.conf.urls.static import static
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
- 测试静态资源
在static和media目录下放置测试图片
启动项目
http://127.0.0.1:8000/static/test.jpeg
http://127.0.0.1:8000/media/test.jpeg
6. 配置后端模板
- 创建模板目录(项目下创建)
templates
- settings.py
TEMPLATES = [
{
'DIRS': [os.path.join(BASE_DIR, 'templates')],
},
]
7. 配置日志和debug
- urls
if settings.DEBUG:
import debug_toolbar
urlpatterns.insert(0, path('__debug__/', include(debug_toolbar.urls)))
- setting
INSTALLED_APPS = [
'debug_toolbar',
]
# 调试工具栏
DEBUG_TOOLBAR_CONFIG = {
# 引入jQuery库
'JQUERY_URL': 'https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js',
# 工具栏是否折叠
'SHOW_COLLAPSED': True,
# 是否显示工具栏
'SHOW_TOOLBAR_CALLBACK': lambda x: True,
}
MIDDLEWARE = [
'debug_toolbar.middleware.DebugToolbarMiddleware',
]
INSTALLED_APPS = [
'debug_toolbar',
]
# 日志
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'simple': {
'format': '%(asctime)s %(module)s.%(funcName)s: %(message)s',
'datefmt': '%Y-%m-%d %H:%M:%S',
},
'verbose': {
'format': '%(asctime)s %(levelname)s [%(process)d-%(threadName)s] '
'%(module)s.%(funcName)s line %(lineno)d: %(message)s',
'datefmt': '%Y-%m-%d %H:%M:%S',
}
},
'filters': {
'require_debug_true': {
'()': 'django.utils.log.RequireDebugTrue',
},
},
'handlers': {
'console': {
'class': 'logging.StreamHandler',
'level': 'DEBUG',
'filters': ['require_debug_true'],
'formatter': 'simple',
},
'file1': {
'class': 'logging.handlers.TimedRotatingFileHandler',
'filename': 'access.log',
'when': 'W0',
'backupCount': 12,
'formatter': 'simple',
'level': 'INFO',
},
'file2': {
'class': 'logging.handlers.TimedRotatingFileHandler',
'filename': 'error.log',
'when': 'D',
'backupCount': 31,
'formatter': 'verbose',
'level': 'WARNING',
},
},
'loggers': {
'django': {
'handlers': ['console', 'file1', 'file2'],
'propagate': True,
'level': 'WARNING',
},
}
}
8. 配置RESTfull
INSTALLED_APPS = [
'rest_framework', # rest风格app
'django_filters', # 数据筛选
'corsheaders',
]
99. 模板主页测试
- urls.py
from api import views
urlpatterns = [
path('', views.index),
]
- views.py
def index(request):
return render(request, 'index.html')
- index.html(templates目录下)
<h1>主页测试</h1>
- http://127.0.0.1:8000/
三.模型(数据库)
tag:django,sql,modile
正向工程:
- 通过程序中的模型生成数据库中的表
python manage makemigrations
python manage migrate
migrate(后面带app 只迁移app的models 否则会迁移自带的10多张表)
反向工程 :
- 通过数据库中的表来生成程序中的模型
python manage inspectdb > car/models.py
如果项目规模较大 有专业的dba 建议使用反向工程
如果项目规模小 没有专业的dba 推荐使用正向工程
四.视图
五. urls(路由和接口)
六. 模型数据库(orm)
一对一
onetoone
一对多
多对多
manyto
七. form(表单检查)
tag: django,form
a. 写检查类
import re
from django import forms
from django.core.exceptions import ValidationError
from vote.models import User
from vote.utils import to_md5_hex
class LoginForm(forms.Form):
username = forms.CharField(min_length=4, max_length=20)
password = forms.CharField(min_length=8, max_length=20)
captcha = forms.CharField(min_length=4, max_length=4)
def clean_username(self):
username = self.cleaned_data['username']
pattern = re.compile(r'\w{4,20}')
if not pattern.fullmatch(username):
raise ValidationError('用户名由字母、数字、下划线构成且长度为4-20个字符')
return username
def clean_password(self):
password = self.cleaned_data['password']
return to_md5_hex(password)
class RegisterForm(forms.ModelForm): # ModelForm 可以关联模型 模型中有的属性可以省略
repassword = forms.CharField(min_length=8, max_length=20)
mobilecode = forms.CharField(min_length=6, max_length=6)
def clean_username(self):
username = self.cleaned_data['username']
pattern = re.compile(r'\w{4,20}')
if not pattern.fullmatch(username):
raise ValidationError('用户名由字母、数字、下划线构成且长度为4-20个字符')
return username
def clean_password(self):
password = self.cleaned_data['password']
return to_md5_hex(password)
def clean_repassword(self):
password = self.cleaned_data['password']
repassword = self.cleaned_data['repassword']
if password != to_md5_hex(repassword):
raise ValidationError('密码和确认密码需要保持一致')
return repassword
# 关联模型
class Meta:
model = User
exclude = ('no', 'regdate')
b. 测试
>>> from vote.myforms import RegisterForm # 导入
>>> f = RegisterForm({'username':'种马就','password':'12345678','repassword':'12345678'}) # 创建对象
>>> f.is_valid() # 格式检查
True
>>> f.cleaned_data # 取数据
{'username': '种马饿哦就', 'password': '25d55ad283aa400af464c76d713c07ad', 'repassword': '12345678'}
>>> f.errors # 输出错误信息
{}
c. 视图使用
def register(request: HttpRequest):
if request.method == 'POST':
form = RegisterForm(request.POST) # 创建检查对象
if form.is_valid():
tel = form.cleaned_data['tel']
- 只要前端提交的表单的key和model,form 一致 就可以直接使用post创建对象
⑩. 模板语法
{# 这是django中有的if语法
{% ifequal item 'vue' %}
<span style="color:yellow;">{{ item }}</span>
{% endifequal %}
#}
⑩. 阶段模板
⑩RESTfull接口
1.分页
2.序列化
3.筛选
1.重写get_queryset(self)方法
filter ()
4.函数重构
⑩认证(JWT)
1.认证
2.JWT
⑩授权
⑩优化
1. cooking / session
用户session
存入
request.session['captcha'] = captcha_text
取出
captcha_sess = request.session.get('captcha', '')
# cooking的使用
resp.set.cookins()
2. 接口 /页面缓存
3. SQL优化
模型不要外键约束
db_constraint=False
取消外检约束可以提升数据库的性能
n+1解决
.prefetch_related #多对多
queryset = Agent.objects.all().prefetch_related('estate')
缓存结果
上下文语法
from contextlib import contextmanager
from time import time
@contextmanager
def duration():
stat = time()
yield
end = time()
print('time:', end - stat)
def func1(num):
if num in (1, 0):
return 1
return num * func1(num-1)
with duration():
print(func1(5))
#异常处理
try :
except
finally
4. 接口限流
5. 消息队列
# 注册环境变量
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'fangtx.settings')
# 创建Celery实例
app = celery.Celery(
'fangtx',
broker='amqp://luohao:[email protected]:5672/vhost1'
)
# 从项目的配置文件读取Celery配置信息
app.config_from_object('django.conf:settings')
# 从指定的文件(例如celery_config.py)中读取Celery配置信息
# app.config_from_object('celery_config')
# 让Celery自动从参数指定的应用中发现异步任务/定时任务
app.autodiscover_tasks(['common', ])
# 让Celery自动从所有注册的应用中发现异步任务/定时任务
# app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
⑩上线
1.上线检查(代码)
python manage.py check --deploy
2.上线配置(代码)
- settings.py
a. 跨域访问
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
]
INSTALLED_APPS = [
'corsheaders',
]
# 配置允许跨域访问接口数据
CORS_ORIGIN_ALLOW_ALL = True
# 跨域访问允许的请求头
CORS_ALLOW_HEADERS = (
'accept',
'accept-encoding',
'authorization',
'content-type',
'dnt',
'origin',
'user-agent',
'x-csrftoken',
'x-requested-with',
'token',
)
# 跨域访问支持的HTTP请求方法
CORS_ALLOW_METHODS = (
'DELETE',
'GET',
'OPTIONS',
'PATCH',
'POST',
'PUT',
)
b. 注释掉调试工具
MIDDLEWARE = [
# 'debug_toolbar.middleware.DebugToolbarMiddleware',
]
INSTALLED_APPS = [
# 'debug_toolbar',
]
c. 关闭调试模式 授予所有主机访问权限
DEBUG = False
ALLOWED_HOSTS = ['*']
sd. 上线安全设置
# 保持HTTPS连接的时间
SECURE_HSTS_SECONDS = 3600
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True
# 自动重定向到安全连接
SECURE_SSL_REDIRECT = True
# 避免浏览器自作聪明推断内容类型
SECURE_CONTENT_TYPE_NOSNIFF = True
# 避免跨站脚本攻击
SECURE_BROWSER_XSS_FILTER = True
# COOKIE只能通过HTTPS进行传输
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
# 防止点击劫持攻击手段 - 修改HTTP协议响应头
# 当前网站是不允许使用<iframe>标签进行加载的
X_FRAME_OPTIONS = 'DENY'
3. 上线环境搭建(服务端)
a. 创建目录
project
|-code 代码
|-conf 配置
|-logs 日志
|-stat 静态资源目录
mkdir -p project/code
mkdir -p project/conf
mkdir -p project/logs
mkdir -p project/stat
b. clone代码
cd code
git clone <url>
c. 创建,激活Python虚拟环境
python3 -m venv venv
source venv/bin/activate
d. 安装依赖项
pip install -r code/fangtx/requirements.txt
4. uwsgi
a. 安装uwsgi
pip install uwsgi
b. 写配置文件
- conf -> uwsgi.conf
[uwsgi]
# 配置前导路径
base=/root/project
# 配置项目名称
name=fangtx
# 守护进程
master=true
# 进程个数(一般按照cpu核心数量配置)
processes=1
# 虚拟环境
pythonhome=%(base)/venv
# 项目地址
chdir=%(base)/code/%(name)
# 指定python解释器
pythonpath=%(pythonhome)/bin/python
# 指定uwsgi文件
module=%(name).wsgi
# 通信的地址和端口(自己服务器的内网IP地址和端口)
# 调试
http = 172.26.203.240:80
# socket=172.26.203.240:8000
# 日志文件地址(调试将其注销,日志将打印在终端控制台)
# logto=%(base)/logs/uwsgi.log
c. uwsgi测试
uwsgi --ini conf/uwsgi.conf
# 启动 uwsgi
# 通过 外网ip访问测试uwsgi 和代码
5. nginx
a. 配置静态资源
- 配置静态资源目录 settings.py
STATIC_URL = '/static/'
STATIC_ROOT = '/root/project/stat/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static'), ]
- 自动收集静态资源
python manage.py collectstatic
注意:先必须激活虚拟环境
b. http配置
- /etc/nginx/nginx.conf
vim /etc/nginx/nginx.conf
# 修改 第5行
user root;
# 删除37行之后的代码
# 37 行添加自己的conf路径
include /root/project/conf/nginx.conf;
# 注意结尾的 } 记得补上
- conf -> nginx.conf
server {
listen 80;
server_name _;
access_log /root/project/logs/access.log;
error_log /root/project/logs/error.log;
location / {
include uwsgi_params;
uwsgi_pass 172.26.203.240:8000;
}
location /static/ {
alias /root/project/stat/;
expires 30d;
}
}
c. 修改uwsgi代码
# 通信的地址和端口(自己服务器的内网IP地址和端口)
# 调试
# http = 172.26.203.240:80
socket=172.26.203.240:8000
# 日志文件地址(调试将其注销,日志将打印在终端控制台)
logto=%(base)/logs/uwsgi.log
d. nginx测试
# 启动 nginx
systemctl start nginx
# 通过 外网ip访问测试
6. https(安全的http协议)
a. 购买域名
b. 域名备案
- 个人域名审核: 需要提交身份证正反面照片和下载一份表单打印并签字
- 网站备案信息真实性核验单(签字)
- 时间是在30个工作日之内
c. 域名绑定
d. 购买证书
- 测试推荐使用在阿里上购买赛门铁克的免费证书(不含子域名)
- 时间在在几分钟到一小时(推荐工作时间购买)
e. 上传证书
cert
|-2249009_cw731.com.pem 公钥
|-2249009_cw731.com.key 私钥
f. 修改配置 (添加内容)
- conf => nginx.conf
server {
listen 443;
server_name _;
access_log /root/project/logs/access.log;
error_log /root/project/logs/error.log;
ssl on;
ssl_certificate /root/project/conf/cert/2249009_cw731.com.pem ;
ssl_certificate_key /root/project/conf/cert/2249009_cw731.com.key;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:! NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
location / {
include uwsgi_params;
uwsgi_pass 172.26.203.240:8000;
}
location /static/ {
alias /root/project/stat/;
expires 30d;
}
}
g. 测试
# 重启 nginx
systemctl restart nginx
# 通过 域名访问测试
拓展
gitlab git私服
版本
使用版本号作为目录名称便于升级,和兼容老版本
参考
https://blog.51cto.com/newthink/1775427
https://django-filter.readthedocs.io/en/master/index.html
https://www.cnblogs.com/derek1184405959/p/8712206.html
转载于:https://www.jianshu.com/p/0bb133e89ade