How to display Model Object Count In Django Admin Index - django

I am trying to display the count of objects of each model. For this i have edited env > lib > django > contrib > templates > admin > app_list.html, bellow is the code. I am having to doubts here.
I know this is not optimal solution where editing directly in env django folder. So how i can edit the app_list.html so that i can display the count.
I tried {{model}}, but was not able to display count, always come as blank as you can see in image.
Possible out i tried in template html-
{{model}}
Object - {'name': 'Exam categorys', 'object_name': 'ExamCategory', 'perms': {'add': True, 'change': True, 'delete': True, 'view': True}, 'admin_url': '/admin/quiz/examcategory/', 'add_url': '/admin/quiz/examcategory/add/', 'view_only': False}
{{model.count}}
Object -
{{model.all}}
Object -
{{model.objects.all}}
Object -
----------------------------------------------------------------
env > lib > django > contrib > templates > admin > app_list.html
----------------------------------------------------------------
{% load i18n %}
{% if app_list %}
{% for app in app_list %}
<div class="app-{{ app.app_label }} module{% if app.app_url in request.path %} current-app{% endif %}">
<table>
<caption>
{{ app.name }}
</caption>
{% for model in app.models %}
<tr class="model-{{ model.object_name|lower }}{% if model.admin_url in request.path %} current-model{% endif %}">
{% if model.admin_url %}
<th scope="row"><a href="{{ model.admin_url }}"{% if model.admin_url in request.path %} aria-current="page"{% endif %}>{{ model.name }}</a></th>
{% else %}
<th scope="row">{{ model.name }}</th>
{% endif %}
<!-- Temporary added this line to get count from model -->
{% if model.add_url %}
<td>Object - {{ model.count }}</td>
{% else %}
<td></td>
{% endif %}
{% if model.add_url %}
<td>{% translate 'Add' %}</td>
{% else %}
<td></td>
{% endif %}
{% if model.admin_url and show_changelinks %}
{% if model.view_only %}
<td>{% translate 'View' %}</td>
{% else %}
<td>{% translate 'Change' %}</td>
{% endif %}
{% elif show_changelinks %}
<td></td>
{% endif %}
</tr>
{% endfor %}
</table>
</div>
{% endfor %}
{% else %}
<p>{% translate 'You don’t have permission to view or edit anything.' %}</p>
{% endif %}

Related

Django 2.2 How to disable checkboxes in list view

Django 2.2
I have a list view controlled by admin.py class. No custom template, all default. I can control what fields from the table should be shown in the view with this:
fields = ('myfield1','myfield2', ...).
Each row in the list table has a checkbox in the first column, the source looks like this:
<td class="action-checkbox">
<input type="checkbox" name="_selected_action" value="123" class="action-select">
</td>
My questions are:
How to disable those checkboxes (preferably, from Django code, without introducing a custom template) ?
Can it be done for SOME of the checkboxes (let's say I have a list of pk ids for the rows I don't want to see checkboxes.)
You can delete Items with those CheckBoxes, but if you want to customize your own admin page to override it
You can use this doc https://docs.djangoproject.com/en/3.0/ref/contrib/admin/#admin-overriding-templates
This question is 2 years old now, but for the case someone still needs it, the following code works to overwrite the change-list_results.html:
{% load i18n static %}
{% if result_hidden_fields %}
<div class="hiddenfields">{# DIV for HTML validation #}
{% for item in result_hidden_fields %}{{ item }}{% endfor %}
</div>
{% endif %}
{% if results %}
<div class="results">
<table id="result_list">
<thead>
<tr>
{% for header in result_headers %}
{% if "checkbox" in header.text %}
{% else %}
<th scope="col" {{ header.class_attrib }}>
{% if header.sortable %}
{% if header.sort_priority > 0 %}
<div class="sortoptions">
<a class="sortremove" href="{{ header.url_remove }}" title="{% translate "Remove from sorting" %}"></a>
{% if num_sorted_fields > 1 %}<span class="sortpriority" title="{% blocktranslate with priority_number=header.sort_priority %}Sorting priority: {{ priority_number }}{% endblocktranslate %}">{{ header.sort_priority }}</span>{% endif %}
</div>
{% endif %}
{% endif %}
<div class="text">{% if header.sortable %}{{ header.text|capfirst }}{% else %}<span>{{ header.text|capfirst }}</span>{% endif %}</div>
<div class="clear"></div>
{% endif %}
</th>{% endfor %}
</tr>
</thead>
<tbody>
{% for result in results %}
{% if result.form and result.form.non_field_errors %}
<tr><td colspan="{{ result|length }}">{{ result.form.non_field_errors }}</td></tr>
{% endif %}
<tr>
{% for item in result %}
{% if "_selected_action" in item %}
{% else %}
{{ item }}
{% endif %}
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
It stops stops the output of the for loops if theres a checkbox in there. --> It just removes the checkboxes.

Displaying label on first form of Django formset only

This is a super straightforward question but I can't seem to find any concise answer it. I have a Django formset that displays different tags associated with an object. Here is the form:
class TagForm(forms.Form):
def __init__(self, *args, **kwargs):
tags = kwargs.pop('tags')
super(TagForm, self).__init__(*args, **kwargs)
self.fields['tags'] = forms.ChoiceField(choices=[(tag, tag) for tag in tags], label="Tags")
I'm rendering the formset using the following code:
<li class="list-group-item">
<ul class="list-inline" id="tag-group">
{{ tag_formset.management_form }}
{% for tag_form in tag_formset %}
<li class="list-inline-item">
{{ tag_form.tags.label_tag }}
{{ tag_form.tags }}
</li>
{% endfor %}
</ul>
</li>
My problem is that this creates a label for each tag. Since this is an inline list, I'd only like to display the label prior to the first tag (and no others). I can't find any straightforward way to do this (without modifying the for loop with explicit logic checking if it is the first form being rendered). I optimistically tried to modify my rendering code to the following:
<li class="list-group-item">
<ul class="list-inline" id="tag-group">
{{ tag_formset.management_form }}
{{ tag_form.empty_form.label_tag }}
{% for tag_form in tag_formset %}
<li class="list-inline-item">
{{ tag_form.tags }}
</li>
{% endfor %}
</ul>
</li>
but this didn't display any labels at all. Is there an idiomatic way to only display the form label prior to the first form in a formset?
The code below is working for me. The main idea is simple. Make a Table and in the headers put the tags. and in the table body put only the data. Try it and let me know.
{% for f1 in formset %}
{{ f1.management_form|crispy }}
{% crispy f1 %}
{% endcomment %}
<table{% if form_id %} id="{{ form_id }}_table" {% endif%} class="table table-striped table-condensed">
<thead>
{% if formset.readonly and not formset.queryset.exists %}
{% else %}
<tr>
<td>
</td>
{% for field in formset.forms.0 %}
{% if field.label and not field.is_hidden %}
<th for="{{ field.auto_id }}"
class="control-label {% if field.field.required %}requiredField{% endif %}">
{{ field.label|safe }}{% if field.field.required %}<span
class="asteriskField">*</span>{% endif %}
</th>
{% endif %}
{% endfor %}
</tr>
{% endif %}
</thead>
<tbody>
{% comment %} <tr class="hidden empty-form">
{% for field in formset.empty_form %}
{% include 'bootstrap/field.html' with tag="td" form_show_labels=False %}
{% endfor %}
</tr> {% endcomment %}
{% for form2 in formset2 %}
{% if form2_show_errors and not form2.is_extra %}
{% include "bootstrap/errors.html" %}
{% endif %}
<tr>
<td>
<a class="btn btn-info pull-right" {% comment %}
href="{% url 'set_final' formfs.pk %}/?next={% url 'update-well-view' form.pk %}">
{% endcomment %}
href="{% url 'Scouts-home' %}"> Set Final
</a>
</td>
{% for field in form2 %}
{% include 'bootstrap/field.html' with tag="td" form2_show_labels=False %}
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>

How to I get the length or size or number of fields in a form in a django template?

I would like to write a loop like this, so that I can spread the form fields out in a table. :
{% load widget_tweaks %}
{% load mathfilters %}
{% load get_range %}
{% for k in form|length|div:5|floatformat|add:1|get_range %}
<tr>
{% for field in form %}
{% if forloop.counter >= k|mul:5 and forloop.counter <= k|mul:5|add:4 %}
<th>{{ field.label_tag }}{{ field.errors }}</th>
{% endif %}
{% endfor %}
</tr>
<tr>
{% for field in form %}
{% if forloop.counter >= k|mul:5 and forloop.counter <= k|mul:5|add:4 %}
<td>{{ field|add_class:"span4" }}</td>
{% endif %}
{% endfor %}
</tr>
{% endfor %}
This doesn't work, but because the code above fails on form|length. In order for this to work, I need to get, in a template, the number of fields in a form. Does anyone know how to do this? I've searched all over but can't find anything. The following do NOT work:
form.len
form.length
form|length
Thanks!
I'm really not sure what you are looking for, but it sounds like this:
{% for field in form %}
<tr>
{% if forloop.counter0|divisibleby:5 %}
<th class="span4">{{ field.label_tag }}{{ field.errors }}</th>
{% else %}
<th>{{ field.label_tag }}{{ field.errors }}</th>
{% endif %}
</tr>
{% endfor%}
{% for field in form %}
<tr>
{% if forloop.counter0|divisibleby:5 %}
<td>{{ field|add_class:"span4" }}</td>
{% else %}
<td>{{ field }}</td>
</tr>
{% endfor %}
I dont like this code, but it was my first idea.
{% for field in form %}
{% if forloop.last %}
{{ forloop.counter }}
{% endif %}
{% enfor %}
form.fields I believe.
{% for field_name in form.fields %}
thanks for your suggestions - they helped! Here is what finally worked for me:
{% for field in form %}
{% if forloop.counter0|divisibleby:5 %}
<tr>
{% for field in form %}
{% if forloop.counter0 >= forloop.parentloop.counter0 and forloop.counter0 <= forloop.parentloop.counter0|add:4 %}
<th>{{ field.label_tag }}{{ field.errors }} </th>
{% endif %}
{% endfor %}
</tr>
<tr>
{% for field in form %}
{% if forloop.counter0 >= forloop.parentloop.counter0 and forloop.counter0 <= forloop.parentloop.counter0|add:4 %}
<td>{{ field }}</td>
{% endif %}
{% endfor %}
</tr>
{% endif %}
{% endfor %}

Custom formset templates in Django

I am using a Django formset for this model:
class Book(models.Model):
book_id=models.AutoField(primary_key=True,unique=True)
book_name=models.CharField(max_length=30)
publisher_name=models.CharField(max_length=40)
author=models.ForeignKey(Author)
The formset is defined thus:
BookFormset = inlineformset_factory(Author, Book,
fields=('book_id','book_name', 'publisher_name'), extra=1,
can_delete=False)
The template is:
{{ formset.non_form_errors.as_ul }}
<table id="formset" class="form">
{% for form in formset.forms %}
{% if forloop.first %}
<thead><tr>
{% for field in form.visible_fields %}
<th>{{ field.label|capfirst }}
{% endfor %}
</tr></thead>
{% endif %}
<tr class="{% cycle row1,row2 %}">
{% for field in form.visible_fields %}
<td>
{# Include the hidden fields in the form #}
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{{ field.errors.as_ul }}
{{ field }}
</td>
{% endfor %}
</tr>
{% endfor %}
</table>
The fields are displayed column-wise, but I would like them to be displayed row-wise.
The above code produces output like this:
Book name Publisher name
book_field Publisher_field
I would like the output to look like this:
Book name book_field
Publisher name Publisher_field
How can I do this?
In your template, you have two <tr> elements, each of which contains a loop over form.visible_fields, each iteration of which generates a single <th> or <td>.
Change this round so that you have a single loop over form.visible_fields, each iteration of which contains a single <tr> element containing a <th> and a <td>. Like this:
<table id="formset" class="form">
{% for form in formset.forms %}
{% for field in form.visible_fields %}
<tr class="{% cycle row1,row2 %}">
<th>{{ field.label|capfirst }}</th>
<td>
{# Include the hidden fields in the form #}
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{{ field.errors.as_ul }}
{{ field }}
</td>
</tr>
{% endfor %}
{% endfor %}
</table>
The examples above seem to show a column-wise layout, which appears to be the default layout when a formset renders itself.
To make it row-wise, use something like this:
<table>
{% for form in formset.forms %}
{% if forloop.first %}
<thead>
{% for field in form.visible_fields %}
<th>{{ field.label }}</th>
{% endfor %}
</thead>
<tbody>
{% endif %}
<tr class="{% cycle row1,row2 %}">
{% for field in form.visible_fields %}
<td>
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{{ field.errors.as_ul }}
{{ field }}
</td>
{% endfor %}
</tr>
{% if forloop.last %}
</tbody>
{% endif %}
{% endfor %}
</table>

Django Admin: Customizing the inline template (tabular.html)

I'm trying to follow the guidelines in this answer, but I'm getting stuck with how to edit the template.
The relevant part of my admin.py:
SegmentFormset = forms.models.inlineformset_factory(Division,Segment)
class DivisionForm(forms.ModelForm):
def __init__(self, **kwargs):
super(DivisionForm, self).__init__(**kwargs)
self.segment_formset = SegmentFormset(instance=self.instance, data=self.data,
prefix=self.prefix)
def is_valid(self):
return (super(DivisionForm, self).is_valid() and
self.segment_formset.is_valid())
def save(self, commit=True):
assert commit == True
res = super(DivisionForm, self).save(commit=commit)
self.segment_formset.save()
return res
class DivisionInline(admin.TabularInline):
model = Division
form = DivisionForm
template = 'competitions/admin/tabular.html'
class CompetitionAdmin(VersionAdmin):
inlines = [DivisionInline,]
The relevant part of my template:
{% for fieldset in inline_admin_form %}
{% for line in fieldset %}
{% for field in line %}
<td class="{{ field.field.name }}">
{{ field.field.errors.as_ul }}
{{ field.field }}
</td>
{% endfor %}
{% endfor %}
<td>My segment formset should be here</td>
{% endfor %}
What I can't figure out is how to access the segment formset. I've experimented with all of the variable names and none of them are my DivisionForm. The division formset is the {{fieldset.formset}} variable and that's as far as I've been able to get.
Edit 1:
Actually, the relevant part of the template is a bit longer ;) Putting in more code:
<tbody>
{% for inline_admin_form in inline_admin_formset %}
{% if inline_admin_form.form.non_field_errors %}
<tr><td colspan="{{ inline_admin_form.field_count }}">{{ inline_admin_form.form.non_field_errors }}</td></tr>
{% endif %}
<tr class="{% cycle row1,row2 %} {% if inline_admin_form.original or inline_admin_form.show_url %}has_original{% endif %}">
<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 %}{% trans "View on site" %}{% endif %}
</p>{% endif %}
{% if inline_admin_form.has_auto_field %}{{ inline_admin_form.pk_field.field }}{% endif %}
{{ inline_admin_form.fk_field.field }}
{% spaceless %}
{% for fieldset in inline_admin_form %}
{% for line in fieldset %}
{% for field in line %}
{% if field.is_hidden %} {{ field.field }} {% endif %}
{% endfor %}
{% endfor %}
{% endfor %}
{% endspaceless %}
</td>
{% for fieldset in inline_admin_form %}
{% for line in fieldset.formset %}
{% for field in line %}
<td class="{{ field.field.name }}">
{{ field.field.errors.as_ul }}
{{ field.field }}
</td>
{% endfor %}
{% endfor %}
<td>My segment formset should be here</td>
{% endfor %}
{% if inline_admin_formset.formset.can_delete %}
<td class="delete">{% if inline_admin_form.original %}{{ inline_admin_form.deletion_field.field }}{% endif %}</td>
{% endif %}
</tr>
{% endfor %}
</tbody>
Formsets are like lists, so you can recurse it like
{% for form in fieldset.formset %}
{{ form.as_p }}
{% endfor %}