zoukankan      html  css  js  c++  java
  • 跨域,CORS和contentType表

    一 . 跨域

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

  • 相关阅读:
    总结
    spring boot 使用mongodb基本操作与一些坑
    java 在循环中删除数组元素之二
    学习spring cloud 笔记
    一些名词解释
    redis--分布式锁
    微信小程序的加密与解密--java
    java 动态代理
    (收藏)CORS(跨域资源共享)
    策略模式学习笔记--在写更好的代码路上
  • 原文地址:https://www.cnblogs.com/attila/p/10808993.html
Copyright © 2011-2022 走看看