覆盖Django InlineModelAdmin上的save_model

Tre*_*ier 17 python django

我的模型有一个user需要从当前登录用户自动填充的字段.如果字段在标准ModalAdmin中,我可以按照此处的指定运行它user,但如果我正在使用的模型是在InlineModelAdmin管理员内部的另一个模型的记录中保存,则不会.

raf*_*man 13

这是我认为最好的解决方案.花了一段时间找到它...这个答案给了我线索:https://stackoverflow.com/a/24462173/2453104

在你的admin.py上:

class YourInline(admin.TabularInline):
    model = YourInlineModel
    formset = YourInlineFormset

    def get_formset(self, request, obj=None, **kwargs):
        formset = super(YourInline, self).get_formset(request, obj, **kwargs)
        formset.request = request
        return formset
Run Code Online (Sandbox Code Playgroud)

在您的forms.py上:

class YourInlineFormset(forms.models.BaseInlineFormSet):
    def save_new(self, form, commit=True):
        obj = super(YourInlineFormset, self).save_new(form, commit=False)
        # here you can add anything you need from the request
        obj.user = self.request.user

        if commit:
            obj.save()

        return obj
Run Code Online (Sandbox Code Playgroud)

  • 这确实是最简单,最好的方法 (2认同)

Emi*_*ron 5

我知道我参加晚会很晚,但是这是我的情况以及我的想法,这可能对将来的其他人有用。

我有4个需要当前登录用户的内联模型。

  • 2作为created_by类型字段。(创建时设置一次)
  • 和另外2个作为closed_by类型字段。(仅根据条件设置)

我使用了rafadev提供的答案,并使其成为一个简单的mixin,使我能够在其他地方指定用户字段名称。

forms.py中的通用表单集

from django.forms.models import BaseInlineFormSet

class SetCurrentUserFormset(forms.models.BaseInlineFormSet):
    """
    This assume you're setting the 'request' and 'user_field' properties
    before using this formset.
    """
    def save_new(self, form, commit=True):
        """
        This is called when a new instance is being created.
        """
        obj = super(SetCurrentUserFormset, self).save_new(form, commit=False)
        setattr(obj, self.user_field, self.request.user)
        if commit:
            obj.save()
        return obj

    def save_existing(self, form, instance, commit=True):
        """
        This is called when updating an instance.
        """
        obj = super(SetCurrentUserFormset, self).save_existing(form, instance, commit=False)
        setattr(obj, self.user_field, self.request.user)
        if commit:
            obj.save()
        return obj
Run Code Online (Sandbox Code Playgroud)

您的admin.py中的Mixin类

class SetCurrentUserFormsetMixin(object):
    """
    Use a generic formset which populates the 'user_field' model field
    with the currently logged in user.
    """
    formset = SetCurrentUserFormset
    user_field = "user" # default user field name, override this to fit your model

    def get_formset(self, request, obj=None, **kwargs):
        formset = super(SetCurrentUserFormsetMixin, self).get_formset(request, obj, **kwargs)
        formset.request = request
        formset.user_field = self.user_field
        return formset
Run Code Online (Sandbox Code Playgroud)

如何使用它

class YourModelInline(SetCurrentUserFormsetMixin, admin.TabularInline):
    model = YourModel
    fields = ['description', 'closing_user', 'closing_date']
    readonly_fields = ('closing_user', 'closing_date')
    user_field = 'closing_user' # overriding only if necessary
Run Code Online (Sandbox Code Playgroud)

小心...

...因为此混合代码将每次为每个用户设置当前登录的用户。如果只需要在创建或特定更新时填充字段,则需要在模型保存方法中进行处理。这里有些例子:

class UserOnlyOnCreationExampleModel(models.Model):
    # your fields
    created_by = # user field...
    comment = ...

    def save(self, *args, **kwargs):
        if not self.id:
            # on creation, let the user field populate
            self.date = datetime.today().date()
            super(UserOnlyOnCreationExampleModel, self).save(*args, **kwargs)
        else:
            # on update, remove the user field from the list
            super(UserOnlyOnCreationExampleModel, self).save(update_fields=['comment',], *args, **kwargs)
Run Code Online (Sandbox Code Playgroud)

或者,如果仅在设置了特定字段(例如boolean field closed)时才需要用户,则:

def save(self, *args, **kwargs):

    if self.closed and self.closing_date is None:
        self.closing_date = datetime.today().date()
        # let the closing_user field set
    elif not self.closed :
        self.closing_date = None
        self.closing_user = None # unset it otherwise

    super(YourOtherModel, self).save(*args, **kwargs)  # Call the "real" save() method.
Run Code Online (Sandbox Code Playgroud)

可能使该代码更通用,因为我对python来说还很陌生,但是现在这就是我的项目中的内容。


Vik*_*ica 0

其他模型能拯救用户吗?在这种情况下,您可以使用该post_save信号将该信息添加到内联模型集中。