我有一些类似的模型:
class BaseModel(models.Model):
created_by = models.ForeignKey(User, related_name="%(app_label)s_%(class)s_created")
created_date = models.DateTimeField(_('Added date'), auto_now_add=True)
last_updated_by = models.ForeignKey(User, related_name="%(app_label)s_%(class)s_updated")
last_updated_date = models.DateTimeField(_('Last update date'), auto_now=True)
class Meta:
abstract = True
class Image(BaseModel):
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
name = models.CharField(_('Item name'), max_length=200, blank=True)
image = models.ImageField(_('Image'), upload_to=get_upload_path)
def save(self, *args, **kwargs):
if self.image and not GALLERY_ORIGINAL_IMAGESIZE == 0:
width, height = GALLERY_ORIGINAL_IMAGESIZE.split('x')
super(Image, self).save(*args, **kwargs)
filename = os.path.join( settings.MEDIA_ROOT, self.image.name )
image = PILImage.open(filename)
image.thumbnail((int(width), int(height)), PILImage.ANTIALIAS)
image.save(filename)
super(Image, self).save(*args, **kwargs)
class Album(BaseModel):
name = models.CharField(_('Album Name'), max_length=200)
description = models.TextField(_('Description'), blank=True)
slug = models.SlugField(_('Slug'), max_length=200, blank=True)
status = models.SmallIntegerField(_('Status'),choices=ALBUM_STATUSES)
images = generic.GenericRelation(Image)
我为所有模型使用BaseModel抽象模型来跟踪保存和更新日志。我可以使用ModelAdmin类自动设置用户字段:
class BaseAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
if not change:
obj.created_by = request.user
obj.last_updated_by = request.user
obj.save()
class AlbumAdmin(BaseAdmin):
prepopulated_fields = {"slug": ("name",)}
list_display = ('id','name')
ordering = ('id',)
有效。所有BaseAdmin字段都会自动填充。但我想通过Inline将图像添加到相册中。所以,我改变了我的admin.py:
from django.contrib.contenttypes import generic
class ImageInline(generic.GenericTabularInline):
model = Image
extra = 1
class AlbumAdmin(BaseAdmin):
prepopulated_fields = {"slug": ("name",)}
list_display = ('id','name')
ordering = ('id',)
inlines = [ImageInline,]
当我保存页面时,我在Image model save方法的第一行gallery_image.created_by_id may not be NULL
行收到错误:super(Image, self).save(*args, **kwargs)
。我知道这是因为GenericTabularInline类没有“save_model”方法来覆盖。
所以,问题是,我如何覆盖保存方法并在InlineModelAdmin类中设置当前用户?
答案 0 :(得分:1)
我找到了另一个问题的解决方案:https://stackoverflow.com/a/3569038/198062
所以,我改变了我的BaseAdmin模型类,它就像一个魅力:
from models import BaseModel
class BaseAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
if not change:
obj.created_by = request.user
obj.last_updated_by = request.user
obj.save()
def save_formset(self, request, form, formset, change):
instances = formset.save(commit=False)
for instance in instances:
if isinstance(instance, BaseModel): #Check if it is the correct type of inline
if not instance.created_by_id:
instance.created_by = request.user
instance.last_updated_by = request.user
instance.save()
请注意,您必须为包含内联的ModelAdmin扩展相同的抽象类以使用此解决方案。或者,您可以将该save_formset方法添加到专门包含内联的ModelAdmin。
答案 1 :(得分:1)
无论操作在何处/如何操作,我都希望将用户设置在我的所有模型上。我花了很长时间才弄清楚,但这里是如何使用中间件在任何模型上设置它:
"""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 instance.has_attr('created_by') and not instance.created_by:
instance.created_by = user
if instance.has_attr('modified_by'):
instance.modified_by = user
答案 2 :(得分:1)
除了心灵的回答;当created_by字段恰好有null=True
时,not instance.created_by
会出错。我使用instance.created_by_id is None
来避免这种情况。
(我宁愿发布这个作为对答案的评论,但我目前的声誉不允许......)