修改Mysql编码格式:
show variables like ‘character%’;
set character_set_database=utf8;
set character_set_server=‘utf8’;
-------------------------------------Django
导出环境:pip freeze > requirements.txt
sudo apt-get remove python-pip (卸载python2的pip)
sudo apt-get remove python3-pip (卸载3版本的pip3)
sudo apt-get install python3-pip (安装python3)
apt-get update (更新代码)
上线(简单):
sudo apt-get update
apt install python3-pip
pip freeze > requirements.txt 生成requirements.txt文件
pip3 install django==1.11
pip3 install -r requirements.txt
后台不间断:
apt install -y screen 安装
screen -S lnmp 创建一个lnmp的会话
screen -r lnmp 恢复到离开前创建的lnmp会话的工作界面、ctrl+a d 返回主页面
screen -ls 查看当前有哪些screen窗口
screen -X -S session quit 删除某个session
kill 9505 关闭指定的screen
python manage.py runserver 0.0.0.0:9000
上线(基础):
apt update 更新包
apt install python-dev python3-dev python-pip python3-pip
pip3 install --update pip
sudo apt-get install gcc
sudo pip3 install uwsgi uwsgi --version 来检查是否正确安装了
sudo apt-get install nginx
django命令
运行django项目: python manage.py runserver
创建django项目: django-admin startproject blog1
创建django应用: python manage.py startapp blog2
创建超级用户: python manage.py createsuperuser
生成迁移文件: python manage.py makemigrations
根据迁移文件创建数据库 python manage.py migrate
静态文件
在项目中创建static文件夹放置静态文件
在setting.py下配置静态文件(2种方法)
1.STATICFILES_DIRS = [ os.path.join(BASE_DIR,‘static’),]
引用的静态文件路径必须是 /static/css/…
2.直接引用静态文件的模版{% load static from staticfiles %}
引用的静态文件路径必须是{% static ‘css/2.css’ %}
URL(路由)
分发路由:url(r’’,include(‘xx.urls’))
无命名分组(视图里面要接收参数):url(r’^xx/(\d{4})’,视图)
有名分组(视图接收参数):url(r’^xx/(?P\d{4})’,视图)
路由别名: url(r’^xx/(\d{4})’,视图,name=‘x’) {%url ‘x’%}
from meduo_mall.demo import views
url(r’register/$’, views.Demo.as_view())
from django.views.generic import View
class Demo(View):
def get(self, request):
return HttpResponse(‘get page’)
def post(self, request):
return HttpResponse(‘post page’)
自定义404错误
1.在setting中配置 DEBUG = False
ALLOWED_HOSTS=["*"]
2.在templates中编写404页面
视图与模板
HttpResponse(“xxxx”)
render(request,‘x.html’,{‘xx’:x})
render_to_response(‘x.html’,{‘xx’:x})
render(request,‘x.html’,locals(将函数所有变量给模板))
loads()
def special(request):
a1 = 123
a2 = 456
a3 = 789
return render(request,‘index.html’,locals()) #跳转页面
重定向(URL会发生改变)
from django.http import HttpResponseRedirect
return HttpResponseRedirect("/index/")
跳转
from django.shortcuts import redirect
from django.urls import reverse
return redirect(’/login’) redirect(view.x) redirect(reverse(‘blog:article_list’))
request
request.POST
request.GET 获取HTTP GET方式请求传参,的参数(字典类型)request.POST.get(“name”)
request.method 获取请求中使用的HTTP方式的字符串表示。全大写表示
request.path 获取请求页面的全路径,不包括域名
request.full_path() 获取HTTP GET方式请求传参,的URL地址
模板
变量: { { var_name }}
过滤器: { { obl | fifter:param }}
注释: {# #}
标签: {% csrf_token %} {% url %}
{% if condition %} … {% endif %}
{% for %} … {% endfor %}
{% ifequal var1 var2 %} … {% endifequal %}
{% include “nav.html” %}
继承: {% block mainbody %} … {% endblock %}
{% extends “x.html” %} {% block mainbody %} … {% endblock %}
model(数据库模型)
配置mysql数据库
init.py导入MySQL
import pymysql
pymysql.install_as_MySQLdb()
DATABASES = {
‘default’: {
‘ENGINE’: ‘django.db.backends.mysql’,
‘NAME’: ‘test’,
‘USER’: ‘root’,
‘PASSWORD’: ‘123456’,
‘HOST’:‘localhost’,
‘PORT’:‘3306’,}}
创建表
class Test(models.Model):
name = models.CharField(max_length=20,verbose_name=‘姓名’)
age = models.IntegerField(‘年龄’,null=True,Blank=True)
nd =models.Charfield(choices=((‘cj’,‘初级’),(‘zj’,‘中级’),(‘gj’,‘高级’)),verbose_name=‘难度’) obj.get_字段名称_display
定义了auto_now_add或auto_now属性,那么这种列不会在admin的页面中显示
time1=models.DateField(auto_now=True) 每次更新都会更新 auto_created=False 自动创建
time2=models.DateTimeField(auto_now_add=True) 永远是创建时的时间
可以在列的定义语句后增加设置editable属性为True(最新版本已经删除了editable无法显示) update_time.editable = True
或者 admin中添加 readonly_fields = (‘save_date’, ‘mod_date’,)
models.BooleanField(Blank=True)允许admin后台中为空
class Meta:
verbose_name = ‘用户表’ #设置表名称在django后台显示的中文名称
verbose_name_plural = verbose_name
def str(self): #设置在django后台显示字段名称
return self.anem
链表操作
一对多:models.ForeignKey(其他表)
多对多:models.ManyToManyField(其他表)
一对一:models.OneToOneField(其他表)
数据库操作(通过views)
from .models import *
添加
1.test1 = Test(name=‘shouce.ren’)
test1.save()
2.Test.objects.create(name=‘xxx’)
3.dic = {‘user’:‘yangmv’,‘pwd’:‘123456’}
Test.objects.create(**dic)
查询
1.list = Test.objects.all()
for var in list:
print(var.name)
2.Test.objects.filter(name=“x”).order_by(“id”)
3.Test.objects.filter(id__gt=1)获取指定条件的数据 .get(id=2) .first() .last() .count()
__gt 大于 __gte 大于等于 __lt 小于 __lte 小于等于
4.order_by()排序,参数:‘字段名’ 称升序、’-字段名’ 称降序
修改
1.test1 = Test.objects.get(id=1)
test1.name = ‘菜鸟教程’
test1.save()
2.Test.objects.filter(id=1).update(name=‘教程’)
3.Test.objects.all().update(name=‘教程’)
删除
1.test1 = Test.objects.get(id=1)
test1.delete()
2.Test.objects.filter(id=1).delete()
3.Test.objects.all().delete()
多表操作(一对一) OneToOneField()外键链表,一对一类型,也就是相当于,在外键字段加了一个唯一索引,在添加数据时不能有重复类容,只能一对一
多表操作(一对多) 正向查找,也就是通过表的外键,查找到外键连接的表里的数据 __双下划线跨表查询必须是外键连接的表
反向查找,从一张表查到它,被那张表外键连接,然后查出外键连接表里的信息 外键表类名称_set,链表反向查找 外键表类名称__外键表字段
添加
1.Book.objects.create(name=‘x’,publish_id=2)
2.pub=Pub.objects.fifter(name=‘xx’)
Book.objects.create(name=‘xx’,publish=pub)
查询
1.pub=Pub.objects.filter(name=‘x’)[0]
ret=Book.objects.filter(publish=pub).value(‘name’)
2.Book.objects.fifter(publish_id=cid)
删除
cid = input(‘班级ID’) cnd = input(‘班级名称’)
1.Student.objects.fifter(cs_id=cid).delete()
2.Student.objects.fifter(cs__name=cnd).delete()
修改
1.Student.objects.fifter(cs_id=cid).update()
2.Student.objects.all().update(cs_id=cid)
多表操作(多对多)
m = models.ManyToManyField(“Teachers”)
obj = Classes.objects.fifter(id=1).first()
# 添加
obj.m.add(1)
obj.m.add([2,3])
# 删除
obj.m.remove([2,3])
# 清空
obj.m.clear()
# 重置
obj.m.set([2,3,5])
# 查询
ret = obj.m.all()
ret = obj.m.filter()
admin
注册
1.admin.site.register(Test)
2.admin.site.register([Test, Contact, Tag])
列表显示
1.class ArticleAdmin(admin.ModelAdmin):
list_display = (‘title’,‘pub_date’,‘update_time’)配置要显示的字段
admin.site.register(Article,ArticleAdmin)
[email protected](Blog)
class BlogAdmin(admin.ModelAdmin):
#listdisplay设置要显示在列表中的字段(id字段是Django模型的默认主键)
list_display = (‘id’, ‘caption’, ‘author’, ‘publish_time’)
#list_per_page设置每页显示多少条记录,默认是100条
list_per_page = 50
#ordering设置默认排序字段,负号表示降序排序
ordering = (’-publish_time’,)
#list_editable 设置默认可编辑字段
list_editable = [‘machine_room_id’, ‘temperature’]
#search_fields 为该列表页增加搜索栏
search_fields = (‘name’,)
#list_filter 对显示结果进行过滤
list_filter = [‘publish_time’]
#fk_fields 设置显示外键字段
fk_fields = (‘machine_room_id’,)
自定义表单
1.class ContactAdmin(admin.ModelAdmin):
fields = (‘name’, ‘email’)
admin.site.register(Contact, ContactAdmin)
2.class ContactAdmin(admin.ModelAdmin):
fieldsets = ( [‘Main’,{ ‘fields’‘name’,‘email’), }],)
admin.site.register(Contact, ContactAdmin)
调整页面头部显示内容和页面标题
class MyAdminSite(admin.AdminSite):
site_header = ‘好医生运维资源管理系统’ # 此处设置页面显示标题
site_title = ‘好医生运维’ # 此处设置页面头部标题
admin_site = MyAdminSite(name=‘management’)
界面汉化
LANGUAGE_CODE = ‘zh-hans’
TIME_ZONE = ‘Asia/Shanghai’
cookies
操作cookie
获取cookie: request.COOKIES[‘xx’]
设置cookie: request.set_cookie[‘xx’,value]
操作session(默认保存15天)
获取session: request.session[‘xx’] session.get(‘username’, ‘’)
设置session: request.session[‘xx’]=value
删除session: del request.session[‘xx’]
设置过期时间: request.session.set_expiry (value)
返回会话过期秒数: request.session.get_expiry_age()
返回会话结束日期: request.session.get_expiry_date()
数据库缓存
python manage.py createcachetable my_cache_table
CACHES = {
‘default’: {
‘BACKEND’: ‘django.core.cache.backends.db.DatabaseCache’,
‘LOCATION’: ‘my_cache_table’,
‘TIMEOUT’: 60 * 5,
}}
from django.views.decorators.cache import cache_page
@cache_page(30)
def index(request):
redis缓存
pip install django-redis
pip install django-redis-cache
CACHES = {
“default”: {
“BACKEND”: “django_redis.cache.RedisCache”,
“LOCATION”: “redis://127.0.0.1:6379”,
“OPTIONS”: {
“CLIENT_CLASS”: “django_redis.client.DefaultClient”,
“CONNECTION_POOL_KWARGS”: {“max_connections”: 100}
}
Ajax
Ajax向后台发送请求:
1.下载jQuery
2.$.ajax({
url:’/add.html’,
type:‘GET’,
data:{‘name’:‘xx’,‘pwd’:‘123’} /data: $(“form”).serialize(),
success:function(arg){
//回调函数 arg是服务端返回的数据
}
})
分页
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
article_list = Article.objects.all()
paginator = Paginator(article_list, 10) # 实例化一个分页对象, 每页显示10个
page = request.GET.get(‘page’) # 从URL通过get页码,如?page=3
try:
articles = paginator.page(page) # 获取某页对应的记录
except PageNotAnInteger: # 如果页码不是个整数
articles = paginator.page(1) # 提取第一页的记录
except EmptyPage: # 如果页码太大,没有相应的记录
articles = paginator.page(paginator.num_pages) # 提取最后一页的记录
return render(request, ‘’, {‘articles’: articles})
{% for page in all_org.paginator.page_range %}
{% if page == all_org.number %}
Form组件
from django import forms
class Form1(forms.Form):
img = forms.FileField()
city = forms.ChoiceField(choices=[(1,‘sh’),(2,‘bj’)])
hobby=forms.MultipleChoiceField(choices=[(1,‘sh’),(2,‘bj’)])
user = forms.CharField(max_length=18,min_lenth=6,required=True)
pwd = forms.CharField(required=True,error_message={
‘required’:‘密码不能为空’,},widget=forms.PasswordInput()
label=‘密码’,initial=‘初始值’)
age = forms.IntegerField(required=True,error_message={
‘invalid’:‘格式错误必须为数字’,})
email= forms.EmailField(required=True)
f = Form1(request.POST)
if f.is_valid():
print(f.cleaned_data)
else:
print(f.errors)
f.errors.username
序列化
from django.core import serializers
ret = models.BookType.objects.all()
data = serializers.serialize(“json”, ret)
上传文件
方式一:
obj = request.FILES.get(‘img’)
f.open(obj.name,‘wb’)
for chunk in obj.chunks():
f.write(chunk)
f.close()
# .read():从文件中读取整个上传的数据,这个方法只适合小文件
# .chunks():按块返回文件,通过在for循环中进行迭代,可以将大文件按块写入到服务器中
# .multiple_chunks()根据myFile的大小,返回True或者False,当myFile文件大于2.5M,True
# .name:这是一个属性
# .size:这也是一个属性
models上传:
class UserModel(models.Model):
name = models.Charfield(max_length=16)
icon = models.ImageField(upload_to=‘icon/%Y/%m/%d’) # upload_to相当于媒体文件MEDIA_ROOT根目录
MEDIA_ROOT = os.path.join(BASE_DIR, ‘upload’)
if request.method == ‘POST’:
username = request.POST.get(‘username’)
icon = request.FILES.get(‘icon’)
user = UserModel()
user.username = username
user.icon = icon
user.save()
print(user.icon.url)
Form组件上传:
class UserForm(forms.Form):
user = forms.CharField()
img = forms.FileField()
if request.method == “POST”:
obj = UserForm(request.POST,request.FILES)
if obj.is_valid():
user = obj.cleaned_data[‘user’]
img = obj.cleaned_data[‘img’]
f = open(img.name,‘wb’)
for line in img.chunks():
f.write(line)
f.close()
Ajax上传:
验证码
pip install Pillow
pip install django-simple-captcha
url(r’^captcha/’, include(‘captcha.urls’)),
from django import forms
from captcha.fields import CaptchaField
class CaptchaForm(forms.Form):
captcha = CaptchaField(label=u"验证码")
{ { captcha }}
{% if captcha_error %}
form = CaptchaForm(request.POST)
if form.is_valid():
pass
else:
ret[‘captcha_error’] = “验证码错误”
success_flag = False
ret[‘captcha’] = CaptchaForm()
xadmin(第三方后台管理)
'xadmin',#settings中INSTALLED_APPS添加
'crispy_forms',#INSTALLED_APPS添加添加
xadmin sites.py 中 注释sys.setdefaultencoding("utf-8")
url(r'^xadmin/', xadmin.site.urls)
import xadmin
from app import models
class BannerAdmin(object):
list_display = ['title','image','url','index','add_time'] 设置数据表在后台显示的字段
search_fields = ['title','image','url','index'] 设置在后台可以搜素的字段
list_filter = ['title','image','url','index','add_time'] 设置在后台可以通过条件帅选查看的字段
list_filter = ['course__name', 'name', 'add_time'] course__name 表示通过course外键字段查询关联表里的name字段
xadmin.site.register(Banner,BannerAdmin) 将制定表注册到xadmin后台
from xadmin import views
class BaseSetting(object):
enable_themes = True
use_bootswatch = True
xadmin.site.register(views.BaseAdminView,BaseSetting)
class GlobalSettings(object): # 头部系统名称和底部版权管理器
site_title = '玉秀管理系统' # 头部系统名称
site_footer = '玉秀管理系统,玉秀公司版权所有' # 底部版权
menu_style = 'accordion' # 设置数据管理导航折叠,以每一个app为一个折叠框
# 设置models的全局图标
global_search_models = [UserProfile, Sports]
global_models_icon = {
UserProfile: "glyphicon glyphicon-user", Sports: "fa fa-cloud" }
xadmin.site.register(views.CommAdminView, GlobalSettings) # 头部系统名称和底部版权管理器绑定views.CommAdminView注册
1.在当前app目录下的apps.py文件里配置后台要显示的中文名称
from django.apps import AppConfig
class AppCoursesConfig(AppConfig):
name = 'app_courses' # 当前app名称
verbose_name = '课程管理' # 要设置的中文名称
2.在当前app目录下的__init__.py文件里应用app中文名称设置类的路径
default_app_config = app中文名称设置类的路径,从app开始到类
default_app_config = 'app_courses.apps.AppCoursesConfig'
Xadmin集成富文本框(DjangoUeditor3)
首先安装DjangoUeditor3模块
os.path.join(BASE_DIR,‘extra_apps’)
将DjangoUeditor文件夹,整个文件夹复制到Xadmin同级目录
安装好后在settings.py将DjangoUeditor添加到app
url(r’^ueditor/’,include(‘DjangoUeditor.urls’ ))
在models.py文件,在要使用富文本框的字段使用UEditorField
from DjangoUeditor.models import UEditorField
class Course(models.Model):
name = models.CharField(max_length=50, verbose_name=‘课程名称’)
desc = models.CharField(max_length=300, verbose_name=‘课程描述’)
detail = UEditorField(verbose_name=‘内容’,
width=900,height=300,
imagePath=“neird/tup/”,
filePath=“neird/wjian/”,
default=’’,
toolbars=‘mini’)
在adminx.py文件里找到对应的数据表管理器,在管理器里指定字段用富文本框
style_fields = {‘字段名称’:‘ueditor’}指定字段使用富文本框
发送邮件
#这一项是固定的
EMAIL_BACKEND = ‘django.core.mail.backends.smtp.EmailBackend’
EMAIL_HOST = ‘smtp.163.com’
EMAIL_PORT = 465
EMAIL_USE_SSL = True
#发送邮件的邮箱
EMAIL_HOST_USER = ‘[email protected]’
#在邮箱中设置的客户端授权密码
EMAIL_HOST_PASSWORD = ‘xxx’
#收件人看到的发件人 <此处要和发送邮件的邮箱相同>
EMAIL_FROM = ‘[email protected]’
from django.core.mail import send_mail
send_mail(email_title,email_body,settings.EMAIL_FROM,[email])
import smtplib
from email.mime.text import MIMEText
mail_server = ‘smtp.qq.com’
mail_username = ‘[email protected]’
mail_password = ‘fxtlwernbugpbadd’
content = ‘QQ:1337983798’
‘微信:18438603979’
message = MIMEText(content)
message[‘Subject’] = ‘联系方式邮件’
message[‘From’] = mail_username
mail = smtplib.SMTP(mail_server)
mail.login(mail_username, mail_password)
to = user
mail.sendmail(mail_username, to, message.as_string())
mail.quit()
用户激活
from random import Random # 导入随机函数
from django.core.mail import send_mail # 导入django邮件函数
from app_users.models import Email # 导入激活操作数据库表
from MxOnline.settings import DEFAULT_FROM_EMAIL
def random_str(randomlength=8):
“”"
循环获取随机字符串,默认8位
“”"
str = ‘’
chars = ‘AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789’
length = len(chars) - 1
random = Random()
for i in range(randomlength):
str+=chars[random.randint(0, length)]
return str
def send_register_email(email, send_type=“register”):
“”"
发送邮件
:接收两个参数:
:第一个验证邮箱,第二个验证类型
“”"
“”“写入数据库验证信息”""
email_record = Email() # 实例化数据库表
if send_type == “update_email”:
code = random_str(4) # 生成4位随机数
else:
code = random_str(16) # 生成16位随机数
email_record.code = code # 数据库写入验证随机数
email_record.email = email # 数据库写入验证邮箱
email_record.send_type = send_type # 数据库写入验证类型
email_record.save()
"""发送验证邮件"""
email_title = "" # 记录邮件标题
email_body = "" # 记录邮件内容
if send_type == "register":
email_title = "慕学在线网注册激活链接"
email_body = "请点击下面的链接激活你的账号: http://127.0.0.1:8000/active/{0}".format(code)
send_status = send_mail(email_title, email_body, DEFAULT_FROM_EMAIL, [email])
if send_status:
pass
elif send_type == "forget":
email_title = "慕学在线网注册密码重置链接"
email_body = "请点击下面的链接重置密码: http://127.0.0.1:8000/reset/{0}".format(code)
send_status = send_mail(email_title, email_body, DEFAULT_FROM_EMAIL, [email])
if send_status:
pass
elif send_type == "update_email":
email_title = "慕学在线邮箱修改验证码"
email_body = "你的邮箱验证码为: {0}".format(code)
send_status = send_mail(email_title, email_body, DEFAULT_FROM_EMAIL, [email])
if send_status:
pass
2.设置激活连接逻辑
url(r’^active/(?P
class active_code(View):
def get(self, request, active_de):
yanzh_email = Email.objects.filter(code=active_de)
if yanzh_email:
for record in yanzh_email:
email = record.email
Users.objects.filter(username=email).update(is_active=True)
Email.objects.filter(code=active_de).delete()
return render(request, ‘login.html’)
media保存上传文件(不存储在数据库)
MEDIA_URL = ‘/media/’ # setting 设置媒体文件的相对路径
MEDIA_ROOT = os.path.join(BASE_DIR, ‘media’) # setting 设置媒体文件的绝对路径
‘django.template.context_processors.media’, # setting TEMPLATES添加
img = models.ImageField(upload_to=‘user/image/%Y/%m’) #model media/user/image/%Y/%m
#url 处理Django静态文件
from django.views.static import serve
url(r’^media/(?P .*)$’, serve, {‘document_root’: MEDIA_ROOT}),
markdown
import markdown
from django.shortcuts import render, get_object_or_404
from .models import Post
def detail(request, pk):
post = get_object_or_404(Post, pk=pk)
# 记得在顶部引入 markdown 模块
post.body = markdown.markdown(post.body,
extensions=[
‘markdown.extensions.extra’,
‘markdown.extensions.codehilite’,
‘markdown.extensions.toc’,
])
return render(request, ‘blog/detail.html’, context={‘post’: post}) # { { post.body|safe }}
## 我是标题一
这是标题一下的正文
## 标题二
这是标题二下的正文
### 我是标题二下的子标题
这是标题二下的子标题的正文
## 我是标题三
这是标题三下的正文
中间件
-------------------------------------Flask--------------------------------------------------------