45 django django-models django-authentication
我有一个带有created_by字段的模型,该字段链接到标准的Django User模型.保存模型时,我需要使用当前用户的ID自动填充它.我不能在Admin层执行此操作,因为站点的大多数部分都不会使用内置的Admin.任何人都可以建议我应该怎么做?
Dan*_*man 34
如果您想要在管理员和其他地方都能工作的东西,您应该使用自定义模型.基本思想是覆盖__init__方法以获取额外的参数 - 请求 - 并将其存储为表单的属性,然后在保存到数据库之前覆盖save方法以设置用户ID.
class MyModelForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
return super(MyModelForm, self).__init__(*args, **kwargs)
def save(self, *args, **kwargs):
kwargs['commit']=False
obj = super(MyModelForm, self).save(*args, **kwargs)
if self.request:
obj.user = self.request.user
obj.save()
return obj
Run Code Online (Sandbox Code Playgroud)
bik*_*der 27
最不受阻碍的方法是使用a CurrentUserMiddleware将当前用户存储在线程本地对象中:
from threading import local
_user = local()
class CurrentUserMiddleware(object):
def process_request(self, request):
_user.value = request.user
def get_current_user():
return _user.value
Run Code Online (Sandbox Code Playgroud)
现在,您只需要在身份验证中间件之后将此中间件添加到MIDDLEWARE_CLASSES .
MIDDLEWARE_CLASSES = (
...
'django.contrib.auth.middleware.AuthenticationMiddleware',
...
'current_user.CurrentUserMiddleware',
...
)
Run Code Online (Sandbox Code Playgroud)
您的模型现在可以使用该get_current_user函数来访问用户,而无需传递请求对象.
from django.db import models
from current_user import get_current_user
class MyModel(models.Model):
created_by = models.ForeignKey('auth.User', default=get_current_user)
Run Code Online (Sandbox Code Playgroud)
如果您在使用Django CMS你甚至都不需要定义自己的CurrentUserMiddleware但可以使用cms.middleware.user.CurrentUserMiddleware和cms.utils.permissions.get_current_user函数来检索当前用户.
Tim*_*her 23
Daniel的答案不会直接用于管理员,因为您需要传入请求对象.您可以通过覆盖类中的get_form方法来实现此目的,ModelAdmin但是可能更容易远离表单自定义并且只是覆盖save_model您的ModelAdmin.
def save_model(self, request, obj, form, change):
"""When creating a new object, set the creator field.
"""
if not change:
obj.creator = request.user
obj.save()
Run Code Online (Sandbox Code Playgroud)
min*_*ace 13
整个方法都让我感到害怕.我只想说一次,所以我在中间件中实现了它.只需在身份验证中间件后添加WhodidMiddleware即可.
如果您的created_by和modified_by字段设置为editable = False那么您根本不必更改任何表单.
"""Add user created_by and modified_by foreign key refs to any model automatically.
Almost entirely taken from https://github.com/Atomidata/django-audit-log/blob/master/audit_log/middleware.py"""
from django.db.models import signals
from django.utils.functional import curry
class WhodidMiddleware(object):
def process_request(self, request):
if not request.method in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):
if hasattr(request, 'user') and request.user.is_authenticated():
user = request.user
else:
user = None
mark_whodid = curry(self.mark_whodid, user)
signals.pre_save.connect(mark_whodid, dispatch_uid = (self.__class__, request,), weak = False)
def process_response(self, request, response):
signals.pre_save.disconnect(dispatch_uid = (self.__class__, request,))
return response
def mark_whodid(self, user, sender, instance, **kwargs):
if 'created_by' in instance._meta.fields and not instance.created_by:
instance.created_by = user
if 'modified_by' in instance._meta.fields:
instance.modified_by = user
Run Code Online (Sandbox Code Playgroud)
这是我如何使用通用视图:
class MyView(CreateView):
model = MyModel
def form_valid(self, form):
object = form.save(commit=False)
object.owner = self.request.user
object.save()
return super(MyView, self).form_valid(form)
Run Code Online (Sandbox Code Playgroud)
小智 7
如果您使用基于类的视图,Daniel的答案需要更多.添加以下内容以确保ModelForm对象中的请求对象可用于我们
class BaseCreateView(CreateView):
def get_form_kwargs(self):
"""
Returns the keyword arguments for instanciating the form.
"""
kwargs = {'initial': self.get_initial()}
if self.request.method in ('POST', 'PUT'):
kwargs.update({
'data': self.request.POST,
'files': self.request.FILES,
'request': self.request})
return kwargs
Run Code Online (Sandbox Code Playgroud)
另外,如前所述,您需要在ModelForm.save()的末尾返回obj
| 归档时间: |
|
| 查看次数: |
39289 次 |
| 最近记录: |