Data accessing & display in Django - django

I'm having trouble accessing database data in another template
different than django administration. In the administration page I
get results:
But when I try to display them in another template:
(No results available)
Here's how my urls.py admin page and template urls looks like:
urlpatterns = [
path('admin/', admin.site.urls),
path('lista/', views.entitats, name = 'lista_entitats')
]
Here's how my admin.py call to entity list and register looks like:
class EntitatAdmin(admin.ModelAdmin):
list_display = ('codi', 'nom', 'adreça', 'cp', 'correu', 'inspector')
inlines = [DiaLliureDisposicioInline, VisitesDirectorCentreInline, ExitEscolarInline, ObresCentreInline, OfertaEstudisInline, NEE_alumnatInline, FormacioInline, ProjectesInline, ProfessorsInline, DespesesFuncionamentInline]
search_fields=('nom',)
list_per_page=5
admin.site.register(Entitat, EntitatAdmin)
In my views.py this is how I ask for the template (and where I feel I'm not getting db information well):
from entitats.models import Entitat
def entitats(request):
lista_entitats = Entitat.objects.all()
context = {'llista_entitats': lista_entitats}
return render(request, 'entitats.html', context)
And finally my template, where I try to display the list of entities:
{% if context.llista_entitats %}
<ul>
{% for question in objects_list %}
<li>{{ question.question_text }}</li>
{% endfor %}
</ul>
{% else %}
<p>Ninguna entidad disponible.</p>
{% endif %}
Sorry if it's loong, I'll delete if there's something not necessary, and THANKYOU in advance.

You don't need context.variable_name syntax in template to check variable value, just use:
{% if llista_entitats %}
instead of
{% if context.llista_entitats %}
Also since your variable is llista_entitats it should be:
{% for question in llista_entitats %}
<li>{{ question.question_text }}</li>
{% endfor %}
Note I replaced objects_list with llista_entitats and entitat.id with question.id.

Related

{% url ... %} templatetag in Django included template not seeing variable

I'm experiencing strange behaviour in an included template which I can't figure out.
urls.py
urlpatterns = (
path(
"items/",
views.list_view,
name="list-view",
),
path(
"item/<int:pk>/",
views.detail_view,
name="detail-view",
),
)
views.py
def list_view(request):
items = Item.objects.all()
return render(request, "parent_template.html", context={"items": items})
def detail_view(request, pk):
item = get_object_or_404(Item, pk=pk)
return render(request, "detail_template.html", context={"item": item}
parent_template.html
{% for item in items %}
Parent: {{ item.pk }}
{% include 'child_template.html' %}
{% endfor %}
child_template.html
Child: {{ item.pk }}
URL: {% url 'detail-view' item.pk %}
I get a reverse error:
Reverse for '/test/url/<int:pk>/' with arguments '('',)' not found. 1 pattern(s) tried: ['test/url/(?P<pk>[0-9]+)/\\Z']
If however I remove the {% url ... %} template tag, it renders correctly and shows:
Parent: 1
Child: 1
So it's clear that item is in the context, but for some reason it isn't being passed to the templatetag.
I have also tried variations like:
{% for item in items %}
{% with new_item=item %}
{% include 'child_template.html' %}
{% endwith %}
{% endfor %}
Any ideas?
I am using Django 3.2.12
I just found the error - I was looking in the wrong place. My complete code looked like this:
parent.html
<!-- {% include 'child_template.html' %} -->
{% for item in items %}
{% with new_item=item %}
{% include 'child_template.html' %}
{% endwith %}
{% endfor %}
I didn't pay attention to the HTML comment at the top of the template. Obviously Django is still rendering the code on the server side and at that point does not have item in its context.

NoReverseMatch when using with tag to set URL pattern name

I am getting an error saying:
NoReverseMatch at /books/
Reverse for 'urlvar' not found. 'urlvar' is not a valid
view function or pattern name.
I guess the {% with %} tag is not working well in books/index.html
but I don't know how to solve this.
this is my code:
books/urls.py
from django.conf.urls import url
from books import views
urlpatterns = [
url(r'^$', views.BooksModelView.as_view(), name='index'),
url(r'^book/$', views.BookList.as_view(), name='book_list'),
url(r'^author/$', views.AuthorList.as_view(), name='author_list'),
url(r'^publisher/$', views.PublisherList.as_view(), name='publisher_list'),
url(r'^book/(?P<pk>\d+)/$', views.BookDetail.as_view(), name='book_detail'),
url(r'^author/(?P<pk>\d+)/$', views.AuthorDetail.as_view(), name='author_detail'),
url(r'^publisher/(?P<pk>\d+)/$', views.PublisherDetail.as_view(), name='publisher_detail'),
]
templates/books/index.html
{% extends 'base_books.html' %}
{% block content %}
<h2>Books Management Systemt</h2>
<ul>
{% for modelname in object_list %}
{% with 'books:'|add:modelname|lower|add:'_list' as urlvar %}
<li>{{ modelname }}</li>
{% endwith %}
{% endfor %}
</ul>
{% endblock %}
urlvar is a variable, so you use urlvar in the {% url %} tag instead of the string 'urlvar'.
<li>{{ modelname }}</li>
You can construct the URL pattern name in the tag if you prefer, or keep the with tag if you find that more readable.
<li>{{ modelname }}</li>
Since you are using the 'books: namespace when you reverse the urls, you should set app_name in your books/urls.py file.
from django.conf.urls import url
from books import views
app_name = 'books'
urlpatterns = [
...
]

Django Template Tag - Display only one value in nested for loop

I'm working on a Django web app and have the following query:
I have a model called 'AppQoSList' which lists the applications available to all users.
I have then another model called 'BasicAppSDWANProfiles' which has a ManyToMany relationship with 'AppQoSList' .
In short, it means a user can have multiple 'BasicAppSDWANProfiles' associated to his account and multiple AppQoS can be within a particular BasicAppSDWANProfiles:
class AppQoSList(models.Model):
app_qos_name = models.CharField(max_length=50, blank=None, null=True)
app_qos_description = models.CharField(max_length=500)
def __str__(self):
return u'%s' % self.app_qos_name
class BasicAppSDWANProfiles(models.Model):
profile_name = models.CharField(max_length=30)
profile_basic_app_qos = models.ManyToManyField(AppQoSList)
tenant_id = models.ForeignKey(Tenant, default=3)
I'm facing issue in my template when I try to display the list of apps available and the associated BasicAppSDWANProfile:
{% for app in apps %}
{% for profile_app in sdwan_prof %}
{% for specific_app in profile_app.profile_basic_app_qos.all %}
{% ifchanged specific_app.pk %}
{% if app.pk == specific_app.pk %}
<td><h4><span class="label label-primary">{{ profile_app.profile_name }}</span></h4></td>
{% else %}
<td><h4><span class="label label-warning">Not Assigned</span></h4></td>
{% endif %}
{% endifchanged %}
{% endfor %}
{% endfor %}
{% endfor %}
Issue with this code is that 'Not Assigned' is displayed 6 times on each row (which corresponds to the number of Apps found in BasicAppSDWANProfiles associated with this user) whereas I would like to display it only once:
Would you have any solution for this ?
Thanks in advance.
I was able to address this issue.
First I did clean up my view code to remove duplicate 'Not Assigned' values.
I pass to my template context a dictionary with only apps that have a profile assigned such as below:
{'citrix-static': 'DPS-BLACKLIST',
'exchange': 'DPS-BLACKLIST',
'ms-lync-audio': 'DPS-WHITELIST',
'ms-update': 'DPS-GREYLIST',
'rtp': 'DPS-WHITELIST',
'share-point': 'DPS-WHITELIST'}
In my template, I only loop through this dictionary:
{% for k,v in app_prof_assign.items %}
{% if app.app_qos_name == k %}
<td><h4><span class="label label-primary">{{ v }}</span></h4></td>
{% endif %}
{% endfor %}
I then simply check if the app is not in the profile dictionary, outside the loop:
{% if app.app_qos_name not in app_prof_assign %}
<td><h4><span class="label label-warning">Not Assigned</span></h4></td>
{% endif %}
Finally, I can get the table populated as expected:

Pass *args in django templates

I did use django pagination, but there is a problem with urls, here is my urls.py:
url(r'^/blog/$', blog_view.main, name='blog'),
url(r'^/blog/page/(?P<page_id>\d{0,9})$', blog.post, name='blog_page'),
My views.py:
def post(request, page_id=None):
posts = Posts.objects.all()
pageid = page_id
return render(request, 'base.html', {'posts': posts, 'pageid': pageid,})
My base.html which use bootstrap:
{% url 'blog_page' as blog_page %} # Blog page need follow patterns
<ul>
{% for post in posts %}
<li {% if request.path == htt://myblog.com/blog/page/5 %} class="active" {% endif %}>{{ post.title }}</li> # When I put blog_page django shows error. Help me how to put something to fix this condition.
{% endfor %}
</ul>
As stated in the documenation on HttpRequest objects,
HttpRequest.path is
A string representing the full path to the requested page, not including the scheme or domain.
Example: "/music/bands/the_beatles/"
(emphasis mine).
So, in your test, leave out the scheme (which you, btw, incorrectly wrote as htt://) and domain parts:
<li {% if request.path == /blog/page/5 %} class="active" {% endif %}>{{ post.title }}</li>

Django TemplateSyntaxErrors in generic date based Class views

I'm trying to update an old Django project (last working at Django 1.4) to use class based generic views (In Django 1.5)
The following used to work
Template:
{% block content %}
{% for month in date_list %}
<h2>{{ month|date:"F" }}</h2>
<h2>Blah</h2>
{% endfor %}
{% endblock %}
urls.py
urlpatterns = patterns('django.views.generic.date_based',
...
(r'^(?P<year>\d{4})/$', 'archive_year', dict(entry_info_dict,make_object_list=True), 'coltrane_entry_archive_year'),
(r'^(?P<year>\d{4})/(?P<month>\w{3})/$', 'archive_month', entry_info_dict, 'coltrane_entry_archive_month'),
...
)
however when I updated the urls.py to use generic class
class ArticleYearArchiveView(YearArchiveView):
queryset = Entry.objects.all()
date_field = "pub_date"
make_object_list = True
allow_future = True
urlpatterns = patterns('',
...
url(
r'^(?P<year>\d{4})/$',
ArticleYearArchiveView.as_view(),
name='coltrane_entry_archive_year'
),
url(
r'^(?P<year>\d{4})/(?P<month>\w{3})/$',
dates.MonthArchiveView.as_view(
template_name='coltrane/entry_archive_month.html',
queryset=Entry.objects.filter(status=Entry.LIVE_STATUS),
date_field='pub_date'),
name="coltrane_entry_archive_month"
),
...
)
the following TemplateSyntaxError starts appearing:
Could not parse some characters: year|,month||date:"b"
I can render the template and check what's being passed to coltrane_entry_archive_month using the following:
{% for month in date_list %}
{{ year }}
{{ month|date:"b" }}
{% endfor %}
I did notice that {{ year }} is being rendered as 'Jan. 1, 2013' rather than '2013' that matches the regex in the url. This I don't understand.
Futher I then tried to render the following:
{% for month in date_list %}
{% url "coltrane_entry_archive_month" "2013","apr" %}
{% endfor %}
No joy, this time the TemplateSyntaxError is:
Could not parse the remainder: ',"apr"' from '"2013","apr"'
Both generic class views and the url seem to be largish topics in Django so any pointers would be very welcome indeed!
The url tag doesn't take comma-separated arguments, just list them with a space.
{% for month in date_list %}
{% url "coltrane_entry_archive_month" "2013" "apr" %}
{% endfor %}
which means you need to change your actual template to
{% url "coltrane_entry_archive_month" year month|date:"b" %}
Also just a note (which I noticed you followed in your second example)
Don’t forget to put quotes around the function path or pattern name!
Changed in Django 1.5: The first parameter used not to be quoted,
which was inconsistent with other template tags. Since Django 1.5, it
is evaluated according to the usual rules: it can be a quoted string
or a variable that will be looked up in the context.