Get related column on .annotate() data Django - django

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})

Related

how to fetch only the newest rows from the model in django and show it as a table?

views.py
def inventory_display(request):
if request.user.vendor == True and request.user.vendor_approval == True:
vendor = CustomUser.objects.get(id=request.user.id)
vendor_product = vendor.vendor_user.all()
items = vendor_product[0].product_variants.all()
return render(request, 'vendor/inventory_display.html',{'vendor_product':vendor_product, 'items':items})
Html
{% for product in vendor_product %}
{% for item in items %}
<tr>
<th scope="row">{{forloop.counter}}</th>
<td>{{product.created|date:"d-m-y"}}</td>
<td>{{product.edited|date:"d-m-y"}}</td>
<td>{{product.vendoruser}}</td>
<td>{{product.product_id}}</td>
<td>{{item.item_num}}</td>
<td>{{item.variant_value}}</td>
<td>{{item.initial_stock}}</td>
<td>2</td>
<td>{{item.approval_status}}</td>
<td>{{item.approved_date|date:"d-m-y"}}</td>
<td>{{product.approved_by}}</td>
</tr>
{% endfor %}
{% endfor %}
I am fetching data from 3 different models. I do fetch all the data from these models every time. What if I want to get the newest row only whenever the new row is added? I have included the User, Product, Productvariants models in the question.
I am showing data in the template by for loop. Without forloop i am getting repeated data in template, I want the latest data that will not exist in the template.
You can get the latest inserted item in multiple ways
last() method
vendor = CustomUser.objects.last()
order_by() method
vendor = CustomUser.objects.order_by('-id').first()
latest() method
vendor = CustomUser.objects.latest('id')
add this field in your model
created_at = models.DateTimeField(auto_now_add=True)
it will automatically add timestamp whenever object is created. and when you are geting objects
use this query
ModelName.objects.all().order_by('-created_at')
Try adding the index number in your views:
def inventory_display(request):
if request.user.vendor == True and request.user.vendor_approval == True:
vendor = CustomUser.objects.get(id=request.user.id)
vendor_product = vendor.vendor_user.all()[0]
items = vendor_product[0].product_variants.all()[0]
return render(request, 'vendor/inventory_display.html',{'vendor_product':vendor_product, 'items':items})
And remove the for loop from the template:
<tr>
<th scope="row">1</th>
<td>{{vendor_product.created|date:"d-m-y"}}</td>
<td>{{vendor_product.edited|date:"d-m-y"}}</td>
<td>{{vendor_product.vendoruser}}</td>
<td>{{product.product_id}}</td>
<td>{{items.item_num}}</td>
<td>{{items.variant_value}}</td>
<td>{{items.initial_stock}}</td>
<td>2</td>
<td>{{items.approval_status}}</td>
<td>{{items.approved_date|date:"d-m-y"}}</td>
<td>{{vendor_product.approved_by}}</td>
</tr>

How to pass a variable from HTML to the backend in Flask

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.

Linking to entity from list

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()

How do I display related many-to-many fields as a table in Django template?

I have a 2 models 'Member' and 'Event'.
They are in a 'ManyToMany' relationship.
Now I want to create a view that shows for each member when he was at an event and when not, in an html table like that:
Name Event1 Event2 Event3 ...
Member1 x x ...
Member2 x x x ...
Member3 x x
Member4 x x ...
.
.
.
and so on.
Problem is now that the amount of events is constantly increasing.
My only idea is to create a html table in the view but this is not very optimal.
Is there a possibility to manually create querysets, which contain first a member, then all events follow and then comes the next member again followed by all events? and so on..
Or is there a real easy way managed by Django to access the manytomany field in a template
for further reference are here my models:
class Member(models.Model):
KAPELLMEISTER='KM'
FLOETE='FL'
KLARINETTE='KL'
SAXOPHON='SX'
FLUEGELHORN='FH'
TENORHORN='TH'
HORN='HR'
TROMPETE='TR'
POSAUNE='PS'
TUBA='TU'
SCHLAGZEUG='SZ'
INSTRUMENTS=(
(KAPELLMEISTER,'Kapellmeister'),
(FLOETE,'Floete'),
(KLARINETTE,'Klarinette'),
(SAXOPHON,'Saxophon'),
(FLUEGELHORN,'Fluegelhorn'),
(TENORHORN,'Tenorhorn'),
(HORN,'Horn'),
(TROMPETE,'Trompete'),
(POSAUNE,'Posaune'),
(TUBA,'Tuba'),
(SCHLAGZEUG,'Schlagzeug')
)
name = models.CharField('Name',max_length=200)
instrument = models.CharField('Instrument',
max_length=2,
choices=INSTRUMENTS,
null=False)
bool_musikschueler = models.BooleanField('Musikschueler')
bool_student = models.BooleanField('Student')
def __unicode__(self):
return self.name
#classmethod
def create(cls, name, instrument, musikschueler, student):
member = cls(name=name, instrument=instrument, bool_musikschueler=musikschueler, bool_student = student)
return member
class Event(models.Model):
PROBE='PR'
BEGRAEBNIS='BG'
MARSCHMUSIK='MM'
KONZERT='KO'
WECKRUF='WR'
TYPES=(
(PROBE,'Probe'),
(BEGRAEBNIS,'Begraebnis'),
(MARSCHMUSIK,'Marschmusik'),
(KONZERT,'Konzert'),
(WECKRUF,'Weckruf')
)
date = models.DateField('Datum')
type = models.CharField(max_length=2,
choices=TYPES,
default=PROBE)
description = models.TextField(max_length=200, blank=True)
anwesend = models.ManyToManyField(Member)#TODO: Widget fuer Django Admin aendern
def __unicode__(self):
return str(self.date.strftime("%Y-%m-%d"))+" , "+self.type
#classmethod
def create(cls, date, type, description):
event = cls(date=date, type=type, description=description)
return event
and my html template:
<table>
<tr><th>Name</th>
{% for event in all_events %}
<th>{{event}}</th>
{% endfor %}
</tr>
{% for member in all_members %}
<tr>
<td>{{ member.name }}</td>
<td>{{ event.anwesend }}</td>
</tr>
{% endfor %}
</table>
and my experimental view:
def statistiken(request):
all_members = Member.objects.all()
all_events = Event.objects.all()
for member in all_members:
anwesend=member.name+": "
for event in member.event_set.all():
anwesend+=str(event)
print(anwesend)
context = {'all_members': all_members,
'all_events' : all_events}
return render(request, 'anwesenheitsapp/statistiken.html', context)
Update related to your comment:
from itertools import count, repeat
def statistiken(request):
# Get all members
members = Member.objects.all()
# Get maximum number of related events
max_n_events = max(member.event_set.all().count() for member in members)
# Create a list to hold table data
table_data = []
for member in members:
# Get all related events for the member
events = member.event_set.all()
# Get number of events
n = events.count()
# Append a iterator with member instance, event instances, and
# repeating empty strings to fill up the table
table_data.append(chain([member], events, repeat('', max_n_events-n)))
context = {'table_data': table_data}
return render(request, 'anwesenheitsapp/statistiken.html', context)
and your template to this:
<table>
<tr>
{% for row in table_data %}
{% for col in row %}
<td>{{ col }}</td>
{% endfor %}
{% endfor %}
</tr>
</table>
The strings in the table will be the result of __unicode__() for your member and events, followed by empty cells.
(old answer)
To access all related Events from a Member instance, use event_set.all().
Your template could look something like this:
<table>
{% for member in all_members %}
<td>{{ member }}</td>
{% for event in member.event_set.all %}
<td>{{ event }}</td>
{% endfor %}
{% endfor %}
</table>
Which should produce this table
| member0 | related_event00 | related_event01 | ... | related_event_0n|
| member1 | related_event10 | related_event11 | ... | related_event_1n|
| .... |
| memberm | related_eventm0 | related_eventm1 | ... | related_event_mn|
(n could be different from member to member of course)

Calling values from a dictionary (Django)

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 %}