打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
【Django】使用requests并通过ORM修改数据操作的一次脱坑记录

最近在写接口自动化的测试平台,在请求接口回填响应头数据的这一步遇到了一个小问题,想要通过requests库自带的获取响应头的方法(r.headers),然后拿到值后传给前端进行展示,展示效果如下:



开始调试时一切都好好的,但为了将该数据做保存记录的时候出了一些问题,报了一个不常见的错误:



第一反应是django序列化相关的的问题,按报错日志追溯到是代码中通过ORM批量创建数据入库的这一步报错,分析了一下还是没有啥头绪:



打了断点、加注释调试也没发现什么结果,也没有怀疑是因为增加了获取响应header这个操作导致的问题,后面实在无头绪将这部分代码注释后就不报错,能够正常运行了!

然后经过一些调试发现requests返回的响应header是:<class 'requests.structures.CaseInsensitiveDict'>这个类型,这是一个requests自定义的数据结构,是一个不区分大小写的纯字符串键的数据结构,它也会包含一些byte数据所以在序列其为json字符串时会报错:

class CaseInsensitiveDict(MutableMapping):
    """A case-insensitive ``dict``-like object.

    Implements all methods and operations of
    ``MutableMapping`` as well as dict's ``copy``. Also
    provides ``lower_items``.

    All keys are expected to be strings. The structure remembers the
    case of the last key to be set, and ``iter(instance)``,
    ``keys()``, ``items()``, ``iterkeys()``, and ``iteritems()``
    will contain case-sensitive keys. However, querying and contains
    testing is case insensitive::

        cid = CaseInsensitiveDict()
        cid['Accept'] = 'application/json'
        cid['aCCEPT'] == 'application/json'  # True
        list(cid) == ['Accept']  # True

    For example, ``headers['content-encoding']`` will return the
    value of a ``'Content-Encoding'`` response header, regardless
    of how the header name was originally stored.

    If the constructor, ``.update``, or equality comparison
    operations are given keys that have equal ``.lower()``s, the
    behavior is undefined.
    """

    def __init__(self, data=None, **kwargs):
        self._store = OrderedDict()
        if data is None:
            data = {}
        self.update(data, **kwargs)

    def __setitem__(self, key, value):
        # Use the lowercased key for lookups, but store the actual
        # key alongside the value.
        self._store[key.lower()] = (key, value)

    def __getitem__(self, key):
        return self._store[key.lower()][1]

    def __delitem__(self, key):
        del self._store[key.lower()]

    def __iter__(self):
        return (casedkey for casedkey, mappedvalue in self._store.values())

    def __len__(self):
        return len(self._store)

    def lower_items(self):
        """Like iteritems(), but with all lowercase keys."""
        return (
            (lowerkey, keyval[1])
            for (lowerkey, keyval)
            in self._store.items()
        )

    def __eq__(self, other):
        if isinstance(other, Mapping):
            other = CaseInsensitiveDict(other)
        else:
            return NotImplemented
        # Compare insensitively
        return dict(self.lower_items()) == dict(other.lower_items())

    # Copy is required
    def copy(self):
        return CaseInsensitiveDict(self._store.values())

    def __repr__(self):
        return str(dict(self.items()))

所以这里我直接将其转换为dict类型就可以解决这个问题:

原:req_log['res_headers'] = r.headers
改:req_log['res_headers'] = dict(r.headers)

我也并未花更多时间去研究该数据结构的功能,这里主要是做个笔记提醒自己。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
9
python对象转字典的两种方式
django中动态生成二级菜单
Python的轻量级ORM框架peewee
Django 源码小剖: 应用程序入口 WSGIHandler
使用纯 Python 代码来模拟实现 Python 字典
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服