How to print model items in a template file? - django

I would like to show in the template file how many users I have and how many from them chose a language exam in English
How to display this information in an admin template file? (base.html) I tried something like this:
{{users.count()}}
I added an application "Userprofile" which is the form that user can choose an exam's language
class UserProfile(models.Model):
JEZYK = (
('DE', 'niemiecki'),
('FR', 'francuski'),
('EN', 'angielski'),
)
jezyk_egzaminu = models.CharField(max_length=6, choices=JEZYK, verbose_name='jezyk')
How can I show in a template file how many users chose 'EN', 'angielski' option ?
Thanks Catavaran I tried this solution but I do something wrong :(
I saved a file in a main project app "aplikacja" (aplikacja/aplikacja)
I added in base.html
{% load mytags %}
<div>Total users: {% user_count %}</div>
<div>English users: {% user_count 'EN' %}</div>
I get an error as return /admin/ site
Exception Type: TemplateSyntaxError
Exception Value:
'mytags' is not a valid tag library: Template library mytags not
found, tried
django.templatetags.mytags,django.contrib.admin.templatetags.mytags,django.contrib.staticfiles.templatetags.mytags

Pass the following context to the template:
{'users': UserProfile.objects.all(),
'en_users': UserProfile.objects.filter(jezyk_egzaminu='EN')}
And then call count() method:
<div>Total users: {{ users.count }}</div>
<div>English users: {{ en_users.count }}</div>
If you want to get user count in the admin's base.html then you have to create custom template tag:
from django import template
from myapp.models import UserProfile
register = template.Library()
#register.simple_tag
def user_count(lang=None):
users = UserProfile.objects.all()
if lang:
users = users.filter(jezyk_egzaminu=lang)
return users.count()
This code should be in the profil/templatetags/mytags.py file. And don't forget to create empty profil/templatetags/__init__.py file. See the docs for code layout.
Usage of this template tag in the base.html:
{% load mytags %}
<div>Total users: {% user_count %}</div>
<div>English users: {% user_count 'EN' %}</div>

Related

Get the value in queryset in Django template

I have used Django to develop a web app.
In the View function, I have rendered a queryset list to frontend.
In my case, title table is book information, and Material is the detailed info of this book is attached to which course and if this attached relation is "discard". is_discard is in Material table, and not the book discard or not. In Material table several books attached to a course, and discard status is not by book but by book-course pair, as some books may discard in one course but active in other courses
view.py:
def render_2(request):
books = Title.objects.filter(name=title).values()
query_results_book_is_discard =
Material.objects.filter(id=book_id).values('is_discard')
return render(request, 'main.html',
context=
{'query_results_book_is_discard':query_results_book_is_discard,
'book', books})
In the frontend, the query_results_book_is_discard variable shows the following format :
<QuerySet [{'is_discard': True}, {'is_discard': False}, {'is_discard': False}, {'is_discard': False}, {'is_discard': True}, {'is_discard': True}, {'is_discard': False}]>
The query_results_book_is_discard variable is in a loop in frontend Django template,
I want to use the forloop counter to get the value(True or False) to use if condition to check.
I haved tried in main.html:
{% for book in books %}
{% if query_results_book_is_discard.counter0 != False %}
...
and
{% if query_results_book_is_discard.counter0.is_discard != False %}
and
{% if query_results_book_is_discard.is_discard.counter0 != False %}
All failed.
How could I get the True or False value in query_results_book_is_discard to use if condition?
I would recommend you to create a custom template tag that allows you to access a specific index of a list in the template, as follows.
Your app file tree structure should have something like this:
your_app/
__init__.py
models.py
templatetags/
__init__.py
your_app_extras.py
views.py
Then, in your custom template tag file.
your_app_extras.py
from django import template
register = template.Library()
#register.filter
def index(indexable, i):
return indexable[i]
Then, in your template, load your custom template tags:
{% load your_app_extras %}
Then, in your for-loop, you use the following:
{% for book in books %}
{% with query_results_book=query_results_book_is_discard|index:forloop.counter0 %}
{% if query_results_book.is_discard %}
{% endwith %}
{% endfor %}

How to get a model by modelname in django template

I have model LandingSnippet that contains attribute ...model = CharField()..., and it is related to context keyword (for example cars in context below)
I have next code in my view
def GeneratedLanding(request):
snippets = LandingSnippet.objects.all().filter(view_on=True).order_by('order')
context = {
'snippets':snippets,
...
'cars':Car.objects.all(), # this is cars
...
return render(request,'qlanding/generateindex.html',{'context':context})
how i can get querySet cars that is in context by keyword cars as a string
for example
{{context}}
prints
{'snippets': <QuerySet [<LandingSnippet: Snippet1Title>, <LandingSnippet: 2 - about - Лучшая служба развозки детей>]>, 'services': <QuerySet []>, 'cars': <QuerySet []>, 'faqs': <QuerySet []>}
and
{{snippet.model}}
prints
cars
QUESTION:
How can i get the {{ context.cars }} ? I think something like context[snippet.model] where snippet.model='cars'
i want push it inside another template when include
{% if snippet.module %}
{% with "qlanding/snippets/module/"|add:snippet.module|add:".html" as path %}
{% include path with model=context[snippet.model] %} # But this is incorect while rendering
{% endwith %}
{% endif %}
you can write a simple template tag like this:
first in your app directory create a directory named templatetags this directory must contains an empty file named __init__.py
create a file with any name in this directory. for example load_from_context
write these code on this file
from django import template
register = template.Library()
#register.tag(name="GetFromContext")
def get_from_context(parser, token):
bits = token.split_contents()
node_list = parser.parse(('endGetFromContext',))
variable = bits[1]
return GetFromContextNode(node_list, variable)
class GetFromContextNode(template.Node):
def __init__(self, node_list, variable):
self.node_list = node_list
self.variable = variable
def render(self, context):
variable_value = template.Variable(self.variable).resolve(context)
with context.push():
context['model'] = context.get(variable_value)
return self.node_list.render(context)
then in your template you can use it like this
{% load load_from_context %}
{# any code in your template #}
{% GetFromContext snippet.model %}
{% include path %}
{% endGetFromContext %}
#vorujack , I get the same error still. but based on your solution I got next.
from Django import template
register = template.Library()
#register.simple_tag
def get_model_from_context(context,model_name):
return context[model_name]
and how I used in view
{% get_model_from_context context=context model_name=snippet.model as model %}
{% include "qlanding/snippets/module/"|add:snippet.module|add:".html" with model=model %}
many thanks for #vorujack

'My_Model' object is not iterable using customtag in django

I am new to Django and I am trying to make my data accessible to templates in different apps by creating custom tags in Django.
my model.py
from django.db import models
class my_Model(models.Model):
name = models.CharField(max_length=20)
age = models.CharField(max_length=20)
my custom tag file templatetag/custom_tag.py(why I did this is to make my data accessible to templates in different apps)
from django import template
from model_file.models import my_Model
register = template.Library()
#register.simple_tag
def get_custom_tag_fn():
return my_Model.objects.order_by('-pk')[0]
my html file
{% load custom_tag %}
{% get_custom_tag_fn as ct %}
{% for item in ct %}
<p> {{ item }} </p>
{% endfor %}
I am getting the error 'My_Model' object is not iterable. Any thought about how to solve this.
The problem is here:
return my_Model.objects.order_by('-pk')[0]
Model objects.order_by(...) returns queryset, alike to the list it`s a collection, so with [0] index you take the first object of that collection which of course is not iterable (it's just a single object). So, after that, when you trying to iterate:
{% for item in ct %}
...
you`re catching this error.

Wagtail not pulling through custom field panels

I'm overriding the wagtail AbstractFormField panel attribute in the following way:
...
before_input = RichTextField(verbose_name=_('before input'), blank=True)
after_input = RichTextField(verbose_name=_('after input'), blank=True)
panels = [
FieldPanel('label'),
FieldPanel('before_input'),
FieldPanel('after_input'),
FieldPanel('required'),
FieldPanel('field_type', classname="formbuilder-type"),
FieldPanel('choices', classname="formbuilder-choices"),
FieldPanel('default_value', classname="formbuilder-default"),
]
where the other panels are what comes out of the box.
This is working perfectly on the admin side and also saving as rich text into my database
I am pulling this through to my form in my template in the following way:
<form action="{% pageurl page %}" method="POST" class="lm-ls1" id="feedback-form">
{% csrf_token %}
{{ form.question1.help_text }} <!-- Simpler non interable way -->
{{ form.question1.before_input }}
<p>---------------</p>
{% for row in form.fields.values %}
{{row.choices}}
<p>---------------</p>
{{row.help_text}}
<p>---------------</p>
{{row.before_input}}
{% endfor %}
</form>
But I am only getting html output for the form panels excluding the before_input and after_input ones
I am getting through roughly the following:
Overall, how did you feel about the service you received today?
---------------
[('Very satisfied', 'Very satisfied'), ('Satisfied', 'Satisfied'),
('Neither satisfied nor dissatisfied', 'Neither satisfied nor dissatisfied'), ('Dissatisfied', 'Dissatisfied'), ('Very dissatisfied', 'Very dissatisfied')]
---------------
Overall, how did you feel about the service you received today?
---------------
---------------
How can I access the before_input field panel data stored in the _formfield wagtail table?
Bit late but hopefully this still helps you or someone else out there.
How Wagtail Forms Work
Wagtail forms provided to the view context for AbstractFormPage models is a fully instanced Django Form. This means that you will only ever find values in the form that can be given to a Django Form.
This includes fields, which are instances of Django's Fields (eg. CharField) and there is no simple way to add additional attributes to these fields.
You can see how the Form object is built in the Wagtail FormBuilder class definition.
1 - Make a Custom Template Tag
A somewhat simple way to get additional attributes on your FormField (Wagtail's FormField) is using a template tag.
Create a new file in in a folder templatetags in your app, and build a simple_tag that will take the form_page, the field (which will be a Django Field instance) and a string of the attribute name you want to get.
# myapp/templatetags/form_tags.py
from django import template
from django.utils.html import mark_safe
register = template.Library()
#register.simple_tag(name='form_field_attribute')
def form_field_attribute(form_page, field, attribute_name, default=None):
"""Return attribute on FormField where field matches 'field' provided."""
# field is a django Field instance
field_name = field.name
results = [
# if html is stored, need to use mark_safe - be careful though.
mark_safe(getattr(form_field, attribute_name, default))
# get_form_fields() is a built in function on AbstractFormPage
for form_field in form_page.get_form_fields()
# clean_name is property on AbstractFormField used for Django Field name
if form_field.clean_name == field_name]
if results:
return results[0]
return default
2 - Revise your form_page.html Template
In your template, cycle through your form (this is the Django Form instance) and use the template helper to get you the extra attributes you need. Example below, passing in page or self will work the same as they are both the instance of your FormPage.
<form action="{% pageurl page %}" method="POST" role="form">
{% csrf_token %}
{% for field in form %}
<div>{% form_field_attribute page field 'before_input' %}</div>
{{ field }}
<div>{% form_field_attribute page field 'after_input' %}</div>
{% endfor %}
<input type="submit">
</form>

Form labels not rendering with Django & WTForms

I'm trying to use WTForms with Django & a MongoEngine/MongoDB database backend. The forms are outputting properly, but I can't for the life of me get the labels to show up.
Here is my template code:
{% load wtforms %}
<form>
{% for f in form %}
{{ f.label }}: {% form_field f %}<br/>
{% endfor %}
</form>
This is what I am passing in the view:
form = StrandForm()
return render_to_response('create_strand.html', locals(), context_instance = RequestContext(request))
The StrandForm class I have tried both creating from the WTForm mongoengine extension's model_form class, and from WTForm's Form class. The label exists in the view, I can print it to the console and it shows the rendered form label, but somehow it gets lost when transferring to the template. Am I doing something wrong?
Django 1.4 has a new feature: do_not_call_in_templates attribute.
If you set it on wtforms.Field class, every child class inherits and all fields will work fine in django templates.
import wtforms
wtforms.Field.do_not_call_in_templates = True
Now following code works as expected:
{% load wtforms %}
{{ f.label }}: {% form_field f %}
I encountered the same problem today. It has to do with the way WTForms is programmed so that it will work with many different templating libraries. Django 1.3 will only see f as it's HTML string even though it has other attributes.
In order to fix this you must add a template tag to retrieve the attribute.
Add the following to your projects hierarchy:
templatetags
templatetags / init.py
templatetags / templatetags
templatetags / templatetags / init.py
templatetags / templatetags / getattribute.py
Then in your settings.py file, add the following line to INSTALLED_APPS
'templatetags',
Open up getattribute.py and paste the following code:
from django import template
from django.conf import settings
register = template.Library()
#register.tag
def getattribute(parser, token):
try:
tag_name, tag_object, tag_function = token.split_contents()
except ValueError:
raise template.TemplateSyntaxError("%r tag requires two arguments" % token.contents.split()[0])
return getattrNode(tag_object, tag_function)
class getattrNode(template.Node):
def __init__(self, tag_object, tag_function):
self.tag_object = tag_object
self.tag_function = tag_function
def render(self, context):
return getattr(context[self.tag_object], self.tag_function)()
This will allow you to use the follow code whenever you're inside a template and need an attribute that won't show up:
{% load getattribute %}
{% getattribute OBJECT ATTRIBUTE %}
In your case:
{% getattribute f label %}
Hope that helped!