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

     
  • 相关阅读:
    centos7搭建kvm
    python脚本与shell脚本的结合应用
    shell脚本常用命令组合
    服务器硬盘损坏恢复过程
    linux grup引导进入单用户下
    mysql 数据库设计查询规范
    mysql 8.0 远程连接问题
    linux新加硬盘的操作
    linux 添加硬盘到/home 目录
    linux设置最大连接数
  • 原文地址:https://www.cnblogs.com/lovershowtime/p/11682196.html
Copyright © 2020-2023  润新知