pass loop from view.py to html template in Django - django

I try to get the data in my models "Machines" and then need to get Additional information form other table related to each machine.
I try bellow code in views.py and render it to specified html page.
def allmachinesLOGO(request):
machines=Machine.objects.all()
c=""
for m in machines:
if m.tb_order_set.filter(status="2").exists():
c="2"
else:
c="0"
context ={'machines':machines,'condition':c}
return render(request,'pline/machineslogos.html',context)
{% if condition == "2" %}
<h4> working</h4>
<img class="btn-circle" style="width: 15px" src="{% static 'images/icons/icons8-green-circle-48.png' %}" alt="image" />
{% else %}
<h4>stop</h4>
{{ condition }}
<img class="btn-circle" style="width: 15px" src="{% static 'images/icons/icons8-red-circle-48.png' %}" alt="image" />
{% endif %}
what's the correct way to pass loop from views.py to template in Django

In the view, at each iteration of the loop, I create a dictionary with two values: 'machines', 'status' and put it in the aaa list.
Either remove the line in the view(if you don't want the lines with 'status'= '0' to be displayed.):
else:
aaa.append({'machines': m, 'status': '0'})
then the line with 'machines': m, 'status': '0' will not be recorded.
Perhaps there is a way without a cycle to filter by the secondary model. It would be interesting to see if there is such a way.
views.py
def allmachinesLOGO(request):
machines = Machine.objects.all()
aaa = []
for m in machines:
if m.tb_order_set.filter(status='2').exists():
aaa.append({'machines': m, 'status': '2'})
else:
aaa.append({'machines': m, 'status': '0'})
context = {'context': aaa}
return render(request, 'pline/machineslogos.html', context)
templates
{% for m in context %}
{% if m.status == '2' %}
<h4> working</h4>
<p>{{ 'machines' }} : {{ m.machines }} {{ 'status' }} : {{ m.status }} </p>
{% else %}
<h4>stop</h4>
<p>{{ 'machines' }} : {{ m.machines }} {{ 'status' }} : {{ m.status }} </p>
{% endif %}
{% endfor %}
One more way. Filter Machine by secondary model with status='2'. To make sure this is the case, two loops (the outer one iterates over Machine, and the inner one a.tb_order_set.all() and outputs status to print(stat.status)):
bbb = Machine.objects.filter(tb_order__status='2')#If unique records are needed, then add distinct().
print(bbb)
for a in bbb:
for stat in a.tb_order_set.all():
print(stat.status)

Related

Iterate context variables in Django templates based on user's attributes

Is it possible to iterate over a list of three context variables shown below so that depending on the user's attribute (in this instance grade, Grade 10, Grade 11, Grade 12). If current user's grade attribute is Grade 10 then they only get: context['grade10'] from below.
Current view:
class SumListView(ListView):
model = Summaries
template_name = 'exam/summary.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['grade10'] = Summary.objects.filter(grade='Grade 10')
context['grade11'] = Summary.objects.filter(grade='Grade 11')
context['grade12'] = Summary.objects.filter(grade='Grade 12')
return context'''
Current html template block:
{% block content %}
{% for summary in grade10 %}
<div class="container>
{{ summary.content }}
</div>
{% endfor %}
{% endblock content %}
I tried this but it breaks the code since for loops and iterations are mixing:
{% block content %}
{% if grade10 %}
{% for summary in grade10 %}
<div class="container>
{{ summary.content }}
</div>
{% endfor %}
{% elif grade11 %}
{% for summary in grade10 %}
<div class="container>
{{ summary.content }}
</div>
{% endfor %}
{% else grade12 %}
{% for summary in grade10 %}
<div class="container>
{{ summary.content }}
</div>
{% endfor %}
{% enif %}
{% endblock content %}
What is the best way to go about this?
I know I can write different urls for each context which in turn renders a different template but that does not seem efficient and I hope there is a better way to do that. Any help highly appreciated, including documentation pointers.
You can perform this logic in your view, you can use a single context variable but change it's contents based on your logic
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
user_grade = self.request.user.get_grade() # Replace with how you access the user's grade
context['grades'] = Summary.objects.filter(grade=user_grade)
return context
Then loop over grades in your template

How can I use a variable to lookup in a tuple? (Django)

I have a tuple, such that
{{VISIBILITY_CHOICES.1.1}}
Outputs "hello".
I have model "task" with a attribute "visibility_status", and in a loop, say all the iterations of task.visibility_status outputs 1
{{task.visibility_status}}
Outputs 1.
How do I use this task.visibility_status inside the lookup of the tuple? Something like VISIBILITY_CHOICES[task.visibility_status][1] in a different language.
I'm very new to django... Thanks a lot.
edit:
The code I was running:
{% for task in tasks %}
<div class="post">
<h1>{{ task.subject }}</h1>
<div class="date">
<p>Due: {{ task.due_date }}</p>
<p>Assigned to: {{task.assigned_to}}</p>
</div>
<p>{{ task.text_area|linebreaks }}</p>
{% with args=""|add:task.visibility_status|add:",1" %}
<p>Visibility Status: {{VISIBILITY_CHOICES|get_index:args}}({{ task.visibility_status }})</p>
{% endwith %}
<p>Case Status: {{ task.case_status }}</p>
<div class="date">
<p>Created: {{ task.created_date }} by {{ task.author }}</p>
</div>
</div>
{% endfor %}
Although the builtin name tuple may not have any syntactic meaning in a template, I'll use my_tuple in its place in the code below.
I've used with to create a context that builds the args for indexing my_tuple (i.e task.visibility_status and 1): :
{% with x=task.visibility_status|stringformat:"s" %}
{% with args=x|add:",1" %}
{{ my_tuple|get_index:args }}
{% endwith %}
{% endwith %}
And in the custom template filter, I've splitted and recreated the arguments and used indexing in plain python to return the item at the index:
from django import template
register = template.Library()
#register.filter
def get_index(my_tuple, args):
arg1, arg2 = args.split(',') # split on the comma separator
try:
i = int(arg1)
j = int(arg2)
return my_tuple[i][j] # same as my_tuple[task.status][1]
except:
return None

Could not parse the remainder django template

I have a condition within a loop in my template like this:
{% for message in message_trash %}
<td><a href="#">
{% if request.session.user_email == message.message_user_reciever.user_email %}
{{ message.message_user_reciever.user_firstName }} {{ message.message_user_reciever.user_lastName }}
{% elif request.session.user_email == message.message_user_sender.user_email %}
{{ message.message_user_sender.user_firstName }} {{ message.message_user_sender.user_lastName }}
{% endif %}
</a><small>Friends</small></td>
{% endfor %}
but i don't know why i get this error when applying the url?
TemplateSyntaxError: Could not parse the remainder: '==message.message_user_reciever.user_email' from 'request.session.user_email==message.message_user_reciever.user_email'
Update:
this is the view and variables that i render to the template:
def trashMessages(request, userId):
if isMessageOwner(request, userId):
user = Users.objects.get(user_id=userId)
message_trash = Messages.objects.filter(Q(message_user_reciever= user, message_sender_type='TRASH') | Q(message_user_sender=user, message_reciever_type='TRASH'))
return render(request, 'navigation_messages.html', {'user': user, 'message_trash': message_trash, 'type': 'trash'})
On testing your code out, I can only replicate your issue is by swapping:
{% if request.session.user_email == message.message_user_reciever.user_email %}
for
{% if request.session.user_email ==message.message_user_reciever.user_email %}
Note the missing space. Is the snippet in your question exactly as it is in your template?

Django: How to output error_message in paragraph <p> instead of list <li> format

I have a simple form which uses a SessionWizardView to spread it over a number of pages. Below is an example of one of the questions.
first_name = forms.CharField(max_length=100, label='What is your first name?', error_messages={'required': 'Please enter your first name'})
Which renders out as
<label for="id_0-first_name">What is your first Name?</label>
<ul class="errorlist">
<li>Please enter your first name</li>
</ul>
<input id="id_0-first_name" maxlength="100" name="0-first_name" type="text" />
Can anyone tell me hwo to change the error output so that it is in <p> Paragraph </p> format rather than <li> List item </li> format?
I am using Django 1.6.2
You'll have to create a class that does renders the HTML as you would want it. See the docs here.
The example from the docs:
from django.forms.util import ErrorList
class DivErrorList(ErrorList):
def __unicode__(self):
return self.as_divs()
def as_divs(self):
if not self: return u''
return u'<div class="errorlist">%s</div>' % ''.join([u'<div class="error">%s</div>' % e for e in self])
f = ContactForm(data, auto_id=False, error_class=DivErrorList)
f.as_p()
You can do as #schillingt suggested and create your own error list class.
Or, if you want to handle this in your template, you can use something like:
<form method="post" action="/some-view/">
... other fields, etc. omitted ...
<!-- The label and form field -->
{{ form.first_name.label_tag }}
{{ form.first_name }}
<!-- Output any errors -->
{% for error in form.first_name.errors %}
<p>{{ error }}</p>
{% endfor %}
... other fields, etc. omitted ...
<button type="submit">Submit</button>
</form>
Update
In order to do this in a cleanly repeatable way, make a template named form-field.html:
{{ field.label_tag }}
{{ field }}
<!-- Output any errors -->
{% for error in field.errors %}
<p>{{ error }}</p>
{% endfor %}
Then, update your main template:
<form method="post" action="/some-view/">
... other fields, etc. omitted ...
{% with field=form.first_name %}
{% include "form-field.html" %}
{% endwith %}
... other fields, etc. omitted ...
<button type="submit">Submit</button>
</form>
You can then make updates to the single form-field.html template and update all of your forms, and it makes your main template a bit simpler

How to give "no results found for this query" properly in a form with Django

I have a search page where user can submit queries that try to match objects in a database. When the user has submitted the form and no results have been found for his/her query, I want to give the message "No results found for this query". The problem I'm having now is that the message is shown even when the user has not submitted the form yet.
This is what my code looks like:
Review Template
<div> What do you want to review? </div>
<form action="/newreview/" method="get">
{% for field in form %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }}: {{ field }}
</div>
{% endfor %}
<input type="submit" value="Submit" name="submit" />
{% if results %}
{{ results.id }}
{% else %}
<li> There is no results for this search </li>
{% endif %}
</form>
And I do the following for the View:
def newreview(request):
if 'submit' in request.GET: # If the form has been submitted...
form = LookforPlace(request.GET) # A form bound to the GET data
if form.is_valid(): # All validation rules pass
name = form.cleaned_data['name']
city = form.cleaned_data['city']
try:
results = Place.objects.get(name__icontains=name)
except Place.DoesNotExist:
results = None
else:
results = []
form = LookforPlace() # An unbound form
return render_to_response('newreview.html', {
'form': form, 'results': results,
})
I thought that by doing the conditional on the results list, I could check whether the form has been submitted or not (empty list from the view).
Right now this code is giving me "There is no results for this search" even if there has not been any submission. Any thoughts?
Why not put a flag in your context to determine whether or not it has been submitted?
if 'submit' in request.GET:
submitted = True
...
else:
submitted = False
...
{% if submitted %}
{% if results %}
{{ results.id }}
{% else %}
<li> There are no results for this search </li>
{% endif %}
{% endif %}