Django InlineModelAdmin - 在保存请求时设置内联字段(自动设置用户字段)(save_formset vs save_model)

时间:2010-06-10 16:04:06

标签: python django django-admin inline

我有两个模型,一个MainModel和一个相关的InlineModel,我想在管理员中显示为内联。此InlineModel可用于,例如,记录模型,并应跟踪登录的管理员用户进行更改。虽然这看起来很简单(实际上,当用户字段是MainModel的一部分时,文档显示了这个例子),当字段在内联时,我似乎无法掌握它。

具体来说,我的目标是:

  1. 用户编辑MainModel
  2. 用户添加InlineModel,未填写用户字段
  3. 用户按保存
  4. 代码填写新创建的InlineModel实例的用户字段
  5. (Bonus!用户字段对于现有实例是只读的,对新内联隐藏)
  6. 我的问题:

    1. 这是对的吗?对于InlineModelAdmin实例
    2. ,不会调用它的bas save_model
    3. 这样做是否允许我保存而不会导致错误? (用户是必需的,验证标记它)
    4. 如何隐藏新内联的用户输入字段,并将其只读为现有内联?
    5. 以下是我目前的想法:


      #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()
      

3 个答案:

答案 0 :(得分:9)

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

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元组中包含'user'字段,但是这不会向作者显示现有的InlineModel实例。 (编辑:将'user'添加到readonly_fields在这里工作)

  2. (编辑)如何使现有的内联呈现'数据'为只读,但在添加新的内联时仍能编辑它?

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

回答奖励问题:“如何将现有内联呈现'数据'作为只读,但在添加新内联时仍能编辑它?”:

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

#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]
    ...