【问题标题】:Django InlineModelAdmin - set inline field from request on save (set user field automatically) (save_formset vs save_model)Django InlineModelAdmin - 在保存时从请求中设置内联字段(自动设置用户字段)(save_formset vs save_model)
【发布时间】:2011-03-02 06:20:14
【问题描述】:

我有两个模型,一个 MainModel 和一个相关的 InlineModel,我想在管理员中显示为内联模型。这个 InlineModel 可以用于,比如说,对模型做注释,并且应该跟踪登录的管理员用户所做的更改。虽然这看起来很简单(事实上,当用户字段是 MainModel 的一部分时,文档显示了一个示例),但当该字段位于内联时,我似乎无法掌握它。

具体来说,我的目标是:

  1. 用户编辑 MainModel
  2. 用户添加了一个 InlineModel,而不是填写用户字段
  3. 用户按下保存键
  4. 代码填写新创建的 InlineModel 实例的用户字段
  5. (奖励!用户字段对于现有实例是只读的,对于新的内联是隐藏的)

还有我的问题:

  1. 这是正确的吗? InlineModelAdmin 实例也不会调用它的基础 save_model
  2. 这样做是否可以让我保存而不会导致错误? (用户是必需的,验证标记它)
  3. 如何隐藏新内联的用户输入字段,并将现有内联设为只读?

这是我目前的想法:


#models.py
class MainModel(models.Model):
    some_info = models.IntegerField()

class InlineModel(models.Model):
    main = models.ForeignKey(MainModel)
    data = models.CharField(max_length=255)
    user = models.ForeignKey('auth.User')

#admin.py
class InlineModelInline(admin.TabularInline):
    model = InlineModel
    fields = ('data', 'user')
    #readonly_fields = ('data', 'user') #Bonus question later

class MainModelAdmin(admin.ModelAdmin):
    list_display = ('id', 'some_info')
    inlines = [InlineModelInline]

    #def save_model(self, request, obj, form, change):
        #http://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.save_model
        #Only called for MainModel, not for any of the inlines
        #Otherwise, would be ideal

    def save_formset(self, request, form, formset, change):
        #http://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.save_formset
        #Experimenting showd this is called once per formset (where the formset is a group of inlines)
        #See code block at http://code.djangoproject.com/browser/django/tags/releases/1.2.1/django/contrib/admin/options.py#L894
        if not isinstance(formset.model, InlineModel):
            return super(MainModelAdmin, self).save_formset(request, form, formset, change)
        instances = formset.save(commit=False)
        for instance in instances:
            if not instance.pk:
                instance.user = request.user
        instance.save()
        formset.save_m2m()

【问题讨论】:

    标签: python django django-admin inline


    【解决方案1】:

    我已经解决了问题的前半部分:

    def save_formset(self, request, form, formset, change):
        if formset.model != InlineModel:
            return super(MainModelAdmin, self).save_formset(request, form, formset, change)
        instances = formset.save(commit=False)
        for instance in instances:
            if not instance.pk:
                instance.user = request.user
            instance.save()
        formset.save_m2m()
    

    现在我对奖励行为感兴趣:

    1. 由于验证规则,我需要在添加新内联时选择用户。我最好的猜测是不要在我的 InlineModelInline.fields 元组中包含“用户”字段,但这不会显示现有 InlineModel 实例的作者。 (编辑:在这里将“用户”添加到 readonly_fields 有效)

    2. (编辑)如何使现有内联将“数据”呈现为只读,但在添加新内联时仍可以对其进行编辑?

    【讨论】:

    • 我自己注意一下,这个save_formset是admin.ModelAdmin的一个方法,它会处理ModelAdmin中分配的所有子Inlines。
    • 感谢您在这里提出问题/回答。至于“奖励”功能——在 django 模型中将用户外键标记为可编辑 = False 后,内联表单集通过了验证,用户字段仍然设置,一切都是洁净的。 user = models.ForeignKey(User, editable=False)
    • 嗯,完全忘记了模型中的 editable=False 。很好的收获,谢谢。
    • 这会破坏删除内联对象。
    【解决方案2】:

    它对我有用。 This 方法不允许我删除内联项。

    def save_formset(self, request, form, formset, change):
        for form in formset.forms:
            form.instance.user = request.user
        formset.save()
    

    【讨论】:

      【解决方案3】:

      回答额外问题:“如何使现有的内联将‘数据’呈现为只读,但在添加新内联时仍能对其进行编辑?”:

      我对同一个模型使用两个内联:

      #admin.py
      class InlineModelInline(admin.TabularInline):
          model = InlineModel
          extra = 1
          max_num = 1
      
      #admin.py
      class InlineModelExistingInline(admin.TabularInline):
          model = InlineModel
          readonly_fields = ('data', 'user') #All Fields here except pk
          can_delete = False
          extra = 0
          max_num = 0
      
      class MainModelAdmin(admin.ModelAdmin):
          ...
          inlines = [InlineModelInline, InlineModelExistingInline]
          ...
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-08-20
        • 2017-11-15
        • 1970-01-01
        • 2012-06-12
        • 1970-01-01
        • 2011-07-25
        • 2018-06-12
        • 2015-11-27
        相关资源
        最近更新 更多