在Django中,如何线程安全地将请求传递给admin.StackedInline表单的__init__?
我想在我的表单集中给 StackedInline 的表单传递一个请求。现在我有了:
from django.contrib import admin
from django.utils.functional import curry
class AlbumInline(admin.StackedInline):
form = AlbumAdminForm
model = Album
extra = 1
def get_formset(self, request, obj=None, **kwargs):
formset = super(AlbumInline, self).get_formset(request, obj, **kwargs)
formset.form.__init__ = curry(formset.form.__init__, request=request)
return formset
这个方法可以用,但这个解决方案安全吗?如果不安全,我该怎么修复它呢?
2 个回答
0
我觉得这个不是线程安全的,因为它使用了柯里化,这会把请求绑定在一起。
不过因为它是在管理后台,所以可能也没什么大问题。
1
这看起来不是线程安全的。根据你想从HTTP请求对象中使用什么,你可以把它复制到一个新的HttpRequest中,只保留线程安全的信息(也就是大部分信息,除了请求的线程锁)。
在我的情况下,我是这样做的:
METACOPY = ['HTTP_X_REAL_IP', 'HTTP_X_FORWARDED_FOR', 'REMOTE_ADDR', 'REMOTE_HOST', 'SERVER_NAME', 'SERVER_PORT', 'LANG', 'LANGUAGE', 'HTTP_REFERER']
def thread_safe_copy(self):
meta = dict([(k,self.META[k]) for k in METACOPY if k in self.META and isinstance(self.META[k], str)])
request = HttpRequest()
request.POST = self.POST
request.GET = self.GET
request.user = self.user
request.path = self.path
request.META = meta
...
return request
在这里,我对HttpResponse和WSGIResponse进行了修改,但你可以用请求实例来替换self。