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()
Related
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.
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})
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 %}
I'm using the django(v.1.2) generic view "list_detail" to print some objects (Model Article) stored in a db.
In urls.py I added the following line
urlpatterns += patterns('django.views.generic.list_detail',
url(r'^article/(?P<slug>[\-\d\w]+)/$', 'object_detail', {'slug_field': 'title_slug', 'queryset': Article.objects.filter(is_public=True)}, name='article'),
)
In the respective template (article_detail.html) I would like to print the article iterating over all its fields. Actually I wrote:
{% for k,v in object.fields %}
<p>{{k}}:{{v}}<p>
{% endfor %}
but it doesn't work. Any suggestions?
'queryset': Article.objects.filter(is_public=True) sends a list to your template.
but in template you are treating it like an Article object.
'article': Article.objects.filter(is_public=True)[0]
then you can access all items of Article. However, I don't understand what you are trying to do with it. is Article.fields a list or dict?
Let us solve this by an example-
I have a model as-
class item(models.Model):
item_number = models.AutoField(primary_key=True)
item_name = models.CharField(max_length=200)
lifetime_rating = models.DecimalField(max_digits=3,decimal_places=1, default=0)
current_rating = models.DecimalField(max_digits=3,decimal_places=1, default=0)
lifefeedbacknum = models.IntegerField(default=0)
currentfeedbacknum = models.IntegerField(default=0)
def __unicode__(self):
return self.item_name
def retlifetime_rating(self):
return self.lifetime_rating
Note method-retlifetime_rating which returns the value of lifetimerating for an object instance.
Now we wish to display lifetime ratings for all products
in views.py-
def showrating(request):
itemslist= models.item.objects.all()
return render(request, 'showrating.html', 'sitems' : itemslist)
the showrating.html file contains the following code snippet-
{% for element in sitems %}
<tr>
<td>{{ element }}</td>
<td>{{ element.retlifetime_rating }}</td>
</tr>
{% endfor %}
basically if you wish to display different fields of an object, you need to have a corresponding method call to return that field
off-course there are other ways to do it but this is most likely the simplest and easiest to implement