There are so many td elements with a tag and I want to know that user clicked which element and I want to pass from HTML to the backend and process with the user's selection on the backend.
This is my HTML content:
<a href="/selected" ????><td>{{ options1 }}</td></a>
<td>{{ options2 }}</td>
<td>{{ options3 }}</td>
<td>{{ options4 }}</td>
<td>{{ options5 }}</td>
<td>{{ options6 }}</td>
When a user clicked one, I want to send it to the backend:
#app.route('/selected', methods=['GET', 'POST'])
def selected():
selected_option = request.args.get('????')
return render_template("selected.html", selected_option=selected_option)
How can I fill the question marks?
Having the separate variables for options1, options2, etc probably makes this a hassle for a few reasons:
You'll need to manually update the hard-coding of the template to add more options.
The URL part of each option, might be different from the link text.
You may wish to define your options in a dictionary:
sections = {'first-option': 'I am the first option',
'second-option': 'Click me for fun and profit',
'third-option': 'All flights have been cancelled',
}
Now on the page which generates your link bar, if you pass that across:
return render_template('some_page.html', SECTIONS=sections)
You can then do something like:
{% for key, value in SECTIONS.items() %}
{{value}}
{% endfor %}
This will automatically generate the correct URLs, which are compatible with the following view function:
#app.route('/selected/<section>')
def selected(section):
# Assuming the first URL:
print (section) # 'first-option'
print (sections[section]) # 'I am the first option'
return render_template("selected.html", selected_option=section)
You may also wish to have a look at this gist which takes the concept a bit further.
This also uses a context processor to insert that SECTIONS variable into all pages, rather than passing it to the individual render_template functions.
Related
I have a Consults page that lists consults in the datastore. The list loop is like this:
{% for consult in consults %}
<tr>
<td>{{ consult.consult_date }}</td>
<td>{{ consult.consult_time }}</td>
<td>{{ consult.patient_first }}</td>
<td>{{ consult.patient_last }}</td>
<td><span class="badge badge-warning">{{ consult.consult_status }}</span></td>
</tr>
{%endfor%}
The handler is like this:
class ConsultsPage(webapp2.RequestHandler):
def get(self):
consults = Consults.query().fetch(5)
consults_dic = {"consults" : consults}
template = JINJA_ENVIRONMENT.get_template('/templates/consults.html')
self.response.out.write(template.render(**consults_dic))
I want to know the basic concept behind how I make each consult in the list a link to go in and view information about that particular consult.
I understand I need to use a key to retrieve an entity but am unsure of the rest of the process.
Edit
I have added the line:
url = '/display_consult?key=%s' % consults.key.urlsafe()
to my ConsultsPage (where the consults are listed). The handler now looks like this:
class ConsultsPage(webapp2.RequestHandler):
def get(self):
consults = Consults.query().fetch(5)
consults_dic = {"consults" : consults}
url = '/display_consult?key=%s' % consults.key.urlsafe()
template = JINJA_ENVIRONMENT.get_template('/templates/consults.html')
self.response.out.write(template.render(**consults_dic))
However I get this error:
url = '/display_consult?key=%s' % consults.key.urlsafe()
AttributeError: 'list' object has no attribute 'key'
Also what do I put into the link href in my loop that lists consults? is it something like:
href="consults/{{ url }}"
From Retrieving Entities from Keys:
You can also use an entity's key to obtain an encoded string suitable
for embedding in a URL:
url_string = sandy_key.urlsafe()
This produces a result like agVoZWxsb3IPCxIHQWNjb3VudBiZiwIM which
can later be used to reconstruct the key and retrieve the original
entity:
sandy_key = ndb.Key(urlsafe=url_string)
sandy = sandy_key.get()
So for each consult entity you can obtain a unique URL where you'd display the info about that entity. For example by using a URL parameter:
url = '/display_consult?key=%s' % consult.key.urlsafe()
And in the /display_consult page handler you'd obtain the entity like this:
consult = ndb.Key(urlsafe=request.get('key')).get()
I created this simple set of data to illustrate my point. It is a simple model with no further relations to any other model.
I need to group the data above by topicid, find the max date for each group and then get the author for that date.
info = TempModel.objects
.values('topic')
.annotate( max=Max('date'))
.order_by('-max')
Iterating through this in a template,
<table>
{% for item in info %}
<tr>
<td>{{ item.topicid }}</td>
<td>{{ item.max }}</td>
<td>{{ item.author }}</td>
</tr>
{% endfor %}
</table>
produces,
How do I display the 'author' column for each max date?
I can do this with a raw sql query like this,
info = list(TempModel.objects
.raw('SELECT *, max(date) AS max
FROM crudapp_tempmodel
GROUP BY topicid
ORDER BY date DESC'))
But I want to do it using a Django query.
The output I am looking for is,
If this is not possible with a Django query I would like to know.
Thanks,
A solution is to amalgamate another query which compares date from one query with max from the other.
Here is the view that does this,
def temp(request):
info2 = TempModel.objects.all()
info = TempModel.objects
.values('topic')
.annotate( max=Max('date'))
.order_by('-max')
columnlist = []
for item in info2:
columnlist.append([item])
for item in info:
for i in range(len(columnlist)):
if item['max'] == columnlist[i][0].date:
item['author'] = columnlist[i][0].author
return render(request, 'template.html', {'info': info, 'info2': info2})
I am using Django 1.8.3 and Python 3.4.3
I've got a custom tag that takes the value of two objects, divides one into the other and renders the total. I did it this way because the two objects being divided are the Sum of many fields so I needed to do the final calculation of the totals.
What I need help with is, once the two values are divided into each other, the float renders up to 15 digits after the decimal and I tried to use |floatformat, but it doesn't seem to work on a tag. I've searched and searched for an answer, but I can't seem to find whats probably right in front of me :)
Everything works, I just want to format the final value to a 2 decimal point. Below is my code.
simple_tag.py
from django import template
register = template.Library()
#register.simple_tag()
def average(num1, num2):
return float(num1 / num2)
traffic.html (my template)
{% if traffic_list %}
<tr>
<th>Monday</th>
<td>{{ total_sales.Monday }}</td>
<td>{{ total_campaigns.Monday }}</td>
<td>{{ total_ifs_signups.Monday }}</td>
<td>{{ total_traffic.Monday }}</td>
<td>{% average total_traffic.Monday total_sales.Monday %}</td>
</tr>
...
Resulting value of the above tag
30.345407503234153
I would like it to render
30.36
Thank you again for your help.
You can round the float in the tag definition:
#register.simple_tag()
def average(num1, num2):
return round(float(num1 / num2), 2)
Or you can use floatformat filter like this:
{% average total_traffic.Monday total_sales.Monday as result %}
<td>{{result|floatformat:2}}</td>
When doing the average, you have to:
#register.simple_tag()
def average(num1, num2):
a = float(num1 / num2)
# if you want you can round it too
# a = round(float(num1/num2))
return format(a, '.2f')
So i have created a custom filter:
#register.filter(name='field_values')
def field_values(model, field):
return model.objects.values_list(field, flat=True)
that takes model class value and a field for an argument and returns a list of model objects for that particular field. Here is the template where I try to call it.
<tr>
{% for field in fields %}
<td>{{ model_class|field_values: field }} </td>
{% endfor %}
</tr>
model_class is a dynamically created model in the views as such
views.py
...
if form.is_valid(): # All validation rules pass
model_classes_field = form.cleaned_data['model_classes_field']
model_class = get_model('Directories', model_classes_field)
I was expecting everything to run smoothly but instead I get a "*field_values requires 1 arguments, 0 provided*" error. Why does this happen when i have already inserted an argument?? is it a problem with the filter syntax?
You have a space after the colon which is confusing the parser. Use it like this instead:
{{ model_class|field_values:field }}
(Note that your code is pretty inefficient: it's querying the database over and over again, once for each field. Rather than doing this, you should probably query it once in the view and group the output by field.)
I am fairly new to Django and I am having trouble getting values to load into the HTML from the dictionary generated in the models.py that looks like this:
>>> generic_id = Generic.objects.get(pk=127)
>>> dict = generic_id._get_dict()
>>> dict
[{'field__name':'key1', 'value_char':'value1a', 'value_num':'value1'},{'field__name':'key2', 'value_char':'value2a', 'value_num':'value2'},{'field__name':'key3', 'value_char':'value3a', 'value_num':'value3'},{'field__name':'key4', 'value_char':'value4a', 'value_num':'value4'}]
>>> dict[2]['value_num']
Decimal('value2')
>>> dict[3]['value_char']
'value3a'
The HTML table looks like this:
<table>
<tr>
<td>Description1</td><td>{{value1}}</td>
<td>Description2</td><td>{{value2}}</td>
<td>Description3</td><td>{{value3a}}</td>
<td>Description4</td><td>{{value4}}</td>
</tr>
<tr>
<td>Name: {{ generic.name }}</td>
<td>E-mail: {{ generic.email }}</td>
<td>State: {{ generic.state }}
</table>
The code in the views.py right now looks like this:
def query_test(request, generic_id):
try:
a = Generic_table.objects.get(pk=generic_id)
except Generic_table.DoesNotExist:
raise Http404
t = loader.get_template('query_test.html')
c = RequestContext(request, {
'generic' : a, })
return HttpResponse(t.render(c))
Can someone give me some suggestions as to how to (and efficiently) get the appropriate values from the dictionary into the generated HTML?
Based on what your objects look like from your model, and your template, I would suggest trying this:
assuming:
a = Generic.objects.get(pk=generic_id)
# a == {'field__name':'key1', 'value_char':'value1a', 'value_num':'value1'}
views.py
from django.shortcuts import render_to_response, get_object_or_404
def query_test(request, generic_id):
a = get_object_or_404(Generic, pk=generic_id)
return render_to_response("query_test.html", a,
context_instance=RequestContext(request))
query_test.html
Name: {{field__name}}
Char: {{value_char}}
Num : {{value_num}}
Your view doesn't show that you are expecting more than one object, since you look for an id, so your template would end up formatting just one object.
Edit: In case you are trying to display a list of results
views.py might look something like this:
def query_test(request, generic_id=None):
if generic_id is not None:
a = Generic.objects.filter(pk=generic_id)
else:
a = Generic.objects.all()
c = {'generic': a}
# add some extra values
c['value1'] = "I am value1"
# add a whole dictionary of other values
c.update({'value2': "yay val2", 'value3a': 3, 'value4': "I am 4"})
return render_to_response("query_test.html", c,
context_instance=RequestContext(request))
And your template something like:
<table>
<tr>
<td>Description1</td><td>{{value1}}</td>
<td>Description2</td><td>{{value2}}</td>
<td>Description3</td><td>{{value3a}}</td>
<td>Description4</td><td>{{value4}}</td>
</tr>
{% for item in generic %}
<tr>
<td>Name: {{item.field__name}}</td>
<td>Char: {{item.value_char}}</td>
<td>Num : {{item.value_num}}</td>
</tr>
{% endfor %}
</table>
Edit2: Addressing the strange object you are sending to your template
Based on your updated question... That is not a dictionary. Its a list of dictionaries, and Its really strange the way you are pulling that data from the single model instance. But assuming that is what you really really want, you have a number of options..
1) Fix that data object BEFORE sending it to the template. I have no idea if you want all the elements in that list, or just a specific item.
not_a_generic_id = Generic.objects.get(pk=127)
not_a_dict = not_a_generic_id._get_dict()
dict_that_I_actually_want = not_a_dict[1]
return render_to_response("query_test.html", dict_that_I_actually_want)
2) Send that entire list to the template and loop over each item, and then access the values:
views.py
not_a_generic_id = Generic.objects.get(pk=127)
not_a_dict = not_a_generic_id._get_dict()
c = {"still_not_a_dict": not_a_dict}
return render_to_response("query_test.html", c)
template.html
<table>
{% for actual_dict in still_not_a_dict %}
<tr>
<td>Name: {{actual_dict.field__name}}</td>
<td>Char: {{actual_dict.value_char}}</td>
<td>Num : {{actual_dict.value_num}}</td>
</tr>
{% endfor %}
</table>
3) Even though the template does not let you actually access numeric indexes of lists because you are suppost to sort that data out yourself in the view...if you insist on accessing a specific index of that list in the template, do the same as #2 for the views.py, but:
template.html
{% for actual_dict in still_not_a_dict %}
{% if forloop.counter == 1 %}
{{actual_dict.value_char}}
{% endif %}
{% endfor %}