一 . Vue+Django 前后端数据交互知识点(一)

一.  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

 

 

 

posted @ 2019-10-16 05:44  supreme999  阅读(5452)  评论(0编辑  收藏  举报