django boolean field in template - django

I am trying to display a message on a template that varies based on the boolean field in my model.
For my model I have:
Class Example(models.Model):
completed = models.BooleanField(default=False)
Views.py
def home(request):
example = Example.objects
return render(request, 'home.html', {'example': example})
home.html
{% for x in example.all %}
{% if x.completed %}
<p>Congratulations!</p>
{% else %}
<p>Try again!</p>
{% endif %}
{% endfor %}
The template always displays "Try again!" even though through the Admin I have ensured that some are True and some are False.

Your views.py should be like this
def home(request):
example = Example.objects.all()
return render(request, 'home.html', {'example': example})
and html should be
{% for x in example %}
{% if x is True %}
<p>Congratulations!</p>
{% else %}
<p>Try again!</p>
{% endif %}
{% endfor %}

The is a simple way I thought of handling boolean related option field in a form
Model.py:
class example(models.Model):
is_online = models.BooleanField(default=False)
Example.html:
<div class="form-row">
<div class="col-md-4 mb-3">
<label class="sr-only">Class Type</label>
<select name="types" class="form-control">
<option selected="true" disabled="disabled">Type (All)</option>
<option value="True"
{% if 'True' == values.types %}
selected
{% endif %}
>Online</option>
<option value="False"
{% if 'False' == values.types %}
selected
{% endif %}
>Classroom</option>
</select>
</div>
</div>
View.py
# Types
if 'types' in request.GET:
types = request.GET['types']
if types == 'True':
queryset_list = queryset_list.filter(is_online=True)
elif types == 'False':
queryset_list = queryset_list.filter(is_online=False)

Related

convert string value to integer in Django template

In home.html
<div class="container">
<div class="row">
<div class="col-md-6">
<h3>Select products:</h3>
<form id="selectProduct" role="search" method="get" action="{% url 'home' %}">
<select name="parameters" data-placeholder="Choose products" class="chosen-select" multiple tabindex="4">
{% for p in productnames %}
{% if k == p %}
<option value="{{ p.productnames }}" selected> {{ p.productnames }} </option>
{% else%}
<option value="{{ p.id }}"> {{ p.productnames }} </option>
{% endif %}
{% endfor %}
</select><br/>
<label for="submit"></label><button id="submit" type="submit" class="btn btn-default">Submit</button>
</form>
</div>
</div>
<div class="row"></div><br />
<h3> Distribution of sales in the products:</h3>
</div>
</div>
{% for p in productList %}
{% for pin in productnames %}
<p>{{pin.id}} {{p}}</p>
{% if p == pin.id %}
<p>exists</p>
{% else %}
<p>not exist</p>
{% endif %}
{% endfor %}
{% endfor %}
<p>{{ productList }}</p>
in this html file 'p' always returns a string value for ex: it returns like '10' instead of 10. all i want is to convent this '10' to 10 or convert returned other p_in value to 10 to '10'.
in views.py
def productList(request):
if request.method == 'GET':
p = request.GET.get('parameters')
print(p)
#k = request.GET('parameters[]')
productnames = Products.objects.all()
context = {
'productList': p, 'productnames': productnames,
}
return render(request, 'home.html', context)
I tried to convert the values of the p in product list to integer. because it dosen't mactch the format with pin.id
You filter the queryset in the template using if-else which is not ideal. Instead you should perform this filtering in the view itself. Also your parameters is a select tag which may have multiple selected values yet you use .get('parameters') which will only give you one value instead you should use the getlist method [Django docs] of the QueryDict:
def productList(request):
if request.method == 'GET': # Do you even need to check this? You appear to only use a GET request...
p = request.GET.getlist('parameters')
productnames = Products.objects.all()
filtered_products = Products.objects.filter(pk__in=p)
context = {
'productList': p, 'productnames': productnames, 'filtered_products': filtered_products
}
return render(request, 'home.html', context)
In the template your loop would simply become:
{% for product in filtered_products %}
{{ product.productnames }}
{% endfor %}
Note: You should use a form class instead of manually making a form. See Building a form in
Django.
Also a models name should be singular hence instead of
Products you should name it Product. In general in
your code you also break various naming conventions in Python, I would
suggest you to look at PEP 8 -- Style Guide for Python
Code
In views.py
def productList(request):
if request.method == 'GET':
p = request.GET.getlist('parameters')
print(p)
#k = request.GET('parameters[]')
productnames = Products.objects.all()
context = {
'productList': p, 'productnames': productnames,
}
# --- logic later for chart ------
return render(request, 'home.html', context)
In home.html
<div class="container">
<div class="row">
<div class="col-md-6">
<h3>Select products:</h3>
<form id="selectProduct" role="search" method="get" action="{% url 'home' %}">
<select name="parameters" data-placeholder="Choose products" class="chosen-select" multiple tabindex="4">
{% for p in productnames %}
{% if k == p %}
<option value="{{ p.productnames }}" selected> {{ p.productnames }} </option>
{% else%}
<option value="{{ p.id }}"> {{ p.productnames }} </option>
{% endif %}
{% endfor %}
</select><br/>
<label for="submit"></label><button id="submit" type="submit" class="btn btn-default">Submit</button>
</form>
</div>
</div>
<div class="row"></div><br />
<h3> Distribution of sales in the products:</h3>
</div>
</div>
{% for p in productList %}
{% for pin in productnames %}
<p>{{pin.id|stringformat:"s"}} {{p}}</p>
{% if p == pin.id|stringformat:"s" %}
<p>exists</p>
{% else %}
<p>not exist</p>
{% endif %}
{% endfor %}
{% endfor %}
<p>{{ productList }}</p>
Note {{value|stringformat:"s"}} can be used to convert integer value to string value

Why this django formset has stopped saving the content all of a sudden?

I had this view that rendered a form and a formset in the same template:
class LearnerUpdateView(LearnerProfileMixin, UpdateView):
model = User
form_class = UserForm
formset_class = LearnerFormSet
template_name = "formset_edit_learner.html"
success_url = reverse_lazy('pages:home')
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
learner = User.objects.get(learner=self.request.user.learner)
formset = LearnerFormSet(instance=learner)
context["learner_formset"] = formset
return context
def get_object(self, queryset=None):
user = self.request.user
return user
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form_class = self.get_form_class()
form = self.get_form(form_class)
user = User.objects.get(learner=self.get_object().learner)
formsets = LearnerFormSet(self.request.POST, request.FILES, instance=user)
if form.is_valid():
for fs in formsets:
if fs.is_valid():
# Messages test start
messages.success(request, "Profile updated successfully!")
# Messages test end
fs.save()
else:
messages.error(request, "It didn't save!")
return self.form_valid(form)
return self.form_invalid(form)
Then i wanted to make it prettier and i added the select2 multicheckbox widget and the django-bootstrap-datepicker-plus
Nothing has changed elsewhere, yet when i submit the post it only saves the data relative to User and not to Learner (which relies on the formset)
According to the messages, the formset data is not validated, I don't understand why since i didn't touch the substance at all but just the appearance.
Being a beginner im probably missing something big, I thank in advance whoever can help me find out the problem.
Here below the forms and the template:
(users.forms)
class LearnerForm(forms.ModelForm):
class Meta:
model = Learner
fields = ['locations', 'organization', 'supervisor', 'intro']
class UserForm(forms.ModelForm):
class Meta:
model = User
fields = ['username', 'first_name', 'last_name', 'birthday', 'email', 'profile_pic']
widgets = {
'birthday': DatePickerInput(format='%Y-%m-%d'), }
LearnerFormSet = inlineformset_factory(User, Learner, form=LearnerForm)
template
{% extends '_base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<form action="" method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form|crispy }}
{{ learner_formset.management_form}}
{% for form in learner_formset %}
{% if forloop.first %}
{% for field in form.visible_fields %}
{% if field.name != 'DELETE' %}
<label for="id_{{ field.name }}">{{ field.label|capfirst }}</label>
<div id='id_{{ field.name }}' class="form-group">
{{ field.errors.as_ul }}
{{ field }}
</div>
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
<input class="btn btn-success" type="submit" value="Update"/>
</form>
{% endblock content %}
I figured it out by combing the previous commits. The problem was in the template, the formset wasn't getting validated because i had ignored the hidden fields, which i hear are a common problem when dealing with formsets.
So the correct code is as such:
{% extends '_base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<form action="" method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form|crispy }}
{{ learner_formset.management_form}}
{% for form in learner_formset %}
{% if forloop.first %}
{% comment %} This makes it so that it doesnt show the annoying DELETE checkbox {% endcomment %}
{% for field in form.visible_fields %}
{% if field.name != 'DELETE' %}
<label for="{{ field.name }}">{{ field.label|capfirst }}</label>
<div id="{{ field.name }}" class="form-group">
{{ field }}
{{ field.errors.as_ul }}
</div>
{% endif %}
{% endfor %}
{% endif %}
{% for field in form.visible_fields %}
{% if field.name == 'DELETE' %}
{{ field.as_hidden }}
{% else %}
{# Include the hidden fields in the form #}
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{% endif %}
{% endfor %}
{% endfor %}
<input class="btn btn-success" type="submit" value="Update"/>
</form>
{% endblock content %}

How to filter and loop through objects in a Django template

I'm modifying the default article.html template that came with Aldryn Newsblog to allow for a comment form and listing of the comments for that specific article. I have included the form without a problem. But I can't figure out how to query the comments.
EDITED
Here is my list_comments.html template:
{% load cms_tags staticfiles sekizai_tags %}
{% if comments %}
{% for item in comments %}
<div class="comment paragraph">
<h4>{{ item.author }}</h4>
<p>{{ item.comment }}</p>
<p>{{ item.date }}</p>
</div>
{% endfor %}
{% else %}
<p>No comments exist on this blog. Be the first to comment!</p>
{% endif %}
and comment_form.html
{% load cms_tags staticfiles sekizai_tags %}
<div id="comment_form">
<div class="container constrained paragraph">
<h5>Submit a comment</h5>
<form method="post">
{% csrf_token %}
{{ comment_form }}
<input type="hidden" name="page" value="{{ article.id }}">
<input type="submit" value="Submit Comment">
</form>
</div>
And models.py:
class BlogComment(models.Model):
ip_address = models.CharField(max_length=255, verbose_name="IP Address")
date = models.DateTimeField(default=datetime.now)
article = models.CharField(max_length=255)
author = models.CharField(max_length=255)
comment = models.CharField(max_length=1000)
And in views.py I have these:
def display_form(request):
comment_form = CommentForm()
return render(request, 'comment_form.html', {'comment_form': comment_form})
def get_blog_comments(request):
qs = BlogComment.objects.all()
context = {'comments': qs, 'another': 'test'}
return render(request, 'list_comments.html', context)
And in both templates, the context variables are outputting nothing. I am at a loss for what I'm doing wrong. django.template.context_processors.request is included in my settings.py context_processors.
As already stated, the querying is done in your views.py file.
# views.py
def get_blog_comments(request):
if request.method == "GET":
qs = BlogComment.objects.all()
template = # location of template, ex. blog_list.html
context = {'obj_list': qs}
return render(request, template, context)

HTML layout object doesn't work

I quite new with Django Crispy Form and I have tried to add a HTML object in my form but it's not working. All the other elements are rendered but not the HTML.
This is my form:
forms.py
from crispy_forms.layout import Layout, Fieldset, HTML
class MyUserRegistrationForm(forms.ModelForm):
class Meta:
model = MyUser
fields = ['title', 'privacy_disclaimer_accepted']
def __init__(self, *args, **kwargs):
super(MyUserRegistrationForm, self).__init__(*args, **kwargs)
helper = FormHelper()
helper.form_method = 'post'
helper.form_class = 'form-horizontal'
helper.label_class = 'col-sm-2'
helper.field_class = 'col-sm-6'
helper.form_error_title = 'Form Errors'
helper.error_text_inline = True
helper.help_text_inline = True
helper.html5_required = True
helper.form_tag = False
helper.layout = Layout(
Fieldset('Information', 'title'),
Fieldset('Privacy Statement',
HTML("""
<div id="iframe" class="mt-5">
<h6>Notice/Disclaimer:</h6>
<div class="privacy-policy">
{% if privacy_disclaimer %}
{{ privacy_disclaimer }}
{% else %}
{% include "registration/privacy_policy.html" %}
{% endif %}
</div>
</div>
"""),
'privacy_disclaimer_accepted', )
)
I have a basic HTML file, where I have the normal html, header and body tags.
This is the HTML registration page:
register.html
{% extends "base.html" %}
{% block title %}Create an account{% endblock %}
{% block content %}
<div class="registration-page">
<h3 class="text-center">Create an account</h3>
<div class="registration-page__form">
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
<div class="alert alert-error">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endfor %}
{% for error in form.non_field_errors %}
<div class="alert alert-error">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endif %}
<form action="" method="post">
{% csrf_token %}
{% load crispy_forms_tags %}
{{ form_myuser|crispy }}
<br/>
<div class="text-right">
<input type="submit" class="btn btn-primary btn--action" value="Create the account">
</div>
</form>
</div>
</div>
{% endblock %}
EDIT:
views.py
class RegisterView(View):
template_name = 'registration/register.html'
def _get_context_data(self, **kwargs):
context = {}
privacy_disclaimer = ''
context['privacy_disclaimer'] = privacy_disclaimer
if kwargs:
context.update(kwargs)
return context
def get(self, request, *args, **kwargs):
extra_context = {
'form_myuser': MyUserRegistrationForm(),
}
context = self._get_context_data(**extra_context)
return render(request, self.template_name, context)
I fixed the issue and the problem was the form loading.
I was loading it in the wrong way.
Instead of this {{ form_myuser|crispy }} I have to use this code {% crispy form_tolauser %}.

Remember form selection

How to "remember" form selection value in Django?
{% load i18n %}
<form action="." method="GET" name="perpage" >
<select name="perpage">
{% for choice in choices %}
<option value="{{choice}}" {% if 'choice' == choice %} selected="selected" {% endif %}>
{% if choice == 0 %}{% trans "All" %}{% else %}{{choice}}{% endif %}</option>
{% endfor %}
</select>
<input type="submit" value="{% trans 'Select' %}" />
</form>
sorry about my words, but this seems a bad aproach. The django way to work with this is a simple form with a initial value for your selected choice. If you don't belive me, and you persist in this way, then change your template if as:
{% if choice == myInitChoice %}
Don't forget to send myInitChoice to context.
c = RequestContext(request, {
'myInitChoice': request.session.get( 'yourInitValue', None ),
})
return HttpResponse(t.render(c))
#register.inclusion_tag('pagination/perpageselect.html', takes_context='True')
def perpageselect (context, *args):
"""
Reads the arguments to the perpageselect tag and formats them correctly.
"""
try:
choices = [int(x) for x in args]
perpage = int(context['request'].perpage)
return {'choices': choices, 'perpage': perpage}
except(TypeError, ValueError):
raise template.TemplateSyntaxError(u'Got %s, but expected integer.' % args)
i just added takes_context='True' and take the value from context. The template i edited as
{% load i18n %}
<form action="." method="GET" name="perpage" >
<select name="perpage">
{% for choice in choices %}
<option value="{{choice}}" {% if perpage = choice %} selected="selected" {% endif%}>
{% if choice == 0 %}{% trans "All" %}{% else %}{{choice}}{% endif %}</option>
{% endfor %}
</select>
<input type="submit" value="{% trans 'Select' %}" />
</form>
Generally when you run into a common tasks, chances are there is an easy way to do it in django.
from django import forms
from django.shortcuts import render, redirect
FIELD_CHOICES=((5,"Five"),(10,"Ten"),(20,"20"))
class MyForm(froms.Form):
perpage = forms.ChoiceField(choices=FIELD_CHOICES)
def show_form(request):
if request.method == 'POST':
form = MyForm(request.POST)
if form.is_valid():
return redirect('/thank-you')
else:
return render(request,'form.html',{'form':form})
else:
form = MyForm()
return render(request,'form.html',{'form':form})
In your template:
{% if form.errors %}
{{ form.errors }}
{% endif %}
<form method="POST" action=".">
{% csrf_token %}
{{ form }}
<input type="submit" />
</form>