我想序列化 Django 请求以便将其记录到数据库中。我尝试了不同的方法,但没有一个成功。
class RunTest(View):
def get(self, request, url):
srd = serializers.serialize('json', request)
return HttpResponse(json.dumps(request.META))
但这会引发错误
module 'rest_framework.serializers' has no attribute 'serialize'
可能是因为我使用其余框架作为中间件。 我也用过
srd = json.dumps(request)
在这种情况下,错误是
Object of type 'WSGIRequest' is not JSON serializable
有什么想法可以解决这个问题吗?
在尝试将收到的请求元数据存储在 JSONField 中时,我遇到了类似的问题。问题是
request.META
是一个字典,但它不是合适的 JSON。
示例请求。我的 META 是:
{
"wsgi.version": (1, 0),
"wsgi.url_scheme": "http",
"wsgi.input": <_io.BufferedReader name=10>,
"wsgi.errors": <_io.TextIOWrapper name="<stderr>" mode="w" encoding="utf-8">,
"wsgi.multithread": True,
"wsgi.multiprocess": False,
"wsgi.run_once": False,
"SERVER_SOFTWARE": "Werkzeug/1.0.1",
"REQUEST_METHOD": "POST",
"SCRIPT_NAME": "",
"PATH_INFO": "/api/v1/vouchers/voucher-distribute/",
"QUERY_STRING": "",
"REQUEST_URI": "/api/v1/vouchers/voucher-distribute"
...
}
因此,您可以看到带有
wsgi
前缀的前几个键是不合适的 JSON 格式,您也可以在线检查:http://json.parser.online.fr/
因此要将 request.META 存储为 JSON 字典,有必要删除这个键。技巧是你不能使用 request.META.pop("wsgi.version") 因为 request.META 不是合适的 JSON 格式:)
我所做的是创建了辅助函数:
def create_request_meta_json_object(meta_data):
return {
"REQUEST_METHOD": meta_data["REQUEST_METHOD"],
"SERVER_SOFTWARE": meta_data["SERVER_SOFTWARE"],
"REQUEST_METHOD": meta_data["REQUEST_METHOD"],
"SCRIPT_NAME": meta_data["SCRIPT_NAME"],
"PATH_INFO": meta_data["PATH_INFO"],
"QUERY_STRING": meta_data["QUERY_STRING"],
"REQUEST_URI": meta_data["REQUEST_URI"],
"RAW_URI": meta_data["RAW_URI"],
"REMOTE_ADDR": meta_data["REMOTE_ADDR"],
"REMOTE_PORT": meta_data["REMOTE_PORT"],
"SERVER_NAME": meta_data["SERVER_NAME"],
"SERVER_PORT": meta_data["SERVER_PORT"],
"SERVER_PROTOCOL": meta_data["SERVER_PROTOCOL"],
"HTTP_X_FORWARDED_HOST": meta_data["HTTP_X_FORWARDED_HOST"],
"HTTP_X_FORWARDED_PORT": meta_data["HTTP_X_FORWARDED_PORT"],
"HTTP_ACCEPT_ENCODING": meta_data["HTTP_ACCEPT_ENCODING"],
"HTTP_USER_AGENT": meta_data["HTTP_USER_AGENT"],
"HTTP_FROM": meta_data["HTTP_FROM"],
"HTTP_ACCEPT": meta_data["HTTP_ACCEPT"],
"CONTENT_TYPE": meta_data["CONTENT_TYPE"],
"CONTENT_LENGTH": meta_data["CONTENT_LENGTH"],
"HTTP_CONNECTION": meta_data["HTTP_CONNECTION"],
"HTTP_X_NGINX_PROXY": meta_data["HTTP_X_NGINX_PROXY"],
"HTTP_X_FORWARDED_PROTO": meta_data["HTTP_X_FORWARDED_PROTO"],
"HTTP_X_FORWARDED_FOR": meta_data["HTTP_X_FORWARDED_FOR"],
"HTTP_X_REAL_IP": meta_data["HTTP_X_REAL_IP"],
}
并像这样使用它:
meta_data_as_json = create_request_meta_json_object(request.META)
您无法序列化
request
- 您可以序列化 request.GET
,在 DRF 中也称为 request.query_params
。
srd = json.dumps(request.query_params)
或
srd = json.dumps(request.GET)
要使用序列化器,您首先必须创建一个序列化器。 声明序列化器是一个很好的起点。
另一个潜在的解决方案是使用字典理解:
meta_keys = {
"wsgi.version": (1, 0),
"wsgi.version": "http",
"wsgi.input": object(),
"wsgi.errors": object(),
"wsgi.multithread": True,
"wsgi.multiprocess": False,
"wsgi.run_once": False,
"SERVER_SOFTWARE": "Werkzeug/1.0.1",
"REQUEST_METHOD": "POST",
"SCRIPT_NAME": "",
"PATH_INFO": "/api/v1/vouchers/voucher-distribute/",
"QUERY_STRING": "",
"REQUEST_URI": "/api/v1/vouchers/voucher-distribute"
}
excluded_meta_keys = ['wsgi.version', 'wsgi.version', 'wsgi.input', 'wsgi.multithread', 'wsgi.multiprocess', 'wsgi.run_once', 'wsgi.errors']
print({key: value for key, value in meta_keys.items() if key not in excluded_meta_keys})
print({key: value for key, value in meta_keys.items() if isinstance(value, (str, bool, int, float))})
结果:
{'SERVER_SOFTWARE': 'Werkzeug/1.0.1', 'REQUEST_METHOD': 'POST', 'SCRIPT_NAME': '', 'PATH_INFO': '/api/v1/vouchers/voucher-distribute/', 'QUERY_STRING': '', 'REQUEST_URI': '/api/v1/vouchers/voucher-distribute'}
{'wsgi.version': 'http', 'wsgi.multithread': True, 'wsgi.multiprocess': False, 'wsgi.run_once': False, 'SERVER_SOFTWARE': 'Werkzeug/1.0.1', 'REQUEST_METHOD': 'POST', 'SCRIPT_NAME': '', 'PATH_INFO': '/api/v1/vouchers/voucher-distribute/', 'QUERY_STRING': '', 'REQUEST_URI': '/api/v1/vouchers/voucher-distribute'}
分别
request.META 具有 json 对象不允许的类型的键,因此您可以仅使用具有 str 类型值的键生成另一个字典:
dict = create_request_meta_json_object(request.META)
def create_request_meta_json_object(meta_data):
diccionario = []
for key, value in meta_data.items():
if type(value) is str:
diccionario.append({"key": key, "value": value})
return diccionario
这是我解决问题的方法:
except Exception as error:
exc_type, exc_value, exc_context = sys.exc_info()
sExceptionName = str(exc_type.__name__)
sExceptionReason = str(exc_value)
sExceptionTraceback = str(traceback.format_exception(exc_context))
rHttpResponse = JsonResponse(
{
"status": "error",
"exception": {
"name": sExceptionName,
"reason": sExceptionReason,
"traceback": sExceptionTraceback
}
}
)
return rHttpResponse
目标是将任何异常以可识别的形式序列化为实际异常。
最终结果是呼叫者可以确定显示多少内容,以便为用户提供一些智能错误消息以捕获并发送给帮助台。