首页 > 其他 > 详细

跨域,CORS和contentType表

时间:2019-05-04 17:55:06      阅读:143      评论:0      收藏:0      [点我收藏+]

一 . 跨域

域名,协议,端口有一个不一样都是跨域,简单的解释一下,,你从你从端口号为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表

原文:https://www.cnblogs.com/attila/p/10808993.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!