认证相关
- 7 认证相关
- 今日详细
- 1. 代码整合
- 2.通用认证组件
- 2.1 处理访问记录
- 2.2 登录之后才具有评论和发布
- 3.随意的接口
- 结论:在serializer中可以调用request
- 4.完善详细页面
- 总结
- 1. 小程序
- 1.1 申请账号APPID
- 1.2 搭建开发者工具
- 1.3 目录结构
- 1.4 组件
- 1.5 微信API
- 1.6 事件
- 1.7 双向绑定 mvvm
- 1.8 指令
- 1.9 自定义tabbar
- 2.API(DRF)
- 2.1 视图
- 2.2 序列化器
- 2.2.1 校验
- 2.2.2 序列化
- 2.3 认证
- 2.4 状态码
- 3.其他
7 认证相关
各位小伙伴想要博客相关资料的话关注公众号:chuanyeTry即可领取相关资料!
认证结合之后的效果:
- 发布页:未登录,点发布跳转到登录页面。
- 首页:不用登录
- 详细页面:不用登录、如果登录就需要在访问记录中添加一条数据。
- 评论,跳转到登录页面
- 点赞,跳转到登录页面
- 个人中心,无需登录
- 登录页面,无需登录
今日详细
1. 代码整合
登录成功之后保存 nickname和avatar
2.通用认证组件
request.user
- None,未登录
- 不为空,用户对象
2.1 处理访问记录
【demos - 4 - 认证组件.zip】
【demo - 4 - 认证组件.zip】
2.2 登录之后才具有评论和发布
-
小程序
- 按钮点击的时候先做判断?
- 自定义tabbar
- 携带token
- url
- header
- Authorization: token asdfauposdifuaskjdfpoaiusdfj
-
api
-
两个认证类
-
应用场景:
-
都不需要登录视图
-
都需要认证的视图
-
有的需要&有的不需要(自定义get_authenticators)
class CommentView(APIView):def get_authenticators(self):if self.request.method == 'POST':return [UserAuthentication(), ]return [GeneralAuthentication(), ]def get(self,request,*args,**kwargs):root_id = request.query_params.get('root')# 1. 获取这个根评论的所有子孙评论node_queryset = models.CommentRecord.objects.filter(root_id=root_id).order_by('id')# 2. 序列化ser = CommentModelSerializer(instance=node_queryset,many=True)return Response(ser.data,status=status.HTTP_200_OK)def post(self,request,*args,**kwargs):# 1. 进行数据校验: news/depth/reply/content/rootser = CreateCommentModelSerializer(data=request.data)if ser.is_valid():# 保存到数据库ser.save(user_id=1)# 对新增到的数据值进行序列化(数据格式需要调整)news_id = ser.data.get('news')models.News.objects.filter(id=news_id).update(comment_count=F('comment_count')+1)return Response(ser.data,status=status.HTTP_201_CREATED)return Response(ser.errors,status=status.HTTP_400_BAD_REQUEST)
-
-
3.随意的接口
结论:在serializer中可以调用request
class TestSER(serializers.ModelSerializer):xx = serializers.SerializerMethodField()class Meta:model = models.Topicfields = "__all__"def get_xx(self,obj):# 获取request 、 request.userself.context['request'].userreturn 123class TestView(ListAPIView):queryset = models.Topic.objectsserializer_class = TestSER
4.完善详细页面
- 点赞
总结
1. 小程序
1.1 申请账号APPID
1.2 搭建开发者工具
1.3 目录结构
小程序文件的目录结构
- config
- api.js
- settings.js
- components
- pages
- index
- index.js
- index.wxml
- index.wxss
- index.json
- index
- utils
- static
- app.js
- app.json
- app.wxss
1.4 组件
- view/text/image
- textarea/navigator/input/button
- block/cover-view/cover-image/swiper
1.5 微信API
- request/navigateto/back/switchtab/chooseimage/chooseloacation
- getUserInfo + button + opensetting
- showToast/showloading/hideloadding
- setstoragesync/setstoreagesync
- getApp/ getcurrenpages
1.6 事件
- 自定义事件
- bindtab
- bindinput
- onload/onshow/onread/onunload/onhide/onpulldownrefresh/onreachbuttom/onshareappmessage
- onlunch
1.7 双向绑定 mvvm
-
setData全部
-
setData局部
setData({['xx.xx.xx.x']:123 })
var v1 = 1; var v2 = 2; var v3 =v1+v2; setData({['xx.xx['+ v3 +']x']:123 })
1.8 指令
- for
- if
1.9 自定义tabbar
2.API(DRF)
2.1 视图
-
APIView
-
ListAPIView…
-
视图中自定义方法
-
选择serializer
class TestView(ListAPIView,CreateAPIView):queryset = models.Topic.objectsserializer_class = TestSERdef get_serializer_class(self):if self.request.method == "GET":return TestSERreturn TestSER
-
选择authenticator
class TestView(ListAPIView,CreateAPIView):queryset = models.Topic.objectsserializer_class = TestSERdef get_authenticators(self):if self.request.method == "GET":return [UserAuthentication(), ]return [GeneralAuthentication(), ]
-
自定义视图函数
class TestView(ListAPIView,CreateAPIView):queryset = models.Topic.objectsserializer_class = TestSERdef get(self,request,*args,**kwargs):response = super().get(request,*args,**kwargs)return response
-
自定义filter做筛选(maxid/minid)
-
2.2 序列化器
他有两个作用:序列化、校验。
2.2.1 校验
class TestSER(serializers.ModelSerializer):class Meta:model = models.Topicfields = "__all__"
is_valid
-
自定义校验规则
import re from rest_framework.exceptions import ValidationErrordef phone_validator(value):if not re.match(r"^(1[3|4|5|6|7|8|9])\d{9}$",value):raise ValidationError('手机格式错误')class TestSER(serializers.ModelSerializer):title = serializers.CharField(label='手机号',validators=[phone_validator,])class Meta:model = models.Topicfields = "__all__"
-
自定义方法校验
class TestSER(serializers.ModelSerializer):title = serializers.CharField(label='手机号')class Meta:model = models.Topicfields = "__all__"def validate_title(self, value):# 具体的校验规则return value
-
嵌套校验
class CreateNewsTopicModelSerializer(serializers.Serializer):key = serializers.CharField()cos_path = serializers.CharField()class CreateNewsModelSerializer(serializers.ModelSerializer):imageList = CreateNewsTopicModelSerializer(many=True)class Meta:model = models.Newsexclude = ['user', 'viewer_count', 'comment_count',"favor_count"]def create(self, validated_data):# 把imageList切走image_list = validated_data.pop('imageList')# 创建New表中的数据news_object = models.News.objects.create(**validated_data)data_list = models.NewsDetail.objects.bulk_create([models.NewsDetail(**info, news=news_object) for info in image_list])news_object.imageList = data_listif news_object.topic:news_object.topic.count += 1news_object.save()return news_object
-
注意事项:如果定义的字段指向做序列化不做校验。
class TestSER(serializers.ModelSerializer):title = serializers.CharField(label='手机号',read_only=True)class Meta:model = models.Topicfields = "__all__"
2.2.2 序列化
class TestSER(serializers.ModelSerializer):class Meta:model = models.Topicfields = "__all__"
-
自定义字段+source
class TestSER(serializers.ModelSerializer):v1 = serializers.CharField(label='手机号',source='get_gender_display')class Meta:model = models.Topicfields = "__all__"
-
自定义时间字段
class TestSER(serializers.ModelSerializer):v1 = serializers.DateTimeField(format="%Y")class Meta:model = models.Topicfields = "__all__"
-
复杂操作字段
class NewsDetailModelSerializer(serializers.ModelSerializer):images = serializers.SerializerMethodField()create_date = serializers.DateTimeField(format="%Y-%m-%d %H:%M")user = serializers.SerializerMethodField()topic = serializers.SerializerMethodField()viewer = serializers.SerializerMethodField()comment = serializers.SerializerMethodField()is_favor = serializers.SerializerMethodField()class Meta:model = models.Newsexclude = ['cover',]def get_images(self,obj):detail_queryset = models.NewsDetail.objects.filter(news=obj)# return [row.cos_path for row in detail_queryset]# return [{'id':row.id,'path':row.cos_path} for row in detail_queryset]return [model_to_dict(row,['id','cos_path']) for row in detail_queryset]def get_user(self, obj):return model_to_dict(obj.user, fields=['id', 'nickname', 'avatar'])def get_topic(self, obj):if not obj.topic:returnreturn model_to_dict(obj.topic, fields=['id', 'title'])def get_viewer(self,obj):# 根据新闻的对象 obj(news)# viewer_queryset = models.ViewerRecord.objects.filter(news_id=obj.id).order_by('-id')[0:10]queryset = models.ViewerRecord.objects.filter(news_id=obj.id)viewer_object_list = queryset.order_by('-id')[0:10]context = {'count':queryset.count(),'result': [model_to_dict(row.user,['nickname','avatar']) for row in viewer_object_list]}return contextdef get_comment(self,obj):"""获取所有的1级评论,再给每个1级评论获取一个耳机评论。:param obj::return:"""# 1.获取所有的 一级 评论first_queryset = models.CommentRecord.objects.filter(news=obj,depth=1).order_by('id')[0:10].values('id','content','depth','user__nickname','user__avatar','create_date')first_id_list = [ item['id'] for item in first_queryset]# 2.获取所有的二级评论# second_queryset = models.CommentRecord.objects.filter(news=obj,depth=2)# 2. 获取所有1级评论下的二级评论# second_queryset = models.CommentRecord.objects.filter(news=obj, depth=2,reply_id__in=first_id_list)# 2. 获取所有1级评论下的二级评论(每个二级评论只取最新的一条)from django.db.models import Maxresult = models.CommentRecord.objects.filter(news=obj, depth=2, reply_id__in=first_id_list).values('reply_id').annotate(max_id=Max('id'))second_id_list = [item['max_id'] for item in result] # 5, 8second_queryset = models.CommentRecord.objects.filter(id__in=second_id_list).values('id','content','depth','user__nickname','user__avatar','create_date','reply_id','reply__user__nickname')import collectionsfirst_dict = collections.OrderedDict()for item in first_queryset:item['create_date'] = item['create_date'].strftime('%Y-%m-%d')first_dict[item['id']] = itemfor node in second_queryset:first_dict[node['reply_id']]['child'] = [node,]return first_dict.values()def get_is_favor(self,obj):# 1. 用户未登录user_object = self.context['request'].userif not user_object:return False# 2. 用户已登录exists = models.NewsFavorRecord.objects.filter(user=user_object,news=obj).exists()return exists
注意:序列化的方法中获取request
class TestSER(serializers.ModelSerializer):title = serializers.SerializerMethodField()class Meta:model = models.Topicfields = "__all__"def get_title(self,obj):request = self.context['request']
2.3 认证
-
编写
from rest_framework.authentication import BaseAuthentication from api import models from rest_framework import exceptionsclass GeneralAuthentication(BaseAuthentication):"""通用认证,如果认证功能则返回数据,认证失败自己不处理,交给下一个认证组件处理。"""def authenticate(self, request):token = request.META.get('HTTP_AUTHORIZATION', None)# 1.如果用户没有提供token,返回None(我不处理,交给下一个认证类处理,则默认是None)if not token:return None# 2.token错误,,返回None(我不处理,交给下一个认证类处理,则默认是None)user_object = models.UserInfo.objects.filter(token=token).first()if not user_object:return None# 3.认证成功return (user_object,token) # request.user/request.authclass UserAuthentication(BaseAuthentication):"""用户认证,用户必须先登录。"""def authenticate(self, request):token = request.META.get('HTTP_AUTHORIZATION', None)# 1.如果用户没有提供token,返回None(我不处理,交给下一个认证类处理,则默认是None)if not token:raise exceptions.AuthenticationFailed()# 2.token错误,,返回None(我不处理,交给下一个认证类处理,则默认是None)user_object = models.UserInfo.objects.filter(token=token).first()if not user_object:raise exceptions.AuthenticationFailed()# 3.认证成功return (user_object,token) # request.user/request.auth
-
应用认证类
-
全不需要登录
-
全需要登录
-
部分需要登录,重写方法
class CommentView(APIView):def get_authenticators(self):if self.request.method == 'POST':return [UserAuthentication(), ]return [GeneralAuthentication(), ]def get(self,request,*args,**kwargs):root_id = request.query_params.get('root')# 1. 获取这个根评论的所有子孙评论node_queryset = models.CommentRecord.objects.filter(root_id=root_id).order_by('id')# 2. 序列化ser = CommentModelSerializer(instance=node_queryset,many=True)return Response(ser.data,status=status.HTTP_200_OK)def post(self,request,*args,**kwargs):# 1. 进行数据校验: news/depth/reply/content/rootser = CreateCommentModelSerializer(data=request.data)if ser.is_valid():# 保存到数据库ser.save(user_id=1)# 对新增到的数据值进行序列化(数据格式需要调整)news_id = ser.data.get('news')models.News.objects.filter(id=news_id).update(comment_count=F('comment_count')+1)return Response(ser.data,status=status.HTTP_201_CREATED)return Response(ser.errors,status=status.HTTP_400_BAD_REQUEST)
-
2.4 状态码
from rest_framework import status例如:Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
3.其他
-
js文件导入
-
三元运算
条件 ? 真 : 假
-
js闭包
-
自执行函数
-
this 和 箭头函数(es6)
-
django orm
-
F
-
分组
-
排序
-
bluk_create
result1 = models.UserInfo.objects.create(**{}) result2 = models.UserInfo.objects.create(**{})print(result1.id,result1.name,result2.id,result2.name,)data = models.UserInfo.objects.blukcreate([models.UserInfo(...),models.UserInfo(...) ]) data[0].name/title/email/ -> id
-
get_or_create
-
自关联(related_name)
-
-
基于Token做的认证、jwt
-
腾讯对象存储 COS
-
腾讯短信API
-
django中编写离线脚本
import os import sys import djangobase_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(base_dir)# 将配置文件的路径写到 DJANGO_SETTINGS_MODULE 环境变量中 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "demos.settings") django.setup()from api import models models.Topic.objects.create(title="春运") models.Topic.objects.create(title="火车票")
注意:可以结合定时任务。