Django 我需要建议将应用程序集成到我的项目中
我创建了一个应用程序来审核对象上的操作。创建、更新或删除对象时,将在“我的审核表”(Auditor模型)中创建一条新记录 Audit应用程序现在正在运行,但要在我的模型上使用它,需要一些工作和大量代码,我相信用最优化的方法可以避免这些工作和代码 我可以使用哪种django资源或方法在我的模型上集成Audit应用程序,而不用编写这么多代码?我需要一种简化的方式来归档Auditor应用程序与我的所有模型和其他项目的集成 我将给出一个示例,说明如何将Auditor模型与要审核的模型(Car)结合使用 多谢各位 车型Django 我需要建议将应用程序集成到我的项目中,django,Django,我创建了一个应用程序来审核对象上的操作。创建、更新或删除对象时,将在“我的审核表”(Auditor模型)中创建一条新记录 Audit应用程序现在正在运行,但要在我的模型上使用它,需要一些工作和大量代码,我相信用最优化的方法可以避免这些工作和代码 我可以使用哪种django资源或方法在我的模型上集成Audit应用程序,而不用编写这么多代码?我需要一种简化的方式来归档Auditor应用程序与我的所有模型和其他项目的集成 我将给出一个示例,说明如何将Auditor模型与要审核的模型(Car)结合使用
class Car(models.Model):
name = models.CharField(max_length=50)
brand = models.CharField(max_length=50)
color = models.CharField(max_length=50)
is_available = models.BooleanField(default=True)
class Auditor(models.Model):
field = models.CharField(max_length=255, blank=True)
action = models.CharField(max_length=6)
old_value = models.TextField(blank=True)
new_value = models.TextField(blank=True)
stamp = models.DateTimeField(auto_now_add=True)
user = models.ForeignKey(settings.AUTH_USER_MODEL)
content_type = models.ForeignKey(ContentType, blank=True)
object_id = models.PositiveIntegerField(blank=True)
content_object = GenericForeignKey('content_type', 'object_id')
deleted_object = models.CharField(max_length=255, blank=True)
审计师模式
class Car(models.Model):
name = models.CharField(max_length=50)
brand = models.CharField(max_length=50)
color = models.CharField(max_length=50)
is_available = models.BooleanField(default=True)
class Auditor(models.Model):
field = models.CharField(max_length=255, blank=True)
action = models.CharField(max_length=6)
old_value = models.TextField(blank=True)
new_value = models.TextField(blank=True)
stamp = models.DateTimeField(auto_now_add=True)
user = models.ForeignKey(settings.AUTH_USER_MODEL)
content_type = models.ForeignKey(ContentType, blank=True)
object_id = models.PositiveIntegerField(blank=True)
content_object = GenericForeignKey('content_type', 'object_id')
deleted_object = models.CharField(max_length=255, blank=True)
汽车视图
from audittest.apps.auditor.models import Auditor
from django.contrib.contenttypes.models import ContentType
#Function for audit creation. I know that the view is not the right place to put this function, but I put this here for test.
def create_audit(obj, request, action, obj_id=False):
if action == 'CREATE':
audit = Auditor(content_type = ContentType.objects.get_for_model(obj), object_id = obj.id, user = request.user, action = action)
elif action == 'DELETE':
audit = Auditor(content_type = ContentType.objects.get_for_model(obj), object_id = obj_id, user = request.user, action = action, deleted_object = obj)
audit.save()
def new(request, template_name='cars/form.html'):
form = CarForm(request.POST or None)
if form.is_valid():
obj = form.save()
create_audit(obj, request, 'CREATE')
return redirect('car:admin')
return render(request, template_name, {'form':form, 'title':u'Novo Car'})
def edit(request, pk, template_name='cars/form.html'):
car = get_object_or_404(Car, pk=pk)
form = CarForm(request.POST or None, instance=car, request=request)
if form.is_valid():
form.save()
return redirect('car:admin')
return render(request, template_name, {'form':form,'title':u'Editar Car'})
def delete(request, pk, template_name='cars/confirm_delete.html'):
car = get_object_or_404(Car, pk=pk)
obj_id = car.id
if request.method=='POST':
car.delete()
create_audit(car, request, 'DELETE', obj_id=obj_id)
messages.success(request, u'Car excluído com sucesso.')
return redirect('car:admin')
return render(request, template_name, {'object':car})
汽车形态
class CarForm(ModelForm):
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
super(CarForm, self).__init__(*args, **kwargs)
def clean(self):
cleaned_data = super(CarForm, self).clean()
# Audit updated fields
if self.instance.pk is not None:
fields = []
for field in self.instance._meta.get_all_field_names():
if field != 'id' and getattr(self.instance, field) != cleaned_data[field]:
#fields.append((field, getattr(self.instance, field), cleaned_data[field]))
audit = Auditor(content_type = ContentType.objects.get_for_model(self.instance), object_id = self.instance.pk, user = self.request.user, action = 'UPDATE', field = self.instance._meta.get_field(field).verbose_name, old_value = getattr(self.instance, field), new_value = cleaned_data[field])
audit.save()
return cleaned_data
在应用程序中使用基于类的视图,这样您就可以充分利用cool
mixin的优势,
我通常创建一个Mixin
,可以添加到任何CreateView或UpdateView
class withAudit(object):
"""
A mixin that will create an audit record wither the action is
Create or Update
"""
def get_success_url(self):
"""
This will be called when the form is valid and saved.
"""
# create the record
audit = Auditor(content_type= ContentType.objects.get_for_model(self.model))
audit.object_id = self.object.pk
audit.user = request.user
# You will need a way to capture this action.
# there are many ways to do it.
audit.action = "Create"
audit.save()
return super(withAudit, self).get_success_url()
在你看来,你必须这样使用它
class CarCreate(withAudit, CreateView):
model = Car
更新
class CarUpdate(withAudit, UpdateView):
model = Car
您可以对应用程序中的任何UpdateView或CreateView执行以下操作。但是,对于删除对象,我认为您需要另一个mixin,它将在执行操作之前捕获数据。您需要查看基于类的视图文档,以便根据需要自定义这些文档
如果你真的想继续使用基于方法的视图,同样的想法也可以在装饰器上实现。
如果您有一个具有高流量的大型应用程序,那么这个过程应该在后台完成,您可以在后台定义一个堆栈或队列,然后不断地将这些信息传递给它,这将提供更好的性能。一些大型应用程序使用另一个数据库进行日志和审计 谢谢@Othman。在Mixin中,如何确定对象是否为新对象,以便设置适当的操作?我是一个真正的mixin初学者。@bleroy检查这个@bleroy检查表单。应该在视图调用方法get\u success\u url
之前完成实例。阅读基于类的视图文档,了解应该使用哪种方法。谢谢@Othman。现在,我可以使用form\u valid方法确定操作,并通过pass获得\u success\u url。但是,我在获取原始对象数据以与get_success_url方法中的self.object进行比较以确定哪些字段被更新时遇到了问题。如何从mixin中的更新表单中获取初始数据?@bleroy您可以在同一个mixin
中使用多种方法,例如form\u valid
您可以在其中执行deepcopy
并将其作为类中的变量存储在旧对象中,将来在get\u success\u url
中使用它。