一. Vue+Django基础项目知识点
1. vue+django 跨域的问题解决
https://www.cnblogs.com/lovershowtime/p/11572569.html 跨域知识点
在后台 解决跨域问题 使用中间件 作用全局
cors.py
class MiddlewareMixin(object): def __init__(self, get_response=None): self.get_response = get_response super(MiddlewareMixin, self).__init__() def __call__(self, request): response = None if hasattr(self, 'process_request'): response = self.process_request(request) if not response: response = self.get_response(request) if hasattr(self, 'process_response'): response = self.process_response(request, response) return response class CORSMiddleware(MiddlewareMixin): def process_response(self,request,response): # 添加响应头 # 允许你的域名来获取我的数据 response['Access-Control-Allow-Origin'] = "*" # 允许你携带Content-Type请求头 response['Access-Control-Allow-Headers'] = "Content-Type" # 允许你发送DELETE,PUT response['Access-Control-Allow-Methods'] = "DELETE,PUT" return response
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', 'api.cors.CORSMiddleware', ]
请求和 ------复杂请求跨域(预检)
https://www.cnblogs.com/2017Python/articles/7942124.html
https://www.cnblogs.com/xueheng36/p/10638384.html
中间件 cors.py
class MiddlewareMixin(object): def __init__(self, get_response=None): self.get_response = get_response super(MiddlewareMixin, self).__init__() def __call__(self, request): response = None if hasattr(self, 'process_request'): response = self.process_request(request) if not response: response = self.get_response(request) if hasattr(self, 'process_response'): response = self.process_response(request, response) return response class CORSMiddleware(MiddlewareMixin): def process_response(self,request,response): # 添加响应头 # 允许你的域名来获取我的数据 # response['Access-Control-Allow-Origin'] = "*" # 允许你携带Content-Type请求头 # response['Access-Control-Allow-Headers'] = "Content-Type" # 允许你发送DELETE,PUT # response['Access-Control-Allow-Methods'] = "DELETE,PUT" # 复杂请求 """ 这是vue前端设置的请求头 headers:{ 'Content-Type':'application/json', //复杂请求头 在后台要接收请求头 'k1':'v1' }""" response['Access-Control-Allow-Origin'] = "*" if request.method == "OPTIONS": response['Access-Control-Allow-Headers'] = "Content-Type,k1" response['Access-Control-Allow-Methods'] = "PUT,DELETE" return response
跨域:因为浏览器的同源策略,在你请求返回的时候会进行拦截 jsonp 只能发 get 请求 cors 可以发任何请求 ,在响应时加个响应头就行 同源策略对ajax阻拦 同源策略对src或href属性的不阻拦 ajax的本质: xhr = new XMLHttpRequest(); xhr.open... xhr.send(...) 解决方案: - JSONP :原理 面试必问 点击按钮: 动态添加一个 <script src='http://www.baidu.com/users/'></script> <script> function func(arg){ alert(arg) } </script> 获取数据之后要删除 script标签 <script src='http://www.baidu.com/users/'></script> - CORS - 加响应头 简单与复杂请求的区分:http://www.cnblogs.com/wupeiqi/p/5703697.html a. 简单请求 A网站: <input type="button" value="获取用户数据" onclick="getUsers()"> <script src="jquery-1.12.4.min.js"></script> <script> function getUsers() { $.ajax({ url: 'http://127.0.0.1:8000/users/', type:'GET', success:function (ret) { console.log(ret) } }) } </script> 服务商: class UsersView(views.APIView): def get(self,request,*args,**kwargs): ret = { 'code':1000, 'data':'老男孩' } response = JsonResponse(ret) response['Access-Control-Allow-Origin'] = "*" return response b. 复杂请求(性能上的损耗,options预检,真实的请求,所以要尽量避免发送复杂的请求) A网站: <input type="button" value="获取用户数据" onclick="getUsers()"> <script src="jquery-1.12.4.min.js"></script> <script> function getUsers() { $.ajax({ url: 'http://127.0.0.1:8000/users/', type:'POST', data: {'k1':'v1'}, headers:{ 'h1':'asdfasdfasdf' }, success:function (ret) { console.log(ret) } }) } </script> 服务商: class UsersView(views.APIView): def get(self,request,*args,**kwargs): ret = { 'code':1000, 'data':'老男孩' } response = JsonResponse(ret) response['Access-Control-Allow-Origin'] = "*" return response def post(self,request,*args,**kwargs): print(request.POST) ret = { 'code':1000, 'data':'老男孩' } response = JsonResponse(ret) response['Access-Control-Allow-Origin'] = "*" return response def options(self, request, *args, **kwargs): # self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com") # self.set_header('Access-Control-Allow-Headers', "k1,k2") # self.set_header('Access-Control-Allow-Methods', "PUT,DELETE") # self.set_header('Access-Control-Max-Age', 10) response = HttpResponse() response['Access-Control-Allow-Origin'] = '*' #允许的跨域名 response['Access-Control-Allow-Headers'] = 'h1' #允许的请求头 # response['Access-Control-Allow-Methods'] = 'PUT' #允许的请求方法 return response
2. 后台接口API +VUE前端(django REST framework 跨域 基础案例)
后台API:
modes from django.db import models class Course(models.Model): """ 课程表 """ title = models.CharField(verbose_name='课程名称',max_length=32) course_img = models.CharField(verbose_name='课程图片',max_length=64) level_choices = ( (1,'初级'), (2,'中级'), (3,'高级'), ) level = models.IntegerField(verbose_name='课程难易程度',choices=level_choices,default=1) def __str__(self): return self.title class CourseDetail(models.Model): """ 课程详细 """ course = models.OneToOneField(to='Course',on_delete=models.CASCADE) slogon = models.CharField(verbose_name='口号',max_length=255) why = models.CharField(verbose_name='为什么要学?',max_length=255) recommend_courses = models.ManyToManyField(verbose_name='推荐课程',to='Course',related_name='rc') # 反向关联 def __str__(self): return "课程详细:"+self.course.title class Chapter(models.Model): """ 章节 """ num = models.IntegerField(verbose_name='章节') name = models.CharField(verbose_name='章节名称',max_length=32) course = models.ForeignKey(verbose_name='所属课程',to='Course',on_delete=models.CASCADE) def __str__(self): return self.name
settings 下urls
from django.conf.urls import url,include from django.contrib import admin urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^api/(?P<version>w+)/', include('api.urls')), ]
项目下urls
from django.conf.urls import url,include from api.views import course urlpatterns = [ # """ # 方式一 比较冗余 不清晰: # url(r'^home/$', course.CourseView.as_view()), # http://127.0.0.1:8000/api/v1/home/ 获取多条数据 # url(r'^home/(?P<pk>d+)/$', course.CourseView.as_view()), # http://127.0.0.1:8000/api/v1/home/1/ 获取单条数据 # """ # 方式二 比较清晰明了 # 获取 多条数据 去list方法 # 获取单条数据 去retrieve 方法 url(r'^home/$', course.CourseView.as_view({'get':'list'})), url(r'^home/(?P<pk>d+)/$', course.CourseView.as_view({'get':'retrieve'})), # 获取 choices 中文字 url(r'^test/$', course.test), ]
解决前端vue发送请求 后端跨域----- 中间件 cors.py
class MiddlewareMixin(object): def __init__(self, get_response=None): self.get_response = get_response super(MiddlewareMixin, self).__init__() def __call__(self, request): response = None if hasattr(self, 'process_request'): response = self.process_request(request) if not response: response = self.get_response(request) if hasattr(self, 'process_response'): response = self.process_response(request, response) return response class CORSMiddleware(MiddlewareMixin): def process_response(self,request,response): # 添加响应头 # 允许你的域名来获取我的数据 response['Access-Control-Allow-Origin'] = "*" # 允许你携带Content-Type请求头 response['Access-Control-Allow-Headers'] = "Content-Type" # 允许你发送DELETE,PUT response['Access-Control-Allow-Methods'] = "DELETE,PUT" return response
settings 配置 INSTALLED_APPS = [ 'django.contrib.admin', 'rest_framework', ] MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'api.cors.CORSMiddleware', ] REST_FRAMEWORK = { 'DEFAULT_RENDERER_CLASSES':['rest_framework.renderers.JSONRenderer','rest_framework.renderers.BrowsableAPIRenderer',], 'DEFAULT_VERSIONING_CLASS':'rest_framework.versioning.URLPathVersioning', 'ALLOWED_VERSIONS':['v1','v2'], # 允许的版本 'VERSION_PARAM':'version', # 参数 'DEFAULT_VERSION':'v1', # 默认版本 }
drf 序列化---serializers/course.py from api import models from rest_framework import serializers class CourseSerializer(serializers.ModelSerializer): """ 课程序列化 """ level = serializers.CharField(source='get_level_display') # 序列化 choices class Meta: model = models.Course fields = ['id','title','course_img','level'] """ 方式一 : 自动序列化 不可控 class CourseDetailSerializer(serializers.ModelSerializer): class Meta: model = models.CourseDetail fields = '__all__' depth=1 #depth关联深度 1-10之间的数 def get_recommends(self, obj): # 这个序列化里面obj 对象就是 models对应的课程 (obj当前课程) print(obj, "这个对象哈哈哈哈哈是111111111111111111111111111111111111111111111111111") # 获取推荐的所有课程 queryset = obj.recommend_courses.all() print(queryset, "当前 0课程对应的详细!!!!!!!!!!") return [{'id': row.id, 'title': row.title} for row in queryset] def get_chapter(self, obj): # 获取推荐的所有课程 queryset = obj.course.chapter_set.all() return [{'id': row.id, 'name': row.name} for row in queryset] """ # # 方式二: 手动序列化 可控 class CourseDetailSerializer(serializers.ModelSerializer): """ 课程详细序列化 """ #OneToOneField / ForeignKey /choice 下面这种 序列化 ===> source参数做连表查询 title = serializers.CharField(source='course.title') # 跨表 img = serializers.CharField(source='course.course_img') # 跨表 level = serializers.CharField(source='course.get_level_display') # 序列化 choices # ManyToManyField 下面这种 序列化 recommends = serializers.SerializerMethodField() chapter = serializers.SerializerMethodField() class Meta: model = models.CourseDetail fields = ['course','title','img','level','slogon','why','recommends','chapter'] def get_recommends(self,obj): # 这个序列化里面obj 对象就是 models对应的课程 (obj当前课程) print(obj,"这个对象哈哈哈哈哈是111111111111111111111111111111111111111111111111111") # 获取推荐的所有课程 queryset = obj.recommend_courses.all() print(queryset,"当前 0课程对应的详细!!!!!!!!!!") return [{'id':row.id,'title':row.title} for row in queryset] def get_chapter(self,obj): # 获取推荐的所有课程 queryset = obj.course.chapter_set.all() return [{'id':row.id,'name':row.name} for row in queryset]
viwes from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.viewsets import GenericViewSet,ViewSetMixin from api.serializers.course import CourseSerializer,CourseDetailSerializer # 序列化 from api import models """ # 方式一: 获取单条数据 和多条数据 (对应url) class CourseView(APIView): def get(self, request, *args, **kwargs): # # 课程列表接口 # :param request: # :param args: # :param kwargs: # :return: ret = {'code': 1000, 'data': None} try: pk=kwargs.get("pk") if pk: obj=models.Course.objects.filter(id=pk).first() ser=CourseSerializer(instance=obj,many=False) # 通过url参数 去单条数据 else: queryset = models.Course.objects.all() ser= CourseSerializer(instance=queryset, many=True) # 获取多条数据 ret['data'] = ser.data print(ser.data,"获取序列化后的数据!!!!!!") except Exception as e: ret['code'] = 1001 ret['error'] = '获取课程失败' return Response(ret) """ # 方式二: 获取单条数据 和多条数据 (对应url) 拆分两个方法 比较清晰 # 通过url获取所有数据访问list方法 # 通过url带参数获取单条数据 访问retrieve 方法 class CourseView(ViewSetMixin,APIView): def list(self,request,*args,**kwargs): """ 课程列表接口 :param request: :param args: :param kwargs: :return: """ ret = {'code':1000,'data':None} try: queryset = models.Course.objects.all() ser = CourseSerializer(instance=queryset,many=True) # 获取多条数据 ret['data'] = ser.data except Exception as e: ret['code'] = 1001 ret['error'] = '获取课程失败' return Response(ret) def retrieve(self,request,*args,**kwargs): """ 课程详细接口 :param request: :param args: :param kwargs: :return: """ ret = {'code': 1000, 'data': None} try: # 课程ID=2 pk = kwargs.get('pk') # 课程详细对象 obj = models.CourseDetail.objects.filter(course_id=pk).first() ser = CourseDetailSerializer(instance=obj,many=False) # 通过url参数 去单条数据 ret['data'] = ser.data except Exception as e: ret['code'] = 1001 ret['error'] = '获取课程失败' return Response(ret) # 获取 choices 中文字 def test(request,*args,**kwargs): from django.shortcuts import HttpResponse obj = models.Course.objects.filter(id=2).first() print(obj.title) print(obj.level) # print(obj.get_level_display()) # return HttpResponse('...') # 人工智能 # 2 # 中级
前台vue:
3. 后台接口API +VUE前端(django REST 基础案例)知识点补充
https://www.cnblogs.com/wwg945/articles/8868786.html
https://blog.csdn.net/Fellow_Y/article/details/81633850
https://blog.csdn.net/wolf131721/article/details/78920080