How to omit object name from Django's TabularI

2019-03-10 19:58发布

I'm using Django's TabularInline admin view to edit category objects related to a main topic object, as shown here:

enter image description here

Is there a way to not show the rendered names of the objects ("General Questions", "Media Handling and Margins", etc. in this example), without creating a custom admin template? In other words, I just want to show a clean grid of input fields.

I found the relevant rendering code here, at this fragment:

   ...
        <td class="original">
          {% if inline_admin_form.original or inline_admin_form.show_url %}<p>
          {% if inline_admin_form.original %} {{ inline_admin_form.original }}{% endif %}
          {% if inline_admin_form.show_url %}<a href="../../../r/{{ inline_admin_form.original_content_type_id }}/{{ inline_admin_form.original.id }}/">{% trans "View on site" %}</a>{% endif %}
            </p>{% endif %}
   ...

Is there a short, clever way to omit the {{ inline_admin_form.original }} or have it return Null?

6条回答
神经病院院长
2楼-- · 2019-03-10 20:12

You could use css to hide the paragraph

查看更多
姐就是有狂的资本
3楼-- · 2019-03-10 20:19

I thought I'd chime in that editing your template is going to be the easiest.

I tried iterating over the formsets in render_change_form but unfortunately, the major problem is that InlineAdminForms are constructed dynamically upon iteration in the template so you can't just set inlineadminform.original = None or modify the context.

They don't even exist until assigned a variable in the template.

# InlineAdminFormset
def __iter__(self):
    for form, original in zip(self.formset.initial_forms, self.formset.get_queryset()):
        yield InlineAdminForm(self.formset, form, self.fieldsets,
            self.opts.prepopulated_fields, original, self.readonly_fields,
            model_admin=self.model_admin)

and the only easily non-hackishly accessible hook we have there is overriding InlineAdminFormset.formset.get_queryset() which breaks other things.

Can I share some code nobody should ever really look at but works and makes me crack up laughing? I owe you one payne. Hope I can get to sleep tonight.

查看更多
我想做一个坏孩纸
4楼-- · 2019-03-10 20:20

@sjaak-schilperoort Nice one! CSS is indeed the 'trick' to use. Example of the class Foo which has Bar as inline.

static/css/hide_admin_original.css:

td.original p {
  visibility: hidden
}

.inline-group .tabular tr.has_original td {
    padding-top: 5px;
}

admin.py:

class FooAdmin(admin.ModelAdmin):
  inlines = [ BarInline, ]
  class Media:
    css = { "all" : ("css/hide_admin_original.css",) }

admin.site.register(Foo, FooAdmin)
查看更多
聊天终结者
5楼-- · 2019-03-10 20:23

I took a slightly different approach. It's a little hackish. This replaces the "original" string with a blank string, so the td for class=original still gets rendered leaving a gap above the edit boxes.

I like the CSS solution better (I had to use 'padding-top: 5px;' to get the rendering right).

models.py:

class Model(model.Model):
  general_questions = models.TextField()
  _hide = False

  def __unicode__(self):
    if _hide:
      return ''

admin.py:

class ModelInline(admin.TabularInline):
    model = Model
    extra = 0

class ModelAdmin(admin.ModelAdmin):
  inlines = [ModelInline, ]

  def render_change_form(self, request, context, *args, **kwargs):
    for formset in context['inline_admin_formsets']:
      qs = formset.formset.queryset
        for model_obj in qs:
          model_obj._hide = True

  return super(ModelAdmin, self).render_change_form(request, context, *args, **kwargs)
查看更多
做自己的国王
6楼-- · 2019-03-10 20:30

the simplest way to do so is by adding a css to the template file, the answer by Rick van der Zwet is the best one

查看更多
我命由我不由天
7楼-- · 2019-03-10 20:32

In case anyone is looking to hide the header on a StackedInline, I used Rick´s approach but adding this css:

div.inline-related h3{
   visibility: hidden;
   height: 0;
}
查看更多
登录 后发表回答