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

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM