Reputation: 14187
I'm using Django's TabularInline
admin view to edit category objects related to a main topic object, as shown 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?
Upvotes: 41
Views: 13477
Reputation: 11
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
Upvotes: 1
Reputation: 6375
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;
}
Upvotes: 1
Reputation: 961
@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)
Upvotes: 69
Reputation: 1061
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).
class Model(model.Model):
general_questions = models.TextField()
_hide = False
def __unicode__(self):
if _hide:
return ''
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)
Upvotes: 4
Reputation: 118498
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 InlineAdminForm
s 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.
Upvotes: 6