跨域,CORS和contentType表
阿新 • • 發佈:2019-05-04
objects 文件 mod 實現 lte resp png quest 發送 只要同時
一 . 跨域
域名,協議,端口有一個不一樣都是跨域,簡單的解釋一下,,你從你從端口號為8000去請求8001的數據就是跨域.
如果想解決跨域問題,需要瀏覽器同時支持,我們這裏用CORS(Cross-origin resource sharing ("跨域資源共享"))來解決跨域的問題
二 . CORS
整個CORS通信過程,都是瀏覽器自動完成,不需要用戶參與。
因此,實現CORS通信的關鍵是服務器。只要服務器實現了CORS接口,就可以跨域通信。
瀏覽器將CORS分為兩類:簡單請求(simple request)和非簡單請求(not-so-simple request)
只要同時 滿足一下兩個條件,就屬於簡單請求
(1) 請求方法是以下三種方法之一:(也就是說如果你的請求方法是什麽put、delete等肯定是非簡單請求) HEAD GET POST (2)HTTP的頭信息不超出以下幾種字段:(如果比這些請求頭多,那麽一定是非簡單請求) Accept Accept-Language Content-Language Last-Event-ID Content-Type:只限於三個值application/x-www-form-urlencoded、multipart/form-data、text/plain,
也就是說,如果你發送的application/json格式的數據,那麽肯定是非簡單請求,vue的axios默認的請求體信息格式是json的,ajax默認是urlencoded的。
解決辦法(在被請求的視圖函數中加上一個響應頭信息)
from django.shortcuts import render
from django.http import JsonResponse
# Create your views here.
def books(request):
obj = JsonResponse([‘西遊記2‘,‘三國演義2‘,‘水滸傳2‘],safe=False)
#下面這個響應頭信息是告訴瀏覽器,"*" 代表誰請求都可以
# obj["Access-Control-Allow-Origin"] = "*"
obj["Access-Control-Allow-Origin"] = "http://127.0.0.1:8000" #只有這個ip和端口來的請求,我才給他數據,其他你瀏覽器幫我攔著
return obj
非簡單請求
這裏簡單的介紹一下簡單請求與非簡單請求的區別
* 簡單請求和非簡單請求的區別?
簡單請求:一次請求
非簡單請求:兩次請求,在發送數據之前會先發一次請求用於做“預檢”,只有“預檢”通過後才再發送一次請求用於數據傳輸。
* 關於“預檢”
- 請求方式:OPTIONS
- “預檢”其實做檢查,檢查如果通過則允許傳輸數據,檢查不通過則不再發送真正想要發送的消息
- 如何“預檢”
=> 如果復雜請求是PUT等請求,則服務端需要設置允許某請求,否則“預檢”不通過
Access-Control-Request-Method
=> 如果復雜請求設置了請求頭,則服務端需要設置允許某請求頭,否則“預檢”不通過
Access-Control-Request-Headers
看圖:
如果是非簡單請求的話,我們在視圖函數中應該這樣寫
from django.shortcuts import render
from django.http import JsonResponse
# Create your views here.
def books(request):
obj = JsonResponse([‘西遊記‘,‘三國演義‘,‘水滸傳‘],safe=False)
# obj["Access-Control-Allow-Origin"] = "*"
obj["Access-Control-Allow-Origin"] = "http://127.0.0.1:8000"
#處理預檢的options請求,這個預檢的響應,我們需要在響應頭裏面加上下面的內容
if request.method == ‘OPTIONS‘:
obj[‘Access-Control-Allow-Headers‘] = "content-type" # 也可以在裏面寫自定義的請求頭,當然也可以寫"*"
obj[‘Access-Control-Allow-Methods‘] = "DELETE,PUT" # 通過預檢的請求方法設置,同樣可以寫"*"
return obj
三 . django中自帶的contentType表
models.py文件
from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
class Electrics(models.Model):
name = models.CharField(max_length=32)
price = models.IntegerField()
coupons = GenericRelation(to=‘Coupon‘) # 用於反向查詢,不會生成表字段
def __str__(self):
return self.name
class Foods(models.Model):
name = models.CharField(max_length=32)
price = models.IntegerField()
coupons = GenericRelation(to=‘Coupon‘)
def __str__(self):
return self.name
class Coupon(models.Model):
name = models.CharField(max_length=32)
content_type = models.ForeignKey(to=ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField() # 存的是關聯的那張表對應的id
content_object = GenericForeignKey(‘content_type‘, ‘object_id‘) # 對象.content_object直接能找到優惠券關聯的商品對象
def __str__(self):
return self.name
視圖函數
from app01 import models
from django.shortcuts import render, HttpResponse
from django.contrib.contenttypes.models import ContentType
def test(request):
if request.method == ‘GET‘:
# ContentType表對象有model_class() 方法,取到對應model
content = ContentType.objects.filter(app_label=‘app01‘, model=‘electrics‘).first() # 表名小寫
elec_class = content.model_class() # elec_class 就相當於models.Electrics
res = elec_class.objects.all()
print(res) # <QuerySet [<Electrics: 電視>, <Electrics: 冰箱>]>
return HttpResponse(‘ok‘)
# 為電視(id=1)創建一條優惠記錄
tv = models.Electrics.objects.filter(id=1).first()
models.Coupon.objects.create(name=‘電視優惠券‘, content_object=tv)
return HttpResponse(‘ok‘)
# 查詢優惠券(id=1)綁定了哪個商品
coupon_obj = models.Coupon.objects.filter(id=1).first()
prod = coupon_obj.content_object
print(prod.name) # 電視
print(prod.price) # 1000
return HttpResponse(‘ok‘)
# 查詢電視(id=1)的所有優惠券
tv = models.Electrics.objects.filter(id=1).first()
res = tv.coupons.all()
print(res) # <QuerySet [<Coupon: 電視優惠券>]>
return HttpResponse(‘ok‘)
!!! 註意:ContentType只運用於1對多的關系!!!並且多的那張表中有多個ForeignKey字段。
跨域,CORS和contentType表