django sort dict after query - python

have a table with websites and a many to one table with descriptions
trying to get a list, firstly getting the latest descriptions and then displaying them ordered by the content of the descriptions...
have the following in views.py
def category(request, category_name_slug):
"""Category Page"""
context_dict = {}
try:
category = Category.objects.get(slug=category_name_slug)
subcategory = SubCategory.objects.filter(category=category)
websites = Website.objects.filter(sub_categories=subcategory, online=True, banned=False)
sites = websites
descriptions = WebsiteDescription.objects.prefetch_related("about")
descriptions = descriptions.filter(about__in=sites)
descriptions = descriptions.order_by('about', '-updated')
descs = []
last_site = "" # The latest site selected
# Select the first (the latest) from each site group
for desc in descriptions:
if last_site != desc.about.id:
last_site = desc.about.id
desc.url = desc.about.url
desc.hs_id = desc.about.id
desc.banned = desc.about.banned
desc.referral = desc.about.referral
descs.append(desc)
context_dict['descs'] = descs
context_dict['websites'] = websites
context_dict['subcategory'] = subcategory
context_dict['category'] = category
except SubCategory.DoesNotExist:
pass
return render(request, 'category.html', context_dict)
this gives me a list with sites and their latest descriptions, so i have the following in category.html
{% if category %}
<h1>{{ category.name }}</h1>
{% for subcategory in category.subcategory_set.all %}
{{ subcategory.name }} ({{ subcategory.website_set.all|length }})
{% endfor %}
{% if descs %}
{% load endless %}
{% paginate descs %}
{% for desc in descs|dictsortreversed:"description"|dictsortreversed:"officialInfo" %}
<ul id='list' class='linksteps'>
<a href="/{{ desc.about_id }}" rel="nofollow" target="_blank">
<img src="/static/screenshots/{{ desc.about_id }}.png" />
</a>
<li><h3>{{ desc.about_id }}{% if desc.title %} - {{ desc.title }} {% endif %}</h3>
{% if desc.description %}<b>Description: </b>{{ desc.description }}
<br />{% endif %} {% if desc.subject %}<b>Keywords: </b>{{ desc.subject }}
<br />{% endif %} {% if desc.type %}<b>Type: </b>{{ desc.type }}
<br />{% endif %} {% if desc.officialInfo %} {% if desc.language %}<b>Language: </b>{{ desc.language }}
<br />{% endif %} {% if desc.contactInformation %}<b>Contact info: </b>{{ desc.contactInformation }}
<br />{% endif %}
{% else %}
{% endif %}
</li>
</ul>
</div>
{% endfor %}
{% show_pages %}
{% else %}
<strong>No websites currently in category.</strong>
{% endif %}
{% else %}
The specified subcategory {{ category_name }} does not exist!
{% endif %}
Initially i used dictsort
{% for desc in descs|dictsortreversed:"description"|dictsortreversed:"officialInfo"|dictsortreversed:"referral" %}
to give me the list in the desired order, so i was all happy ;)
Then however i decided i needed some pagination because the lists became too long.
django-endless-pagination works fine and does what its supposed too, however it splits up my list before the dictsort kicks in.
is there a way to sort before pagination happens and after i ordered_by at the initial query to have the latest descriptions selected?
much obliged
EDIT:
not getting any answers so my question might not be clear.
as far as i understand i need to sort the values in context_dict at the end in views.py replacing the dictsort as in the template
SOLVED:::
doing this did the trick for me to replace the dictsort.
descs1 = sorted(descs, key=operator.attrgetter('referral', 'officialInfo', 'description'), reverse=True)
context_dict['descs'] = descs1

SOLVED:::
doing this did the trick for me to replace the dictsort.
descs1 = sorted(descs, key=operator.attrgetter('referral', 'officialInfo', 'description'), reverse=True)
context_dict['descs'] = descs1

Related

Jinja2 ValueError: too many values to unpack (expected 2)

{%for feed,tim in feeds,time %}
{% set nickname = feed.nick %}
{% set like = feed.like %}
{% set text = feed.text %}
{% set today = tim %}
{% set postid = feed.postid %}
{% set photo = feed.photo %}
{% set profile = feed.profile %}
{%for cmt in cmts %}
{% set nickname = cmt.nick %}
{% set cmt = cmt.cmt %}
{% set cmtid = cmt.cmtid %}
{% if cmtid == postid %}
<p class="description"><span>{{nickname}} </span> {{cmt}}</p>
{% endif %}
{% endfor %}
<div class="comment-wrapper">
<img src="../static/images/smile.PNG" class="icon" alt="">
<input type="text" class="comment-box" id='cmt' placeholder="Add a comment">
<button class="comment-btn" onclick=cmt_write()>post</button>
</div>
</div>
</div>
{% endfor %}
succeeded in executing the for statement with one list in jinja2,
but we have to use two lists.
i try 2 list ( feeds, time ) use in jinja2
how to jinja2 for loop from jinja2
Is there a way to use two lists in jinja2?
If you want to loop over a combined list of two lists (of same length) you have to apply zip function on them. E.g.:
def view_function():
feeds = [...]
time = [...]
feeds_and_time = zip(feeds, time)
# Looks like this: [('feed_1', 'time_1'), ('feed_2', 'time_2')]
Then pass this new feeds_and_time variable to the render function. And in the template, modify the loop:
{% for feed,tim in feeds_and_time %}

Pagination in Django not working as expected

I wanted pagination for all the courses available and that was easy to achieve. But now I'm stuck because I wanted pagination for faculties also, which will show specific courses of the accessed faculty. I have 4 models: faculties, departments, studies, and courses. The pagination will show for faculties as well, but the problem is that if I try to go to the second page, it will redirect me to the second page of all courses list. Or, if I change page on all courses and then try to access a faculty, no course will show at all in the faculty.
def index(request):
course_list = Course.objects.all()
page = request.GET.get('page', 1)
paginator = Paginator(course_list, 1)
try:
courses = paginator.page(page)
except PageNotAnInteger:
courses = paginator.page(1)
except EmptyPage:
courses = paginator.page(paginator.num_pages)
faculty_list = Faculty.objects.all()
page = request.GET.get('page2', 1)
paginator = Paginator(faculty_list, 1)
try:
faculties = paginator.page(page)
except PageNotAnInteger:
faculties = paginator.page(1)
except EmptyPage:
faculties = paginator.page(paginator.num_pages)
context = {'courses': courses,
'faculties': faculties,
'departments': Department.objects.all(),
'studies': StudyProgramme.objects.all(),
'teachers': Teacher.objects.all()
}
return render(request, 'courses/index.html', context)
<div id="crs">
<h3>All courses</h3>
<ul>
{% for course in courses %}
<li><a href={{ course.slug }}>{{ course.name }}</a></li>
{% endfor %}
</ul>
<div class="pagination">
<span class="step-links">
{% if courses.has_previous %}
« first
{{ courses.previous_page_number }}
{% endif %}
<span class="current">
Page {{ courses.number }} of {{ courses.paginator.num_pages }}
</span>
{% if courses.has_next %}
{{ courses.next_page_number }}
last »
{% endif %}
</span>
</div>
</div>
{% for faculty in faculties %}
<div id="fac_{{ faculty.pk }}_tab" style="display:none;">
<h3> {{ faculty.name }} Courses</h3>
<ul>
{% for department in faculty.department_set.all %}
{% for study in studies %}
{% if study.department == department %}
{% for course in courses %}
{% if course.study_programme == study %}
<li>
<a class="first" href={{ course.slug }}>{{ course.name }}</a>
</li>
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
{% endfor %}
</ul>
<div class="pagination">
<span class="step-links">
{% if faculties.has_previous %}
« first
{{ faculties.previous_page_number }}
{% endif %}
<span class="current">
Page {{ faculties.number }} of {{ faculties.paginator.num_pages }}
</span>
{% if faculties.has_next %}
{{ faculties.next_page_number }}
last »
{% endif %}
</span>
</div>
</div>
{% endfor %}
It's not a Django problem that your view is most certainly handle one pagination parameter page which will direct to courses, so if you changed the get parameter for each of your model pagination it will work.
ex:
## views.py
page = request.GET.get('page')
## yourtemplate.html
yourtext
localhost:8000/MYVIEW/?page=2 # Goes to courses
## views.py
page = request.GET.get('faculties')
## yourtemplate.html
yourtext
##
localhost:8000/MYVIEW/?faculties=2 # Goes to faculties
etc..
edited:
{% for faculty in faculties %} change it to {% for faculty in faculties2 %} and remove faculties from your context, cuz you are repeating yourself as faculties2 and faculties hold the same queryset .
paginator = Paginator(course_list, 1)
paginator = Paginator(faculty_list, 1)
Changing your second instance name to paginator_two would solve your problem

Django store information in one variable

I have different pages with items, each item has its own price which I would like to store in one variable and then send all of them to paypal payment form.
So question is,how can I store information about price from different pages? I tried sessions but nothing happens.
<article>
{% block content %}
<span>Kuriame mieste registruojiesi</span>
<select>
{% for item in upsell.skaidyti_miestus %}
<option value="{{item}}">{{ item }}</option>
{% endfor %}
</select>
{%if upsell.prideti_upsell_nr_2_taip%}
<button onclick="location.href='/upselliai/{{upsell.upsell_nr2_taip.id}}/pirkti/'">Taip, pridÄ—ti prie bendros sumos</button>
<!-- {#prideti kaina paimti ID} -->
{% else %}
<button onclick="location.href='/pirkejas/apmoketi'">Taip, pridÄ—ti prie bendros sumos</button>
{%endif%}
{%if upsell.prideti_upsell_nr_2_ne%}
{{ upsell.atsisakymo_tekstas }}
<!-- {#prideti kaina paimti ID} -->
{% else %}
{{ upsell.atsisakymo_tekstas }}
{%endif%}
{% endblock %}
</article>
my views.py
def pirkti_upsell(request, upsellis_id = 1):
#if 'pirkejas_id' in request.session:
session_pirkejas_id = request.session['pirkejas_id']
Upsellis.objects.get(id = upsellis_id).sum(session_pirkejas_id)
return render_to_response("upsell_template.html", {"upsell": Upsellis.objects.get(id = upsellis_id)})

Paginating based on the alphabet (A-Z)

I have a simple contacts application where I want to paginate the contact list based on first name alphabet.
Here is my views.py
def contacts(request):
contact_list = Contact.objects.filter(user=request.user).order_by('first_name')
pages = [contact_list.filter(first_name__istartswith=i) for i in "ABCDEFGHIJKLMNOPQRSTUVWXYZ"]
return render(request, 'contact/contact.html', {'contact_list': contact_list, 'pages': pages})
Here is my template
{% for alphabet in pages %}
{% if alphabet %}
<p>{{ alphabet }}</p>
{% for contact in contact_list %}
{% if contact in pages %}
<ul>
<li>{{ contact.first_name }}</li>
</ul>
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
The output from this is something like
[<Contact: Steve>, <Contact: Su>]
Steve
Su
[<Contact: Ted>]
Ted
[<Contact: Zedd>]
Zedd
The {{ alphabet }} prints a list. What should I write to print the alphabet instead?
Capture the alphabet in the context variable:
pages = [{"letter": i, "contacts": contact_list.filter(first_name__istartswith=i) }
for i in "ABCDEFGHIJKLMNOPQRSTUVWXYZ"]
return render(request, 'contact/contact.html', {'pages': pages}) # why pass contact_list?
Your template should be simplified to:
{% for alphabet in pages %}
{% if alphabet.contacts %}
<p>{{ alphabet.letter }}</p>
{% for contact in alphabet.contacts %}
<ul>
<li>{{ contact.first_name }}</li>
</ul>
{% endfor %}
{% endif %}
{% endfor %}

Iterate Items in Their Specific Groups in Django

In my Django template I want to be able to iterate through groups and items, but I want to iterate the items underneath their group. So far I have them iterating like this but it does not show which groups the items are a part of. How would I iterate the template to get this inclusion?
Views:
def manage(request):
group_list = Group.objects.order_by('name').filter(user=request.user)
item_list = Item.objects.order_by('name').filter(user=request.user)
return render(request, 'manage.html', {'group_list': group_list, 'item_list': item_list})
Template:
{% extends "base.html" %}
{% block content %}
{% for group in group_list %}
{{ group.name }}<br />
{% endfor %}
{% for item in item_list %}
{{ item.name }}<br />
{% endfor %}
{% endblock %}
UPDATE
Models (Sorry forgot to include this):
class Group(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=30)
class Item(models.Model):
user = models.ForeignKey(User)
group = models.ManyToManyField(Group)
name = models.CharField(max_length=30)
Your approach does unneccessary additional database hits. For performance reasons you should select just the items with related groups like this:
def manage(request):
item_list = Item.objects.order_by(
'group__name', 'name').filter(
user=request.user).select_related('group')
return render(request, 'manage.html', {'item_list': item_list})
The template looks like this:
{% extends "base.html" %}
{% block content %}
{% for item in item_list %}
{% ifchanged item.group.name %}
{{ item.group.name }}<br />
{% endifchanged %}
{{ item.name }}<br />
{% endfor %}
{% endblock %}
That way you only have ONE database hit regardless of how many groups there are.
I guess you have a fk from item to group
class Item(models.Model):
group = models.ForeignKey(Group)
views:
def manage(request):
group_list = Group.objects.order_by('name').filter(user=request.user)
return render(request, 'manage.html', {'group_list': group_list})
template:
{% extends "base.html" %}
{% block content %}
{% for group in group_list %}
{{ group.name }}<br />
<p>Item for this group</p>
{% for item in group.item_set.all %}
{{item.name}}
{% endfor %}
{% endfor %}
{% endblock %}

Categories

Resources