1. 程式人生 > >跨域,Content-Type元件

跨域,Content-Type元件

1,跨域:是瀏覽器的同源策略

  • 阻止ajax請求不組織src請求

2,一個源的定義:如果兩個頁面的協議,埠(如果由指定)和域名都相同,則兩個頁面具有相同的源

下面給出相對http://a.xyz.com/dir/page.html同源檢測的示例

URL 結果 原因
http://a.xyz.com/dir2/other.html 成功  
http://a.xyz.com/dir/inner/another.html 成功  
https://a.xyz.com/secure.html 失敗 不同協議(http和https)
http://a.xyz.com:81/dir/etc.html 失敗 不同埠(81和80)
http://z.opq.com/dir/other.html 失敗 不同域名(xyz和opq)

3,同源策略是什麼

同源策略是瀏覽器的一個安全功能,不同源的客戶指令碼在沒有明確授權的情況下,不能讀寫對方資源,所以xyz.com下的js指令碼採用abc.com裡面的檔案資料是會被拒絕的

同源策略限制了同一個源載入的文件或指令碼如何與來自另一個源的資源進行互動,這是一個用於隔離潛在惡意檔案的重要機制

4,不受同源策略限制

  1. 頁面中的連線,重定向以及表單提交時不會受到同源策略限制的
  2. 跨域資源的引入是可以的,但是js不能讀寫載入的內容,如嵌入式到頁面中<script src=" "></script>, <img>, <link>, <iframe>等

5,CORS跨域請求

CORS即Cross Resource Sharing跨域資源共享

那麼跨域請求還分兩種,一種是簡單請求,一種是複雜請求~~~

5.1>簡單請求

HTTP方法是下列方法之一

  • HEAD GET POST

HTTP頭資訊不超過以下幾種欄位

  • Accept, Accept-Language, Last-Event-ID
  • Content-Type只能是以下型別中的一個
    • application/x-www-from-urlencoded
    • multipart/form-data
    • text/plain

任何一個不滿足上述要求的請求,即會被認為是複雜請求~~

複雜請求會發出一個預請求,我們也叫預檢, OPTIONS請求~~

5.2>瀏覽器的同源策略

  • 跨域是因為瀏覽器的同源策略導致的,也就是說瀏覽器會阻止非同源的請求~~
  • 那什麼是非永遠呢~~即域名不同,埠不同屬於非同源的~~~
  • 瀏覽器只阻止表單以及ajax請求,並不會阻止src請求,所以我們的cnd,圖片等src請求都可以發~~

5.3>解決跨域

  • JSONP:jsonp的實現是根據瀏覽器不阻止請求入手~來實現的~~

 

class Test(APIView):

    def get(self, request):
        callback = request.query_params.get("callback", "")
        ret = callback + "(" + "'success'" + ")"
        return HttpResponse(ret)

 

jsonp的前端ajax程式碼

<button id="btn_one">點選我向JsonP1傳送請求</button>
<script>
    // 測試傳送請求失敗 跨域不能得到資料
    $('#btn_one').click(function () {
        $.ajax({
            url: "http://127.0.0.1:8000/jsonp1",
            type: "get",
            success: function (response) {
                console.log(response)
            }
        })
    });
    
    function handlerResponse(response) {
        alert(response)
    };
    
    window.onload = function () {
        $("#btn_one").click(function () { let script_ele = document.createElement("script"); script_ele.src = "http://127.0.0.1:8000/jsonp1?callback=handlerResponse"; document.body.insertBefore(script_ele, document.body.firstChild); }) } </script>

jsonp解決跨域只能傳送get請求,並且實現起來需要前後端互動比較多

  • 新增響應頭
from django.utils.deprecation import MiddlewareMixin


class MyCors(MiddlewareMixin):
    def process_response(self, request, response):
        response["Access-Control-Allow-Origin"] = "*"
        if request.method == "OPTIONS":
            # 複雜請求會先發預檢
            response["Access-Control-Allow-Headers"] = "Content-Type"
            response["Access-Control-Allow-Methods"] = "PUT,PATCH,DELETE"
        return response

 6,ContentType元件

  • 需求
  • 現在我們有這樣一個需求~我們的商城裡有很多的商品~~節目要來了~~我們要搞活動~~
  • 那麼我們就要設計優惠券~~優惠券都有什麼型別呢~~滿減的~折扣的~立減的~~
  • 我們對應著我們活動型別~對我們的某類商品設計優惠券~~比如~~
  • 家電是一類商品~~實物是一類商品~那麼我們可以設計家電折扣優惠券~以及實物滿減優惠券等
  • 那麼表結構怎麼設計~~

程式碼如下:

from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation

# Create your models here.


class Food(models.Model):
    """
    id      name
    1       醬香餅
    2       雞蛋餅
    3       水煎包
    """
    name = models.CharField(max_length=32) # 反向查詢用 coupons = GenericRelation(to="Coupon") class Fruit(models.Model): """ id name 1 紅心蜜柚 2 黑美人西瓜 """ name = models.CharField(max_length=32) # 反向查詢用 coupons = GenericRelation(to="Coupon") # class Table(models.Model): """ 第一版 id title food_id fruit_id.... 1 醬香餅買一送一 1 null 2 黑美人西瓜2折 null 2 """ # title = models.CharField(max_length=32) # # 第一版設計 # food = models.ForeignKey(to="Food") # fruit = models.ForeignKey(to="Fruit") # # # class MyTable(models.Model): """ id app_name table_name 1 Demo Food 2 Demo Fruit """ # # 第二版設計 # table = models.ForeignKey(to="MyTable") # object_id = models.IntegerField() # app_name = models.CharField(max_length=32) # table_name = models.CharField(max_length=32) class Coupon(models.Model): """ 第三版 id title table_id object_id 1 醬香餅買一送一 1 1 2 黑美人西瓜2折 2 2 """ # 第三版用django自帶的ContentType表 title = models.CharField(max_length=32) # content_type和ContentType表外來鍵關聯ContentType表是django自帶的表 content_type = models.ForeignKey(to=ContentType) object_id = models.IntegerField() # 不會生成欄位,只用於關聯到物件的 content_object = GenericForeignKey("content_type", "object_id")

遇到這種情況,一張表跟多種表外來鍵關聯的時候, Django就提供了ContentType元件~

ContentType是Django的內建的一個應用,可以追蹤專案中所有的app和model的對應關係,並記錄ContentType表中.

當我們的專案做資料庫遷移的後,會有很多自帶的表,其中就有django_content_type表.

  • ContentType元件的作用:
    • 在model中定義ForeiginKey欄位,並關聯到ContentType表,通常這個欄位命名為content-type
    • 在model中定義PositiveIntergerField欄位,用來儲存關聯表中的主鍵,通常我們用object_id
    • 在model中定義GenericForeignKey欄位,傳入上面兩個欄位的名字
    • 方便反向查詢可以定義GenericRelation欄位

檢視函式的程式碼如下:

 

from django.shortcuts import render
from rest_framework.views import APIView
from django.http import HttpResponse
from .models import Food, Fruit, Coupon
from django.contrib.contenttypes.models import ContentType

# Create your views here.


class TestView(APIView): def get(self, request): # 找到表id以及表物件 # content_type_obj = ContentType.objects.filter(app_label="Demo", model="food").first() # print(type(content_type_obj)) # model_class = content_type_obj.model_class() # print(model_class) # print(content_type_obj.id) # 給醬香餅建立優惠券 food_obj = Food.objects.filter(id=1).first() Coupon.objects.create(title="醬香餅買一送小威",content_object=food_obj) # 給黑美人加優惠券 # fruit_obj = Fruit.objects.get(id=2) # Coupon.objects.create(title="黑美人2折", content_type_id=9, object_id=2) # 查詢優惠券繫結物件 # coupon_obj = Coupon.objects.filter(id=1).first() # print(coupon_obj.content_object.name) # 查某個物件的優惠券 food_obj = Food.objects.filter(id=1).first() print(food_obj.coupons.all()) return HttpResponse("ok")