Django:获取模型保存中的当前用户
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django:获取模型保存中的当前用户相关的知识,希望对你有一定的参考价值。
我想在models.py的request.user
方法中获取当前登录的用户(save
)。我想检查用户的角色,看看它是否可以根据自己的角色执行某些操作。
models.朋友:
class TimeSheet(models.Model):
check_in_time = models.TimeField()
check_out_time = models.TimeField()
class Tasks(models.Model):
time_sheet = models.ForeignKey(TimeSheet)
project = models.ForeignKey(Project)
start_time = models.TimeField()
end_time = models.TimeField()
def save(self, *args,**kwargs):
project = SpentTime.objects.get(project__project__id = self.project.id)
start = datetime.datetime.strptime(str(self.start_time), '%H:%M:%S')
end = datetime.datetime.strptime(str(self.end_time), '%H:%M:%S')
time = float("{0:.2f}".format((end - start).seconds/3600.0))
if common.isDesigner(request.user):
SpentTime.objects.filter(project__project__id = self.project.id).update(design = float(project.design) + time)
if common.isDeveloper(request.user):
SpentTime.objects.filter(project__project__id = self.project.id).update(develop = float(project.develop) + time)
super(Tasks, self).save(*args, **kwargs)
这里Tasks
模型被用作Timesheet
模型中的内联。我想检查当前登录用户的角色,并根据用户的角色更新另一个模型。在这里,我需要request.user
来检查当前用户的角色。我没有使用任何表单或模板,并完全使用Django管理员。是否有任何方法可以在request.user
方法中获取save
或检查和更新admin.py中另一个模型中的值?
您可以从另一个角度解决此问题。您应该覆盖AdminSites save_model
方法,而不是更改模型保存方法。在那里,您将拥有请求对象,并且可以像您已经指出的那样访问登录的用户数据。
看看文档的这一章:Django ModelAdmin documentation save_model
我找到了一种方法,但它涉及声明一个MiddleWare。在您的应用内创建一个名为get_username.py
的文件,其中包含以下内容:
from threading import current_thread
_requests = {}
def get_username():
t = current_thread()
if t not in _requests:
return None
return _requests[t]
class RequestMiddleware(object):
def process_request(self, request):
_requests[current_thread()] = request
编辑你的settings.py
并将其添加到MIDDLEWARE_CLASSES
:
MIDDLEWARE_CLASSES = (
...
'yourapp.get_username.RequestMiddleware',
)
现在,在您的save()
方法中,您可以获得如下的当前用户名:
from get_username import get_username
...
def save(self, *args, **kwargs):
req = get_username()
print "Your username is: %s" % (req.user)
我不认为save_model方法覆盖是最好的选择。例如,想象一下,您希望保存用户信息或根据用户信息验证模型,并且save()不是来自视图或管理站本身。
人们问的是那些建筑:
def save(..)
self.user = current_user()
要么
def save(..)
user = current_user()
if user.group == 'XPTO':
error('This user cannot edit this record')
我到目前为止找到的最佳方法是:
https://bitbucket.org/q/django-current-user/overview
@nKn提出的解决方案是一个很好的起点,但是当我今天尝试实施时,我面临两个问题:
- 在当前的Django版本中间件创建为普通对象不起作用。
- 单元测试失败(因为它们通常在单线程中运行,因此如果第一个测试具有HTTP请求而第二个测试没有HTTP请求,则'请求'将在两个后续测试之间粘连。
这是我更新的中间件代码,它与Django 1.10一起使用并且不会破坏单元测试:
from threading import current_thread
from django.utils.deprecation import MiddlewareMixin
_requests = {}
def current_request():
return _requests.get(current_thread().ident, None)
class RequestMiddleware(MiddlewareMixin):
def process_request(self, request):
_requests[current_thread().ident] = request
def process_response(self, request, response):
# when response is ready, request should be flushed
_requests.pop(current_thread().ident, None)
return response
def process_exception(self, request, exception):
# if an exception has happened, request should be flushed too
_requests.pop(current_thread().ident, None)
正确的方法是使用threading.local
,而不是使用带有threading.current_thread
的字典,因为它会导致内存泄漏,因为旧的值将在应用程序运行的时间内保持不变:
import threading
request_local = threading.local()
def get_request():
return getattr(request_local, 'request', None)
class RequestMiddleware():
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
request_local.request = request
return self.get_response(request)
def process_exception(self, request, exception):
request_local.request = None
def process_template_response(self, request, response):
request_local.request = None
return response
如果您想访问用户而不是请求,您可以使用get_request().user
,或者保存用户而不是__call__
上的请求
以上是关于Django:获取模型保存中的当前用户的主要内容,如果未能解决你的问题,请参考以下文章