Ama*_*mar 4 python django audit-logging django-rest-framework django-auditlog
我需要在我使用Django 1.8和的项目之一中实现审核日志功能Django-Rest-Framework 3.2.2。我已经扩展BaseUserManager class了创建用户模型,因为我必须在我的应用程序中使用电子邮件作为用户名(如果此信息很重要)。
下面是我的数据库设计,它将保存日志:
**fields type desc**
id pk ( auto_increment)
cust_id FK customer
customer_name FK customer
user_id FK user
user_name FK user
module Varchar(100) sales,order,billing,etc
action Varchar(10) Create/Update/Delete
previous_value varchar(500)
current_value varchar(500)
Datetime Datetime timestamp of change
Run Code Online (Sandbox Code Playgroud)
我已经尝试过https://pypi.python.org/pypi/django-audit-log但根据我的要求它有两个问题 -
我正在寻求建议以继续使用此功能。哪个包最适合我的任务。
PS我也尝试过Django-reversion,我没有数据版本控制的要求。
谢谢
我通过修改auditlog代码实现了我所需要的 -
使用这个我就完成了一半。现在我面临的唯一问题是,由于 1 个表的模型实例也包含其他表的信息,因为该表中使用了 FK。
为了解决这个问题,我可以想出一个效果很好的解决方案,但我对此不满意。我在每个模型中添加了一个像include_in_model()这样的函数,并修改了auditlog的registry.py register()函数来获取这些字段,并且仅使用它来保存LogEntry模型中的信息。
这种方法将要求我在每个模型类中创建此include_in_model()函数,并传递特定模型所需的字段。这样我就避免了与 FK 相关的信息。
Django Simple History是一个优秀的应用程序,我过去在生产项目中使用过,它将为您提供针对用户的每个模型的审核。
此外,您应该创建自己的身份验证类,该类将负责记录请求。假设用户使用令牌对您的 API 进行身份验证。它会在每个 HTTP 请求的标头中发送到您的 API,如下所示Authorization: Bearer <My Token>:然后我们应该记录与请求相关的用户、时间、用户的 IP 和正文。
这很简单:
设置.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'common.authentication.MyTokenAuthenticationClass'
),
...
}
Run Code Online (Sandbox Code Playgroud)
通用/身份验证.py
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from ipware.ip import get_real_ip
from rest_framework import authentication
from rest_framework import exceptions
from accounts.models import Token, AuditLog
class MyTokenAuthenticationClass(authentication.BaseAuthentication):
def authenticate(self, request):
# Grab the Athorization Header from the HTTP Request
auth = authentication.get_authorization_header(request).split()
if not auth or auth[0].lower() != b'bearer':
return None
# Check that Token header is properly formatted and present, raise errors if not
if len(auth) == 1:
msg = _('Invalid token header. No credentials provided.')
raise exceptions.AuthenticationFailed(msg)
elif len(auth) > 2:
msg = _('Invalid token header. Credentials string should not contain spaces.')
raise exceptions.AuthenticationFailed(msg)
try:
token = Token.objects.get(token=auth[1])
# Using the `ipware.ip` module to get the real IP (if hosted on ElasticBeanstalk or Heroku)
token.last_ip = get_real_ip(request)
token.last_login = timezone.now()
token.save()
# Add the saved token instance to the request context
request.token = token
except Token.DoesNotExist:
raise exceptions.AuthenticationFailed('Invalid token.')
# At this point, insert the Log into your AuditLog table:
AuditLog.objects.create(
user_id=token.user,
request_payload=request.body,
# Additional fields
...
)
# Return the Authenticated User associated with the Token
return (token.user, token)
Run Code Online (Sandbox Code Playgroud)