I have a query that I do in my view to get a bunch of team stat objects...
team_stats = NCAABTeamStats.objects.filter(
name__name__in=teams_playing).order_by(sort)
One of the fields 'name' is a foreign key. I pass team_stats to my template to display the data in a chart via a 'for loop'.
{% for team in team_stats %}
<tr>
<td>
{{ team.name }}
</td>
</tr>
{% endfor %}
So in my template, for every object in team_stats it is doing a query when it prints {{ team.name }} and it really slows things down, especially when there are 50-100 teams.
My question is, is there a way to print 'team.name' without it doing a query every time?
if it is a foreignkey you can do something like this
team_stats=NCAABTeamStats.objects.select_related('name').filter(name__name__in=teams_playing).order_by(sort)
you can learn more on select_related here
if it is a manytomany field you can do something like this
team_stats=NCAABTeamStats.objects.prefetch_related('name').filter(name__name__in=teams_playing).order_by(sort)
you can learn more on prefetch_related Here
Related
I am working on a basic ecommerce website.I have created a superuser page in which I would like to see all the orders as well as the order details like customer who ordered, their address etc. These are my models.py:
class ShippingAddress(models.Model):
customer=models.ForeignKey(Customer,on_delete=models.SET_NULL,null=True)
order=models.ForeignKey(Order,on_delete=models.SET_NULL,null=True)
address=models.CharField(max_length=200,null=False)
email=models.EmailField(null=False)
class Customer(models.Model):
user=models.OneToOneField(MyUser,null=True,blank=True,on_delete=models.CASCADE)
email=models.CharField(max_length=100)
class Order(models.Model):
customer=models.ForeignKey(Customer,on_delete=models.SET_NULL,null=True,blank=True)
complete=models.BooleanField(default=False,null=True,blank=False)
class OrderItem(models.Model):
product=models.ForeignKey(Product,on_delete=models.SET_NULL,null=True)
order=models.ForeignKey(Order,on_delete=models.SET_NULL,null=True,)
And this is my views.py:
def superuser(request):
user=User.objects.all()
customer=Customer.objects.all()
order=Order.objects.filter(complete=True)
items=OrderItem.objects.all()
shipping=ShippingAddress.objects.all()
return render(request,"superuser.html",{'order':order,'items':items,'customer':customer,'shipping':shipping})
Currently in my template I am unable to iterate over the above context such that I can get all the orders and with the every order I can print their orderitems as well as shipping details as well as customer details. I tried in one way which was really in efficient that was to iterate over all orders then iterate over all orderitems and check if orderitem.order.id was equal to order.id . Please tell me what is the best method to pass the objects in context which are the most efficient for my need . And how to iterate over them in my template.
Thanks
How about this?
# view
from django.shortcuts import render
from .models import Order
def superuser(request):
orders = Order.objects.select_related('customer__user')
orders = orders.prefetch_related('shippingaddress_set')
orders = orders.prefetch_related('orderitem_set')
return render(request,"superuser.html",{'orders':orders})
You can of course chain the .select_related and .prefetch_related calls on the same lines, I've split them up here for increased readability. You can read about select_related and prefetch_related in the docs. You can now use the 'orders' QuerySet in a template like this:
<!--template-->
{% if orders %}
<ul>
{% for order in orders %}
<li>order id: {{order.id}}</li>
<li>customer name: {{order.customer.id}}</li>
<li>customer email: {{order.customer.email}}</li>
{% if order.shippingaddress_set.all %}
<li>Shipping addresses:
<ul>
{% for shipadd in order.shippingaddress_set.all %}
<li>shipping address: {{shipadd.address}}</li>
{% endfor %}
</ul>
</li>
{% endif %}
{% if order.orderitem_set.all %}
<li>Order items:
<ul>
{% for item in order.orderitem_set.all %}
<li>orderitem id: {{item.id}}</li>
{% endfor %}
</ul>
</li>
{% endif %}
{% endfor %}
</ul>
{% endif %}
Using Django Debug Toolbar and going to the page above, I'm informed that 3 SQL queries are made:
One fetches data from the 'order' table, doing a LEFT OUTER JOIN with the 'customers' table ON customer id.
One fetches data from the 'shippingaddress' table, with a WHERE clause specifying rows that have a 'order_id' IN (<list of all order id's>).
A similar query is made for the 'orderitem' table.
This way, Django preemptively fetches all the required data from the database, rather than e. g. doing another query for every iteration.
You might find it strange that I included a loop for the shipping addresses in the HTML template. This is however necessary, because the way you've set up your models, there is a many-to-one relationship from shipping addresses to orders. This doesn't make a lot of sense IMO, so you will probably want to redefine the ShippingAddress model's relationships to the other models.
If you want to use additional information related to each order, you can of course add more prefetch_related/select_related calls before putting the QuerySet in your context.
I have a dictionary that I pass to Django template.
If I render just a dictionary with {{dict}} , then it is rendered fine, like this:
If I render just the keys with {{appoint}}, they are also rendered just fine, like this:
But if I render dictionary values with {{dict.appoint}} then I get nothing
I have read every post here about Django, template language and dictionaries and have not been able to solve this seemingly simple problem.
Render your dict in html like this:
{% for key, value in dict.items() %}
<tr>
<td> {{ key }}: </td> <td> {{ value }} </td>
</tr>
{% endfor %}
you can do with a custom template tag, check in here how to do it https://docs.djangoproject.com/en/3.0/howto/custom-template-tags/
I'm not sure the best way to explain it so I created an example picture and made up some data:
I looked at this post and know I need to use some forloop template stuff: Displaying a Table in Django from Database
The parts that are throwing me off are how to have a table within a table. For example, the doctor 'Bob" has 3 different patients. Bob has one row but Bob's patient column has 3 rows within it.
<table class="table table-striped table-bordered">
<thead>
<th>Name</th>
<th>Total Patient Meetings</th>
<th>Patient</th>
<th>Meetings for Patient</th>
</thread>
<tbody>
{% for doctor in query_results %}
<tr>
<td> {{ doctor.name }} </td>
<td> {{ doctor.total_meetings }}</td>
//*Would I have a nested forloop in here?*//
{% for patient in query_results2 %}
<td> {{patient.name }} </td>
<td> {{patient.meeting_number }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
I'm having trouble finding an example like this to work off of and am not sure how to approach it.
I also need those patients to link to the individual patient pages. So if I click on Bob's patient 'C755' I will be directed to that patient's page. I was thinking something like:
`<p>{{patient.name}}:</p>`
Thanks for any help. Just not sure the best way to approach this.
"A 'related manager' is a manager used in a one-to-many or many-to-many
related context."
https://docs.djangoproject.com/en/1.10/ref/models/relations/
I can't see how your relation between doctor and patient is, but supposing it is something like this:
class Patient(models.Model):
name = models.CharField(max_length=50)
class Doctor(models.Model):
patient = models.ManyToManyField(Patient, verbose_name='patients')
You can easly iterate over doctor.patient using:
{% for doctor in doctors %}
{% for patient in doctor.patients.all %}
{{ patient.name }}
{% endfor %}
{% endfor %}
If you don't have a verbose_name attribute for the relation, then instead of using doctor.patients.all you use doctor.patients_set.all.
And to the patient's page, you can use a method inside your class Patient to easly do this:
{{ patient.name }}
"with get_absolute_url on your model it can make dealing with them on a per-object basis much simpler and cleaner across your entire site"
https://godjango.com/67-understanding-get_absolute_url/
I have managed to create the forms I need using modelformset_factory.
avaluos = Avaluo.objects.filter(Estatus__contains='CONCLUIDO',Factura__isnull=True)
FacturaFormset = modelformset_factory(Avaluo,form=FacturaForm,extra=0)
Currently this is generating the following HTML for each of the rows found:
<form id="id-FacturaForm" class="blueForms" method="post">[..]</form>
<form id="id-FacturaForm" class="blueForms" method="post">[..]</form>
<form id="id-FacturaForm" class="blueForms" method="post">[..]</form>
I want to submit all the forms using a single submit button.
Any ideas?
UPDATE
I ended up using django-crispy-forms which allowed me to gerate inputs for each row, and then I just manually added the form and submit.
self.helper.form_tag = False
{{example_formset.management_form }}
{% for a,b in olist %}
{{ b.id }}
<tr>
<td style="width:10px;"> {% crispy b %} </td>
<td> {{a.id}} </td>
</tr>
{% endfor %}
Read more into model formsets. You don't need to have separate form tags, it's the whole point of using a formset.
<form method="post" action="">
{{ factura_formset.management_form }}
<table>
{% for form in factura_formset %}
{{ form }}
{% endfor %}
</table>
</form>
Also, every time you use the id attribute more than once on a page… a developer cries themselves to sleep somewhere in the world.
I suspect you will need to do it using Ajax - otherwise as soon as one form is submitted you will not be able to go the other way.
There are a few jQuery form libraries that should make it relatively straightforward. For example, http://malsup.com/jquery/form/.
It would look something like:
$('#button-id').click(function() {
$('.blueForms').ajaxSubmit();
});
Of course, you'll then need to deal with error handling and waiting for all the forms to have submitted.
If you're trying to create many instances of the "same" form (this is, they all look equal), as if it were one of many childs belonging to a single, master element, you don't actually need to create a form tag for each of the formsets.
If I'm not mistaken, you're trying to edit many facturas for a single avaluo object. Am I right? The representation would be a single "avaluo" form with many inline formsets, one for each "factura".
Check out the inline formsets factory instead of the modelformset factory.
I'm using Google App Engine and Django templates.
I have a table that I want to display the objects look something like:
Object Result:
Items = [item1,item2]
Users = [{name='username',item1=3,item2=4},..]
The Django template is:
<table>
<tr align="center">
<th>user</th>
{% for item in result.items %}
<th>{{item}}</th>
{% endfor %}
</tr>
{% for user in result.users %}
<tr align="center">
<td>{{user.name}}</td>
{% for item in result.items %}
<td>{{ user.item }}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
Now the Django documention states that when it sees a . in variables
It tries several things to get the data, one of which is dictionary lookup which is exactly what I want but doesn't seem to happen...
I found a "nicer"/"better" solution for getting variables inside
Its not the nicest way, but it works.
You install a custom filter into django which gets the key of your dict as a parameter
To make it work in google app-engine you need to add a file to your main directory,
I called mine django_hack.py which contains this little piece of code
from google.appengine.ext import webapp
register = webapp.template.create_template_register()
def hash(h,key):
if key in h:
return h[key]
else:
return None
register.filter(hash)
Now that we have this file, all we need to do is tell the app-engine to use it...
we do that by adding this little line to your main file
webapp.template.register_template_library('django_hack')
and in your template view add this template instead of the usual code
{{ user|hash:item }}
And its should work perfectly =)
I'm assuming that the part the doesn't work is {{ user.item }}.
Django will be trying a dictionary lookup, but using the string "item" and not the value of the item loop variable. Django did the same thing when it resolved {{ user.name }} to the name attribute of the user object, rather than looking for a variable called name.
I think you will need to do some preprocessing of the data in your view before you render it in your template.
Or you can use the default django system which is used to resolve attributes in tempaltes like this :
from django.template import Variable, VariableDoesNotExist
#register.filter
def hash(object, attr):
pseudo_context = { 'object' : object }
try:
value = Variable('object.%s' % attr).resolve(pseudo_context)
except VariableDoesNotExist:
value = None
return value
That just works
in your template :
{{ user|hash:item }}
#Dave Webb (i haven't been rated high enough to comment yet)
The dot lookups can be summarized like this: when the template system encounters a dot in a variable name, it tries the following lookups, in this order:
* Dictionary lookup (e.e., foo["bar"])
* Attribute lookup (e.g., foo.bar)
* Method call (e.g., foo.bar())
* List-index lookup (e.g., foo[bar])
The system uses the first lookup type that works. It’s short-circuit logic.
As a replacement for k,v in user.items on Google App Engine using django templates where user = {'a':1, 'b', 2, 'c', 3}
{% for pair in user.items %}
{% for keyval in pair %} {{ keyval }}{% endfor %}<br>
{% endfor %}
a 1
b 2
c 3
pair = (key, value) for each dictionary item.
shouldn't this:
{{ user.item }}
be this?
{{ item }}
there is no user object in the context within that loop....?