trying to display the final mark per student. But instead of just showing the result of sum , it displays a chunk of query set: for example:
Annie <QuerySet [{'studName': None, 'attendance__sum': 3}, {'studName': 1, 'attendance__sum': 2}, {'studName': 2, 'attendance__sum': 1}]>
and same goes to the rest of the students.
I would like to display it like :
Annie 2
Benny 3
Charlie 4
My view:
def attStudName(request):
studentName = MarkAtt.objects.all()
mark = MarkAtt.objects.values('studName').annotate(Sum('attendance'))
context = {
'studentName' : studentName,
'mark' : mark
}
return render(request,'show-name.html',context)
My template:
{% for y in mark %}
{% for x in studentName %}
<p>{{x.studName}}</p> <p> {{mark}}</p>
{% endfor %}
{% endfor %}
How do i display each student name with their own mark accordingly? And how do i display the mark without the
Edited:
Model.py:
class Namelist(models.Model):
name = models.CharField(max_length=100)
program = models.CharField(max_length=10)
year = models.IntegerField(default=1)
studType = models.CharField(max_length=15)
courseType = models.CharField(max_length=15)
nationality = models.CharField(max_length=20)
VMSAcc = models.CharField(max_length=30)
classGrp = models.ForeignKey('GroupInfo', on_delete=models.SET_NULL, null=True)
class MarkAtt(models.Model):
studName = models.ForeignKey(Namelist,on_delete=models.SET_NULL,blank=True, null=True, default=None)
classGrp = models.ForeignKey(GroupInfo, on_delete=models.SET_NULL, null=True)
currentDate = models.DateField(default=now())
week = models.IntegerField(default=1)
attendance = models.IntegerField(default=100) #1 is present
Thank you in advance.
The below should return a queryset with student names and marks. Two separate queries should not be needed.
students = MarkAtt.objects.values('studName').annotate(mark=Sum('attendance'))
If studName is a foreign key, do this .values('studName__name')
Then in your context you can just add:
context = {
students = students
}
You can then loop through students in you template and display data as:
<p>{{x.studName}}</p> <p> {{x.mark}}</p>
You are overcomplicating things. Given the following simple context:
students = MarkAtt.objects.values('studName').annotate(mark=Sum('attendance'))
context = {
'students' : students,
}
you can do in the template:
{% for student in students %}
<p>{{student.studName}}</p> <p> {{ student.mark}}</p>
{% endfor %}
Related
I have two models interrelated items and broken :
class Items(models.Model):
id = models.AutoField(primary_key=True)
item_name = models.CharField(max_length=50, blank=False)
item_price = models.IntegerField(blank=True)
item_quantity_received = models.IntegerField(blank=False)
item_quantity_available = models.IntegerField(blank=True)
item_purchased_date = models.DateField(auto_now_add=True, blank=False)
item_units = models.CharField(max_length=50, blank=False)
def __str__(self):
return self.item_name
class Broken(models.Model):
item = models.ForeignKey(Items, default=1, on_delete=models.CASCADE)
item_quantity_broken = models.IntegerField(blank=True)
item_broken_date = models.DateField(auto_now_add=True, blank=False)
item_is_broken = models.BooleanField(default=True)
date_repaired = models.DateField(auto_now=True, blank=True)
def __str__(self):
return self.item.item_name
I wrote this view function to retrieve data to a table into a template:
def broken_items(request):
br = Broken.objects.select_related('item').all()
print(br.values_list())
context = {
'title': 'broken',
'items': br,
}
return render(request, 'store/broken.html', context)
this is the executing query:
SELECT "store_broken"."id",
"store_broken"."item_id",
"store_broken"."item_quantity_broken",
"store_broken"."item_broken_date",
"store_broken"."item_is_broken",
"store_broken"."date_repaired",
"store_items"."id",
"store_items"."item_name",
"store_items"."item_price",
"store_items"."item_quantity_received",
"store_items"."item_quantity_available",
"store_items"."item_purchased_date",
"store_items"."item_units"
FROM "store_broken"
INNER JOIN "store_items"
ON ("store_broken"."item_id" = "store_items"."id")
looks like it gives me all the fields I want. In debugger it shows data from both tables,
so I wrote for loop in template,
{% for item in items %}
<tr>
<td>{{item.id}}</td>
<td>{{item.item_id}}</td>
<td>{{item.item_quantity_broken}}</td>
<td>{{item.item_broken_date}}</td>
<td>{{item.item_is_broken}}</td>
<td>{{item.date_repaired}}</td>
<td>{{item.item_name }}</td>
<td>{{item.item_item_quantity_received}}</td>
<td>{{item.item_quantity_available}}</td>
<td>{{item.item_purchased_date}}</td>
<td>{{item.items_item_units}}</td>
</tr>
{% endfor %}
The thing is this loop only gives me data from broken table only. I can't see data from Items table.
can someone help me to find the reason why other details are not showing?
Your items query is of Broken objects. So in order to access the Items values you need to change your table. For better understanding change your view like this:
brokens = Broken.objects.select_related('item').all()
context = {
'title': 'broken',
'brokens ': brokens,
}
and then your table:
{% for broken in brokens %}
<tr>
<td>{{broken.id}}</td>
<td>{{broken.item.pk}}</td> # This is the item id
<td>{{broken.item_quantity_broken}}</td>
<td>{{broken.item_broken_date}}</td>
<td>{{broken.item_is_broken}}</td>
<td>{{broken.date_repaired}}</td>
<td>{{broken.item.item_name}}</td>
<td>{{broken.item.item_quantity_received }}</td>
<td>{{broken.item.item_quantity_available}}</td>
<td>{{broken.item.item_purchased_date}}</td>
<td>{{broken.item.items_item_units}}</td>
</tr>
{% endfor %}
you loop over a List of Broken objects
to access the related item objects
item.item.item_name
I'm trying create a table with 2 columns:
1) Collections and 2) Qualified Sales.
Like the image above.
Each book count the own qualified_sales.
The Qualified sales(column in the table) must sum all qualified_sales of all books of each collection.
models.py
class Publishing_company(models.Model):
title = models.CharField(max_length=50)
class Collection(models.Model):
publishing_company = models.ForeignKey(Publishing_company, on_delete=models.CASCADE)
class Book(models.Model):
publishing_company = models.ForeignKey(Publishing_company, on_delete=models.CASCADE)
class Sale(models.Model):
book = models.ForeignKey(Book, on_delete=models.CASCADE)
qualified_sale = models.IntegerField(default=0)
views.py
def qlf_sales(request):
book = Collection.objects.filter(user=request.user)
qualified_sum = Sale.objects.filter(user=request.user, book__publishing_company__collection__in=book).aggregate(Sum('qualified_sale'))['qualified_sale__sum'] or 0
context = {'qualified_sum': qualified_sum}
return render(request, 'template.html', context)
template.html
{% for collection in collections %}
<tr>
<td>{{collection}}</td>
<td>{{qualified_sum}}%</td>
</tr>
{% endfor %}
But this code not work. Dont appear any debug error, but in the all fields in the Qualified Sales' column appear the same value: the sum of all qualified_sales of all sales of all book.
why didn't separate by collection?
If anyone can help me. Please i go a lot grateful.
I have two querysets. My first Queryset (services) has all of my service objects. My second Queryset (rating_values) has all of my rating values, where each index corresponds to the index in the services Queryset. For example services[1] corresponds with rating_values[1].
How do I loop through these two queries in an html page in django so so that I can display the service name along with the corresponding rating value?
To be clear, services contains service objects and rating_values contains decimal values. I pass the variables like this:
return render_to_response('services/display_services.html', {'user': request.user, 'services':services, 'rating_values': rating_values })
I would like to do something like this:
{% for service in services %}
<p> {{service.service_name}} : {{ corresponding rating_value}} </p>
Edit
Here is my Service model:
class Service(models.Model):
user_id= models.IntegerField(default=1)
service_name = models.CharField(max_length=100)
address = models.CharField(max_length=200)
def __str__(self): # __unicode__ on Python 2
return self.service_name
Here is my Rating Model:
class Rating(models.Model):
service_id= models.IntegerField(default=1)
service_name= models.CharField(max_length=200)
number_of_ratings = models.IntegerField()
total_rating_value = models.IntegerField()
rating_average = models.FloatField()
def __str__(self): # __unicode__ on Python 2
return self.service_name
Just to answer the original question as well.
If you for some reason don't want a database relation between the models, you could convert the querysets to lists and zip them in the view, turning the querysets to a list of tuples.
view:
return render_to_response(
'services/display_services.html',
context_instance={
'user': request.user,
'services_and_ratings': zip(
services.all(),
rating_values.all()
)
}
)
template:
{% for service, rating in services_and_ratings %}
<p> {{ service.service_name }} : {{ rating.rating_average }} </p>
You can establish the relationship right in the model.
class Rating(models.Model):
service= models.OneToOneField(Service, primary_key=True)
service_name= models.CharField(max_length=200)
number_of_ratings = models.IntegerField()
total_rating_value = models.IntegerField()
rating_average = models.FloatField()
....
You can then pass services and get the corresponding ratings..
{% for service in services %}
<p> {{service.service_name}} : {{ service.rating.rating_average }} </p>
How to get the top 10 users, whose question with most answers? I did it by using 2 requests to db, but I need in one request, if possible.
P.S. I'm using MySQL, there is no 'distinct'
Result format:
User.username | Question.id | number of comments
I have the models:
from django.contrib.auth.models import User
...
class Category(models.Model):
name = models.CharField(max_length=255)
class Question(models.Model):
header = models.CharField(max_length=255)
author = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
creation_date = models.DateTimeField(default=datetime.datetime.now)
view_count = models.IntegerField(default=0)
content = models.TextField()
category = models.ForeignKey(Category, null=True, on_delete=models.SET_NULL)
class Answer(models.Model):
question = models.ForeignKey('Question')
author = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
content = models.TextField()
My realization with 2 requests:
def select5():
print 'SELECT 5'
N = 10
top_n_questions = Answer.objects.all().values('question').annotate(ans_count=Count('question')).order_by('ans_count').reverse()[:N]
top_n_questions_id = []
top_n_questions_rate = []
top_n_users = []
print top_n_questions
for dic in top_n_questions:
top_n_questions_id.append(dic['question'])
top_n_questions_rate.append(dic['ans_count'])
top_n_questions = Question.objects.filter(pk__in=top_n_questions_id)
for question in top_n_questions:
top_n_users.append(question.author)
for i in range(N):
print '%s question id: %d, rate: %d' % (top_n_users[i].username,\
top_n_questions_id[i], top_n_questions_rate[i])
UPD: I found how to do it:
def select6():
print 'SELECT 6'
print 'bla-bla-bla'
top_questions = Question.objects.annotate(answers=Count('answer')).order_by('-answers').select_related('author')[:10]
for question in top_questions:
print '%s question id: %d, rate: %d' % (question.author, question.id, question.answers)
1) By logic you need something like that below (but I think it will work only if question with user has one_to_one relation), so I think it doesn't work, but you can try it =) :
top_users = User.objects.annotate(ans_count=Count('question_set__answer_set')).order_by('-ans_count')[:10]
2) Solution that I suggest (I think is not best, but simple one) is additional field answer_count in Question that store count of answer so I can sort or filter by that value. This field updates after every Answer.objects.create() by post save signal:
#receiver(post_save, sender=Answer)
def update_answer_count(sender, instance, created, **kwargs):
question = instance.question
question.answer_count = sender.objects.filter(question=question).count()
question.save(update_fields=['answer_count'])
so after this you can do:
top_users = User.objects.order_by('-question_set__answer_count')[:10]
and in your template:
{% for user in top_users %}
{% for question in user.question_set.all %}
{{ user.username }}
{{ question.id }}
{{ question.answer_count }}
{% endfor %}
{% endfor %}
This is Laravel's ORM
User::orderBy('answers', 'desc')->take(10)->get();
something like this mate but for DJango!
Entry.objects.all().order_by('answers')[:5]
i am trying to do this:
i have a table of rating records of locations. in this table, one location can also have multiple rating scores. but i want to restrict the search only to the last record of same locations. for example:
one location with id=1 has 3 rating scores: 1, 2, 4. now when user searchs for rating score 2, this location should NOT appear, because its last record is 4.
EDIT
there are two tables(django models): location and rating.
can i do this:
all_locations = Location.objects.all()
then in template. locations_rating is a related_name for foreignkey locationID in rating table.
{% for location in all_locations %}
{{ location.locations_rating }}
{% endfor %}
models.py
class Location(models.Model):
locationname = models.CharField(max_length=100)
def __unicode__(self):
return self.locationname
def latest(self):
return Rating.objects.values('rating').filter(von_location=self).order_by('-id')[0]
class Rating(models.Model):
von_location = models.ForeignKey(Location,related_name="locations_rate")
rating = models.IntegerField()
def __unicode__(self):
return "{0}".format(self.rating)
views.py
all_locs = Location.objects.all()
template
{% for location in all_locs %}
{{ location.locationname }} - {{ location.latest.rating }}<br/>
{% endfor %}
This is pure guessing, but can you do something like this?
Rating.objects.filter(location_id=1).order_by(id).reverse()[0]
Ahh, I misinterpreted the question. Here's a not very efficient way to do what you're asking:
locations = Location.objects.all();
filtered = []
for location in locations:
try:
r = Rating.objects.filter(location=location).order_by(-id).[0]
if r.rating = 2:
filtered.append(location)
except Exception as ex:
pass