Django命令
版本号 | python -m django --version |
---|---|
创建项目 | django-admin startproject mysite(项目名称) |
创建子项目(要进到项目中) | python manage.py startapp user(子应用名称) |
启动项目 | python manage.py runserver 127.0.0.1:8005(ip:端口)可不写 |
创建超级用户 | python manage.py createsuperuser |
setting.py为配置文件,需要修改语言,时区
修改语言:
*#语言英语——》汉语en-us——**》*zh-Hans
LANGUAGE_CODE='zh-Hans'
修改时区:
时区UTC(格林时区,比我们的时间早八小时)——>Asia-Shanghai**(中国上海)*
TIME_ZONE='Asia/Shanghai'
修改时区将此改为False
USE_TZ=False
配置html模板
'DIRS':[os.path.join(BASE_DIR,'templates')]
配置允许访问ip
ALLOWED_HOSTS=['*']
迁移数据库
python manage.py makemigrations # (生成脚本)
python manage.py migrate # (创建)
Django常用模块
from django.shortcuts import render,HttpResponse,redirect,reverse#视图文件常规使用的方法
from django.contrib.auth.hashers import make_password,check_password#密码加密与解密
from django.views import View#使用类视图,导包
from django.http import JsonResponse#返回一个json回响
from django.conf import settings#导入配置文件
from django.core.mail import send_mail#发送邮件导包
from django.contrib import admin#后台管理系统
from django.urls import path,include,re_path#路由的配置,include设置二级路由,re_path正则路由
import pymysql
pymysql.install_as_MySQLdb()#用于主文件下的init中,防止数据库错误
from itsdangerous import TimedJSONWebSignatureSerializer as encrypt #接口加密模块
from django.core.paginator import Paginator #分页器
from rest_framework import serializers #序列化
from rest_framework.views import APIView #跨域接口(用于类继承)
Django发邮件
配置文件 settings
# 发送邮件配置
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.163.com' # 发送邮件的服务器
EMAIL_PORT = 25 # 发送邮件的端口号
# 发送邮件到邮箱
EMAIL_HOST_USER = 'liujunjie_j@163.com' # 发件人 用户名
# 在邮箱中设置客户到授权密码
EMAIL_HOST_PASSWORD = 'abc123' # 发件人密码
# 收件人看到到发件人
EMAIL_FORM = '天天生鲜<liujunjie_j@163.com>'
代码
# 导包
from django.core.mail import send_mail
# 代码
def getcode(request):
email = request.POST.get('email')
# 定义验证码的备选值
str = '1234567890QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm' # 随机选取4个值作为验证码
rand_str = ''
for i in range(0, 4):
rand_str += str[random.randrange(0, len(str))]
request.session['code'] = rand_str
# 3、发送邮件
标题
title = '美多商城-用户注册'
内容
content = '您的注册码是:{}'.format(send_str)
发件人
sender = settings.EMAIL_FORM
收件人列表
email_list = [email]
send_mail(title,content,sender,email_list)
send_mail(subject, settings.EMAIL_FORM,to_list, html_message=message)
d = {
'code': 200,
'message': '邮件发送成功'
}
return JsonResponse(d)
存储cookie,session,浏览器存储
Cookie、Session
存储session:request.session['name']=a.name
读取session:name=request.session.get('name')
存储cookie:
创建cookie
res=HttpResponse('ok')
res.set_cookie('user','zhangsan')
return res
获取cookie
a=request.COOKIES.get('user')
删除cookie
res=HttpResponse('ok')
res.delete_cookie('user')
return res
浏览器存储
#存储session是在服务器上,由于项目是多台服务器,存储session在另外的服务器无法识别,
#此时不需要再存储session,而是发送一个加密的数据,验证是否登录解析一下字符串就可以了
#user不可直接转换成json字符串,用序列化类
ser=myserializers.UserModelSerializer(user,many=False) 数据
token_obj=encrypt(settings.SECRET_KEY,3600) 加密方式
token=token_obj.dumps(ser.data).decode() 将数据进行加密然后传输到浏览器
d['message']=token
return JsonResponse(d)
把后端传的值存储到浏览器中,在需要验证操作时
sessionStorage.setItem('token',res.data.message); sessionStorage(会话存储,有时限)
sessionStorage.setItem('username',res.data.username);
localStorage.setItem('token',res.data.message) localStorage(永久存储,不删除就一直存在)
将信息取出传入到后端进行解密判断
var token = sessionStorage.getItem('token')
关联数据库增删改查
增
# 方法一
S = models.School()
S.属性(字段名) = '数据'
S.save()
# 方法二
models.School.objects.create(属性='值')
查:惰性查询
与缓存机制
配合
Django的查询为惰性查询,查询出的结果如果未使用,则没有真正的查询数据库的数据,只是生成出一个查询条件或类
缓存机制:在第一次查询后会缓存,第二次就不用再查询数据库
# 查所有数据
s=models.School.objects.filter()#1
s=models.School.objects.all()#2
for i in s:
print(i)
# 条件查询
s=models.School.objects.filter(name='郑州工程').first()#查一个
s=models.School.objects.get(id=2)#根据id查,若id不存在会报错
s=models.School.objects.filter(name='郑州工程').all()#查多个
for i in s:
print(i)
# 连表查询
# 查询积云教育下的班级
g=models.Grade.objects.filter(school__name='积云教育')
# 查询小红属于哪个班
g=models.Grade.objects.filter(student__name='小红')
# 查询小黑属于哪个学校
s=models.School.objects.filter(grade__student__name='小黑').first()
# 查询积云教育下所有的学生
s=models.Student.objects.filter(grade__school__name='积云教育')
# 查询1903A下的学生
s=models.Student.objects.filter(grade__name='1903A')
g=models.Grade.objects.filter(name='1903A').first()
for i in g.student_set.all():#此为grade下的隐藏属性
print(i)
# 排序:
book_list=models.Books.objects.order_by('-create_time').all() # 加负号为倒序
book_list=models.Books.objects.order_by('create_time').all() # 不加负号为正序
改
s=models.School.objects.filter(name='郑州工程').first() # 修改1
s.name='郑州01'
s.save()
models.School.objects.filter(name='郑州01').update(name='郑州大学') # 修改2
#批量修改
models.School.objects.filter(name='北京吉利').update(name='北京大学')
删
s=models.School.objects.filter(name='郑州大学').first()
s.delete()
#批量删除
models.School.objects.filter(name='北京大学').delete()
原生SQL语句(raw
)
goods=models.Goods.objects.raw('select * from goods')
一对多(ForeignKey()
,on_delete
)
auth和books两个表,外键在books中,此时auth有隐藏属性:books_set.all()可以查询作者所有书籍
外键属性:on_delete不可缺少属性
on_delete=models.CASCADE 此时删除主键时,外键的数据也会删除
on_delete=models.SET_NULL 此时删除主键时,外键的数据不会删除,但外键变为空。若用此字段,需要加上null=True
多对多创建
Flask
的多对多关系可以跟着数据一起添加(append
)
Django必须先有此数据,然后才可以添加(add)多对多关系,manytomany
系统会自动生成一个关系表
第一种:(ManyToManyField()
)
Demo:movies和actor,多对多外键在movies中为 actor=models.ManyToManyField(Actor)
movies.actor.all() | 此电影所有的演员 |
---|---|
movies.actor.add(a) | 添加单个演员 |
movies.actor.set(list) | 一次添加多个演员 |
actor.movies_set.all() | 该演员出演的所有电影(隐藏属性) |
第二种:手动创建关系表
class Movies_Actor_Relationship(models.Model):
movies = models.ForeignKey(Movies,on_delete=models.CASCADE)
actor = models.ForeignKey(Actor,on_delete=models.CASCADE)
多对多添加关系
第一种 单个添加
for i in cid:
s = models.SmallCate.objects.filter(pk=i).first()
goods.cate_list.add(s)
第二种 批量添加
s=models.SmallCate.objects.filter(id__in=cid)
goods.cate_list.set(s)
多对多查询
#第一种、单表内的隐藏属性找结果
#速度与激情的演员
#a=models.Actor.objects.filter(movies_actor_relationship__movies__name='速度与激情')
#for i in a:
#print(i.name)
#本山出演的电影
#m=models.Movies.objects.filter(movies_actor_relationship__actor__name='本山')
#for i in m:
# print(i.name)
#第二种、在关系表中添加方法输出结果
#猫和老鼠的演员
#a=models.Movies_Actor_Relationship.objects.filter(movies__name='猫和老鼠')
#for i in a:
#print(i.actors_name())
#赵四演的电影
#a=models.Movies_Actor_Relationship.objects.filter(actor__name='赵四')
#for i in a:
#print(i.movies_name())
枚举类型
STATUS_CHOICE=(
(1,'待付款'),
(2,'运输中'),
(3,'待评价'),
(4,'已完成')
)
# 字段
status=models.IntegerField(choices=STATUS_CHOICE,default=1) # 订单状态
建表:class Meta
中的字段
抽象类(不会真正的创建此表)abstract=True
表名称db_table='admin'
在django后台管理中的表名称verbose_name_plural='用户表'
数据添加时间auto_now_add = True
实时修改时间 auto_now = True
公开文件夹
settings中:UPLOAD_DIRS = os.path.join(BASE_DIR,'upload') # 公开upload文件夹,允许外界访问
主urls中:
from django.views.static import serve
from django.conf import settings
第一种:path('upload/<path>/',serve,{'document_root':settings.UPLOAD_DIRS})
第二种:re_path('upload/(.*)',serve,{'document_root':settings.UPLOAD_DIRS})
接口发送数据加密
#导包
from itsdangerous import TimedJSONWebSignatureSerializer as encrypt,SignatureExpired
#加密
token_obj=encrypt(settings.SECRET_KEY,3600)#参数1:一个密匙参数二:时间限制(s)
token_str=token_obj.dumps(user_obj).decode()
content="<ahref='http://127.0.0.1:8000/api/active/"+token_str+"'>激活</a>"
#解密
try:
token_obj=encrypt(settings.SECRET_KEY,3600)
user_obj=token_obj.loads(username)
username=user_obj['username']
except SignatureExpired as ex: #排除异常:身份过期报错
d['code']=500
d['message']='身份已过期'
return JsonResponse(d)
#认证类判断是否登录,BaseAuthentication认证类
# from rest_framework.authentication import BaseAuthentication
class MyAuth(BaseAuthentication):
def authenticate(self,request):
token=request._request.META.get('HTTP_AUTHORIZATION')
try:
# itsdangerous的加密模块
ser=TimedJSONWebSignatureSerializer(settings.SECRET_KEY,3600)
user=ser.loads(token)
return (user,token)
# return的值对应的是user与auther user代表元组第一位(user),auther为第二位(token)
except Exceptionasex:
raise exceptions.AuthenticationFailed('身份令牌不可用')
#exceptions异常 ,from rest_framework import exceptions
# 添加到购物车
class AddCart(APIView):
# 认证类的使用方式
authentication_classes=[MyAuth]
def get(self,request):
pass
序列化
1、导入序列化模块
from rest_framework import serializers
2、创建序列化类
# 第一种
class GoodsModelSerializer(serializers.ModelSerializer):
class Meta:
model = models.Goods
fields = '__all__' 表示goods表所有字段
# depth=1 若有外键,此时也可以展示外键信息,但是此表必须为创建了外键字段的表
# 第二种 自定义
class ShowCartModelSerializer(serializers.ModelSerializer):
#外键所有的序列化,此序列化类可以展示对应goods的所有字段
#goods=GoodsModelSerializer(many=True)
# source作用为使关联的外键字段都变为此序列化的字段,此序列化类现在可以展示其外键对应的goods的name等字段
is_checked=serializers.BooleanField(default=True)
name=serializers.CharField(source='goods.name')
image=serializers.CharField(source='goods.image_url') price=serializers.DecimalField(source='goods.price',max_digits=10,
decimal_places=2,default=99999999.99)
class Meta:
model=models.Cart
fields='__all__'
3、使用序列化
# 将表信息变为可Json类型,
carts=models.Cart.objects.filter(id__in=ids)
cart_list=myserializers.ShowCartModelSerializer(carts,many=True) # 若为多条信息,需添加many=True默认False
# 将接收的数据直接添加到数据库中
cart=myserializers.CartModelSerializer(data=request.data) # 此时接受的数据的键必须跟数据库字段名一致
cart.is_valid() #判断是否添加成功
if cart.is_valid():
cart.save() # 保存数据
# 修改数据库中的数据
# 1、查询到该数据,必须保证有数据,否则报错
c=models.Cart.objects.filter(goods_id=goods,user_id=user).first()
# 2、序列化修改
cart=myserializers.CartModelSerializer(c,data=request.data)
# 3、保存
if cart.is_valid(): # 若信息可以写入到数据库
cart.save() # 保存数据
前后端交互分页(Django+Vue)
django中
goods=models.Goods.objects.all()
paginator=Paginator(goods,2) # 先用分页器将数据分开
p=request.data.get('p',1)
page=paginator.page(p) # 用axios从前端传入页码
totalpages=paginator.num_pages
goodslist=myserializer.GoodsModelSerializer(page,many=True) # 用序列化器将数据序列化
return JsonResponse({'code':200,'goodslist':goodslist.data,
'totalpages':totalpages}) # 返回当前页数据和总页数
Vue中
javascript:return false; // 禁止超链接动作
<a href="javascript:returnfalse;" v-for="i in pages" @click="getgoods(i)">{{i}}(1,2,3…)</a>
methods:{
getgoods:function(i){
this.axios({
url:'/api/api/showgoods/',
method:'post',
data:{'p':i}
}).then((res)=>{
this.goodslist=res.data.goodslist;
this.p=i
}).catch((err)=>{
console.log(err)
})
}
}