Django ordering search results from get_queryset(self) - python

I am using django 2.2.10. I have a searchbar which returns search results to the showpage, using get_queryset(self) in searchresultsview(listview) class. I have set paginate_by=10. In the front-end I made links to order the table: `
<th>Title original </th>
At the start of the get_queryset(self) function I have the following code:
order_by = self.request.GET.get('order_by')
direction = self.request.GET.get('direction')
if order_by is not None and order_by != "" and direction is not None and direction != "":
ordering = Lower(order_by)
if direction == 'desc':
ordering = '-{}'.format(ordering)
publications = Publication.objects.filter(is_deleted=False).order_by(ordering)
'''
paginator = Paginator(publications, 10)
page = self.request.GET.get('page')
try:
all_publications = paginator.page(page)
except PageNotAnInteger:
all_publications = paginator.page(1)
except EmptyPage:
all_publications = paginator.page(paginator.num_pages)
'''
return publications
The main problem is that the publications variable contain all publications, I want to restrict it to the publications from the previous get_queryset(self) call. Also the showpage is paginated (paginate_by = 10 in template).The ordering for descending does not work I get: invalid order_by arguments: ['-Lower(F(title_original))'] . If I order ascending it logically does not keep my search results.
I tried finding a stackoverflow solution but the explanation is minimal. Any help would be appreciated.
It might be easier to use django-tables, if so I am open for suggestions.
view codes:
class SearchResultsView(ListView):
'''
ListView of the initial search page.
The function get_queryset works for the search bar and the search form home page.
The search bar typically uses q for query otherwise a id for list search.
Use a countries_dict to convert for example Netherlands to NL so that search succeeds.
If a normal field is searched use __icontains if a list element is searched use: __in.
'''
model = Publication
template_name = 'publications/show.html'
context_object_name = 'publications'
publications = Publication.objects.filter(is_deleted=False)
#paginator = Paginator(publications, 10)
#paginator = Paginator(publications, 25)
paginate_by = 10
def get_ordering(self):
order_by = self.request.GET.get('order_by')
direction = self.request.GET.get('direction')
if order_by is not None and order_by != "" and direction is not None and direction != "":
ordering = Lower(order_by)
if direction == 'desc':
ordering = '-{}'.format(ordering)
return ordering
def get_queryset(self):
#form = PublicationForm(self.request.GET)
authors = self.request.GET.getlist('author')
translators = self.request.GET.getlist('translator')
authors = Author.objects.filter(pk__in=authors).all()
translators = Translator.objects.filter(pk__in=translators).all()
form_of_publications = self.request.GET.getlist('form_of_publication')
form_of_publications = FormOfPublication.objects.filter(pk__in=form_of_publications).all()
languages = self.request.GET.getlist('language')
languages = Language.objects.filter(pk__in=languages).all()
affiliated_churches = self.request.GET.getlist('affiliated_church')
affiliated_churches = Church.objects.filter(pk__in=affiliated_churches).all()
content_genres = self.request.GET.getlist('content_genre')
content_genres = Genre.objects.filter(pk__in=content_genres).all()
connected_to_special_occasions = self.request.GET.getlist('connected_to_special_occasion')
connected_to_special_occasions = SpecialOccasion.objects.filter(pk__in=connected_to_special_occasions).all()
currently_owned_by = self.request.GET.getlist('currently_owned_by')
currently_owned_by = Owner.objects.filter(pk__in=currently_owned_by).all()
copyrights = self.request.GET.get('copyrights')
is_a_translation = self.request.GET.get('is_a_translation')
publications = Publication.objects.filter(is_deleted=False)
uploadedfiles = self.request.GET.getlist('uploadedfiles')
uploadedfiles = UploadedFile.objects.filter(pk__in=uploadedfiles).all()
keywords = self.request.GET.getlist('keywords')
keywords = Keyword.objects.filter(pk__in=keywords).all()
translated_from = self.request.GET.getlist('translated_From')
translated_from = Language.objects.filter(pk__in=translated_from).all()
city = self.request.GET.getlist('publication_city')
country = self.request.GET.getlist('publication_country')
collection_country = self.request.GET.getlist('collection_country')
if list(collection_country) != ['']:
collection_country = Country.objects.filter(pk__in=city).all()
if list(country) != ['']:
country = Country.objects.filter(pk__in=city).all()
print('....', city)
if list(city) != ['']:
city = City.objects.filter(pk__in=city).all()
print(publications)
exclude = ['csrfmiddlewaretoken','search']
in_variables = [('author', authors), ('translator', translators), ('form_of_publication', form_of_publications), ('language',languages), ('affiliated_church', affiliated_churches) \
, ('content_genre', content_genres), ('connected_to_special_occasion', connected_to_special_occasions), ('currently_owned_by', currently_owned_by),\
('uploadedfiles', uploadedfiles), ('publication_country', country), ('publication_city', city), ('collection_country', collection_country), ('keywords', keywords), ('translated_from',translated_from)]
special_case = ['copyrights', 'page', 'is_a_translation']
if ('q' in self.request.GET) and self.request.GET['q'].strip():
query_string = self.request.GET['q']
if query_string.lower() in countries_dict.keys():
query_string = countries_dict[query_string.lower()]
search_fields = ['title_original', 'title_subtitle_transcription', 'title_subtitle_European', 'title_translation', 'author__name', 'author__name_original_language', 'author__extra_info', \
'form_of_publication__name', 'editor', 'printed_by', 'published_by', 'publication_date', 'publication_country__name', 'publication_city__name', 'publishing_organisation', 'translator__name', 'translator__name_original_language', 'translator__extra_info', \
'language__name', 'language__direction', 'affiliated_church__name', 'extra_info', 'content_genre__name', 'connected_to_special_occasion__name', 'donor', 'content_description', 'description_of_illustration', \
'nr_of_pages', 'collection_date', 'collection_country__name', 'collection_venue_and_city', 'contact_telephone_number', 'contact_email', 'contact_website', \
'currently_owned_by__name', 'uploadedfiles__description', 'uploadedfiles__uploaded_at', 'general_comments', 'team_comments', 'other_comments', 'keywords__name', 'is_a_translation', 'ISBN_number', 'translated_from__name', 'translated_from__direction']
arabic_query = translator.translate(query_string, dest='ar').text
query_string = to_searchable(query_string)
#arabic_query = to_searchable(arabic_query)
entry_query = get_query(query_string, search_fields)
arabic_query = get_query(arabic_query, search_fields)
print('&&&&&&', query_string)
#publications = publications.filter(entry_query)
publications = publications.filter(Q(entry_query) | Q(arabic_query))
print(publications)
publications = publications.distinct()
return publications
for field_name in self.request.GET:
get_value = self.request.GET.get(field_name)
if get_value != "" and not field_name in exclude and not field_name in [i[0] for i in in_variables] and\
not field_name in special_case:
print('******', field_name)
arabic_query = translator.translate(get_value, dest='ar').text
get_value = to_searchable(get_value)
get_value = get_query(get_value, [field_name])
arabic_query = get_query(arabic_query, [field_name])
print('444444444', get_value)
publications = publications.filter(Q(get_value) | Q(arabic_query))
print('55555555555', publications)
#publications = publications.filter(Q(**{field_name+'__regex':get_value}) | Q(**{field_name+'__icontains':arabic_query}) )
for field_name, list_object in in_variables:
print('****', list_object)
if list_object:
print('------', field_name)
if list(list_object) != ['']:
publications = publications.filter(**{field_name+'__in': list_object})
if str(copyrights) != "unknown" and str(copyrights) != "None":
val = False
if str(copyrights) == "yes":
val = True
print('11111', str(copyrights))
publications = publications.filter(copyrights=val)
print('666666', publications)
if str(is_a_translation) != "unknown" and str(is_a_translation) != "None":
val = False
if str(is_a_translation) == "yes":
val = True
print('11111', str(is_a_translation))
publications = publications.filter(is_a_translation=val)
publications = publications.distinct()
return publications

You can use get_ordering method
def get_ordering(self):
ordering = self.request.GET.get('ordering', ''#default order param)
return ordering

I solved this. Basically if you have a get_queryset method you need to call get_ordering from there. Also for pagination you need to have the sorting variables in context so that if you go to page 2 for example, the ordering is maintained. Below is the solution code:
ordering = self.get_ordering()
if ordering is not None and ordering != "":
publications = publications.order_by(ordering)
return publications
def get_context_data(self, **kwargs):
context = super(SearchResultsView, self).get_context_data(**kwargs)
order_by = self.request.GET.get('order_by')
if order_by is not None and order_by != "":
context['order_by'] = order_by
context['direction'] = self.request.GET.get('direction')
else:
context['order_by'] = ''
context['direction'] = ''
q = self.request.GET.get('q')
if q is not None and q != "":
context['q'] = q
else:
context['q'] = ''
return context
And the html code:
{% extends "base.html" %}
{% block content %}
<table class="table table-striped table-bordered table-sm">
<thead class="thead-light">
<tr>
<th>Title original </th>
<th>Title subtitle transcription </th>
<th>Title translation </th></th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<br />
{% for publication in publications %}
<tr id="publications">
<td style="text-align: start;unicode-bidi: plaintext;">{{ publication.title_original }}</td>
<td>{{ publication.title_subtitle_transcription}}</td>
<td>{{ publication.title_translation }}</td>
<td>
View
<span class="glyphicon glyphicon-pencil" >Edit</span>
<a class="confirm-delete-pub" href="/publication/{{ publication.id }}/delete">Delete</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="pagination">
<span class="step-links">
{% if page_obj.has_previous %}
« first
previous
{% endif %}
<span class="current">
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
</span>
{% if page_obj.has_next %}
next
last »
{% endif %}
</span>
</div>
{% endblock %}

Related

django - how do i use an input from a select form to compare data in my database and output it on another page?

<form method = "POST">
{% csrf_token %}
<div class = "lookback"
<label for = "time"></label>
<select name = "time" id = "time">
<option value = "today">Today</option>
<option value = "yesterday">Yesterday</option>
<option value = "lastweek">Last Week</option>
<option value = "lastmonth">Last Month</option>
<option value = "lastyear">Last Year</option>
<option value = "forever">Forever</option>
</select>
<button><a type= "button" class = "Look" id = "look" href = "">Look Back?!</a></button>
</form>
** Above is the portion of HTML page i am using to get the select value so that I can use it in my views.py to filter out the data and output it on another page. **
def retro(request):
if request.method == "POST":
time = ThoughtForm(request.POST)
today = timezone.now().date()
if time == "Yesterday":
yesterday = timezone.now().date() - timedelta(days=1)
data = Thought.objects.filter(date__gte=yesterday, date__lt=today)
elif time == "Last Week":
week = timezone.now().date() - timedelta(days=7)
data = Thought.objects.filter(date__gte=week, date__lt=today)
elif time == "Last Month":
month = timezone.now().date() - timedelta(days=30)
data = Thought.objects.filter(date__gte=month, date__lt=today)
elif time == "Last Year":
year = timezone.now().date() - timedelta(days=365)
data = Thought.objects.filter(date__gte=year, date__lt=today)
elif time == "Forever":
data = Thought.objects.all
else:
data = Thought.objects.filter(date__gte=today, date__lt=today)
return render(request,'look.html', {'data' : data})
else:
return render(request, 'retro.html')
When I use the submit button of the retro.html (the one with the select input), it does direct me to the page I want to output my data to. However, it does not print the data in the page.
<div class = "results">
<form method = "GET" >
<h1>Till now, you thought of writing- </h1>
<table class="table">
<thead class = "thead-dark">
<tr>
<td>Thought</td>
<td>Date</td>
</tr>
</thead>
<tbody>
{% for obj in data%}
<tr>
<td scope="row">{{ obj.thought }}</td>
<td>{{ obj.date.date}}</td>
</tr>
{% endfor %}
Directly above is the html for the page I am trying to output my data in.
from django.db import models
from django.utils import timezone
# Create your models here.
class Thought(models.Model):
thought = models.CharField( max_length=300)
done = models.BooleanField(default = False)
#date = models.models.DateField()
date = models.DateTimeField(default=timezone.now)
def __str__(self):
return str(self.thought) + "- " + str(self.done)
Directly above is my models.py file.
from django import forms
from retrospection.models import Thought
class ThoughtForm(forms.ModelForm):
class Meta:
model = Thought
fields = ['thought', 'done', 'date']
Directly above is my form.py file.
After trying what Blackeagle52 suggested and by printing(form.is_valid()), I found out that my form is failing the is_valid test with an error -
<ul class="errorlist"><li>thought<ul class="errorlist"><li>This field is required.</li></ul></li><li>date<ul class="errorlist"><li>This field is required.</li></ul></li></ul>
My form contains a select item with a few options and a submit button. I am not sure how the field can be empty. Please help me.
def retro(request):
if request.method == "POST":
form = ThoughtForm(request.POST)
if form.is_valid():
time = form.cleaned_data['time']
today = timezone.now().date()
if time == "Yesterday":
yesterday = timezone.now().date() - timedelta(days=1)
data = Thought.objects.filter(date__gte=yesterday, date__lt=today)
elif time == "Last Week":
week = timezone.now().date() - timedelta(days=7)
data = Thought.objects.filter(date__gte=week, date__lt=today)
elif time == "Last Month":
month = timezone.now().date() - timedelta(days=30)
data = Thought.objects.filter(date__gte=month, date__lt=today)
elif time == "Last Year":
year = timezone.now().date() - timedelta(days=365)
data = Thought.objects.filter(date__gte=year, date__lt=today)
elif time == "Forever":
data = Thought.objects.all
else:
data = Thought.objects.filter(date__gte=today, date__lt=today)
return render(request,'look.html', {'data' : data})
# TODO Do something when form is invalid.
# Maybe just removing the else below this, so you'll get retro.html
else:
return render(request, 'retro.html')
To explain my solution, in your code time was not a value, but a Form.
To retrieve the data from the form, you first need to check whether the form is valid (is_valid()) and than retrieve the value from form.cleaned_data.
There are some other minor things you could improve. After a POST, redirect to another view, as now this look.html is only visible on a POST. If you want to refresh that page or something, you'll be back at retro.html.
With the Forever-case, you are also missing () on your .all() call.

Django dynamic Search View based on filled GET request keys

please how is possible in Django to reach a view, which will be filtering based on filled keys from GET request?
I am using only one search view, but two forms:
I am taking these requests:
q = request.GET.get('q') # this is for VIN and LOT number (two columns in Model/DB)
make = request.GET.get('make')
model = request.GET.get('model')
year_from = request.GET.get('year_from')
year_to = request.GET.get('year_from')
There are no required fields/requests, so it should work dynamically. If the user fills "q" - it will filter out by VIN or LOT number.
If the user will fill Make and Year, it will filter out by make and to year...
How is possible to do this, some better way, than if , elif, elif, elif, ... Is there any proper way, please?
This is my solution, but I really dont like it, it is not professional and I don't know, how to find a better solution
def is_valid_queryparam(param):
return param != '' and param is not None
def search_filer(request):
qs = Vehicle.objects.all()
# VIN and Lot number
q = request.GET.get('q')
make = request.GET.get('make')
model = request.GET.get('model')
year_from = request.GET.get('year_from')
year_to = request.GET.get('year_from')
if is_valid_queryparam(q):
qs = qs.filter(Q(vin__icontains=q) | Q(lot_number__icontains=q))
elif is_valid_queryparam(make):
qs = qs.filter(make__name__exact=make)
elif is_valid_queryparam(model):
qs = qs.filter(model__name__exact=model)
elif is_valid_queryparam(year_from):
qs = qs.filter(year__gte=year_from)
elif is_valid_queryparam(year_to):
qs = qs.filter(year__lte=year_to)
elif is_valid_queryparam(make) and is_valid_queryparam(model):
qs = qs.filter(make__name__exact=make)\
.filter(model__name__exact=model)
elif is_valid_queryparam(make) and is_valid_queryparam(model) and is_valid_queryparam(year_from):
qs = qs.filter(make__name__exact=make)\
.filter(model__name__exact=model)\
.filter(year__gte=year_from)
elif is_valid_queryparam(make) and is_valid_queryparam(model)\
and is_valid_queryparam(year_from) and is_valid_queryparam(year_to):
qs = qs.filter(make__name__exact=make)\
.filter(model__name__exact=model)\
.filter(year__gte=year_from)\
.filter(year__lte=year_to)
...
...
...
return qs
def search_view(request):
qs = search_filer(request)
# Year field for search form
today = datetime.now()
context = {
'queryset': qs,
'years_from': reversed(range(1920, today.year + 1)),
'years_to': reversed(range(1920, today.year + 1))
}
return render(request, 'search.html', context)
Thank you for any advice!
And also I don know, why context is not reusable, as you can see, I have created two variables years_from and years_to because I am looping through them in the template:
<option value>From ...</option>
{% for y in years_from %}
<option value="{{ y }}">{{ y }}</option>
{% endfor %}
<option value>To ...</option>
{% for y in years_to %}
<option value="{{ y }}">{{ y }}</option>
{% endfor %}
When I tried to create only a one-year variable and loop through in template, it was working. But when I created another loop with the same variable, no values were shown. So I have created exact same variable and looped.
Thank you very much!
I have figured out, how to solve that. It is really not professional, but it does the desired work. I will be glad for any advice or hints, to make my code better. If someone will be trying something like me, here is my solution:
def is_valid_queryparam(param):
return param != '' and param is not None
def is_valid_name(name):
return name == 'make' or name == 'model' or name == 'year_from' or name == 'year_to'
def get_filter(key):
if key == 'make':
return 'make__name__exact'
if key == 'model':
return 'model__name__exact'
if key == 'year_from':
return 'year__gte'
if key == 'year_to':
return'year__lte'
def search_view(request):
queryset = None
valid_params = False
# VIN and LOT number
q = request.GET.get('q')
if is_valid_queryparam(q):
queryset = Vehicle.objects.filter(Q(vin__icontains=q) | Q(lot_number__icontains=q))
else:
request_filter = {}
q_list = Q()
for key, value in request.GET.items():
if is_valid_name(key) and is_valid_queryparam(value):
valid_params = True
request_filter[get_filter(key)] = value
if valid_params:
for k, v in request_filter.items():
q_list.add(Q(**{k: v}), Q.AND)
queryset = Vehicle.objects.filter(q_list)
# Year field for search form
today = datetime.now()
years_from = reversed(range(1920, today.year + 1))
years_to = reversed(range(1920, today.year + 1))
context = {
'queryset': queryset,
'years_from': years_from,
'years_to': years_to
}
return render(request, 'search.html', context)

Django template rendering not giving expected results

I am rendering data from my views into my template, as follows:
<tbody>
{% for item in lyrics %}
<tr class='lyrics-table'>
<td>{{item}}</td>
<td>
{% if item in user_flash %}
<p>{{flash}}</p>
{% else %}
<p>xxx</p>
{% endif %}
</td>
{{item}} works as expected, but {{flash}} only gives the same value for every row, instead of the relevant value.
My views are as follows:
class SongVocab(LoginRequiredMixin, generic.DetailView):
model= models.Song
template_name = 'videos/song_vocab.html'
context_object_name = 'song'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
from pymystem3 import Mystem
m = Mystem()
user_flash = Flashcard.objects.filter(owner=self.request.user).values_list('question', flat=True)
lyrics_list = models.Song.objects.get().lyrics_as_list()
user_flash_ = [item.replace('\n', ' ') for item in m.lemmatize(" ".join(user_flash))]
user_flash_clean = [w for w in user_flash_ if w.strip()] ##removes empty strings
lyrics_list_ = [item.replace('\n', ' ') for item in m.lemmatize(" ".join(lyrics_list))]
lyrics_list_clean = [w for w in lyrics_list_ if len(w.strip())]
user_word = list(set(user_flash_clean) & set(lyrics_list_clean))
import icu # PyICU
def sorted_strings(strings, locale=None):
if locale is None:
return sorted(strings)
collator = icu.Collator.createInstance(icu.Locale(locale))
return sorted(strings, key=collator.getSortKey)
context['percent_known'] = ((len(user_word))/(len(set(lyrics_list_clean))))*100
context['lyrics'] = sorted_strings(set(lyrics_list_clean),"ru_RU.UTF8")
context['user_flash'] = user_flash_clean
for word in user_word:
flash = Flashcard.objects.get(owner=self.request.user, question=word)
context['flash'] = flash.answer
return context
I thought that using the for loop would let me get flash.answer for all words in user_word. In the example I'm testing, there should be two words, but I get just one. What am I doing wrong?
Models.py:
class Flashcard(models.Model):
owner = models.ForeignKey(User, on_delete=models.CASCADE)
deck = models.ForeignKey(Deck, on_delete=models.CASCADE)
question = models.TextField()
answer = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
last_shown_at = models.DateTimeField(auto_now_add=True)
next_due_date = models.DateTimeField(default=timezone.now)
difficulty = models.FloatField(default=2.5)
consec_correct_answers = models.IntegerField(default=0)
objects = FlashcardManager()
def __str__(self):
return self.question
def number_of_questions(self):
return self.question.count(deck=deck.id)
In your code
for word in user_word:
flash = Flashcard.objects.get(owner=self.request.user, question=word)
context['flash'] = flash.answer
context['flash'] will hold the last flash.answer, because the last line is outside the for-loop (it has one indentation level less than the second line).
Did you perhaps mean something like this?
context['flash_list'] = []
for word in user_word:
flash = Flashcard.objects.get(owner=self.request.user, question=word)
context['flash_list'].append(flash.answer)

mysql returning 1 row per id/name

I want to join 3 tables and get the results of them without any duplicates
SELECT * FROM `database`.project
INNER JOIN post on project.id = post.project_id
INNER JOIN media on media.post_id = post.id
;
Current output
I was wondering if the output could be something like
floaty
Headphone
fasion + technolgie
I tried using the distinct function. but then it only returns the names's i would like to return the joined tables, because i still want to use that data.
models.py
I am using the Project.with_media() all
"""models."""
from app import db
from peewee import *
import datetime
class Project(Model):
"""Projects."""
name = CharField(unique=True)
content = CharField()
created_date = DateTimeField(default=datetime.datetime.today())
class Meta(object):
"""Select database."""
database = db
def get_project_media(self):
"""Grab image from get_posts."""
post = Post.select().where(Post.project_id == self).get()
return Media.select().where(Media.post_id == post).get().media
def check_media(self):
"""Check if project has media."""
try:
post = Post.select().where(Post.project_id == self).get()
Media.select().where(Media.post_id == post.id).get()
print('True')
return True
except DoesNotExist:
print('False')
return False
This is my calling so i can display it on jinja engine
def with_media():
"""Grab image from get_posts."""
return (Project.select(Project, Post, Media)
.join(Post)
.join(Media)
.where(Post.id == Media.post_id
and
Project.id == Post.project_id))
def posts(self):
"""Return all posts that are accosicated with this project."""
return Post.select().where(Post.project_id == self)
def media_post(self):
"""Return all posts that are accosicated with this project."""
post = Post.select().where(Post.project_id == self)
return post.get_media()
# return Media.select().where(Media.post_id == post).get()
class Post(Model):
"""Model for posts."""
project = ForeignKeyField(Project, backref='Post', null=True, default=None)
name = CharField()
content = TextField()
"Media Model"
"Category Model"
"Project Model"
created_date = DateTimeField(default=datetime.datetime.today())
class Meta(object):
"""Select database."""
database = db
def get_category(self):
"""Grab all the posts from project."""
return (Category.select()
.where(Category.post_id == self))
def get_media(self):
"""Grab all media from this post."""
return (Media.select()
.where(Media.post_id == self))
def standalone():
"""Return a model of all posts not bound to a project."""
return (Post.select()
.where(Post.project.is_null())
.order_by(Post.created_date.desc()))
def date():
"""Return dates order_by."""
return(Post.select()
.order_by(Post.created_date.desc()))
class Media(Model):
"""Media for post."""
post = ForeignKeyField(Post, backref='Media')
media = CharField()
class Meta(object):
"""Select database."""
database = db
class Category(Model):
"""model for all avaible category's."""
post = ForeignKeyField(Post, backref='Category')
name = CharField()
class Meta(object):
"""Select database."""
database = db
def get_name():
"""Get all category's without overlaping."""
categorys = Category.select()
categoryList = []
for category in categorys:
categoryName = category.name.title()
if categoryName not in categoryList:
categoryList.append(categoryName)
return categoryList
def initialize():
"""Create tables."""
db.connect()
db.create_tables([Category, Project, Post, Media], safe=True)
db.close()
main.py
I want to call the projects with media() function so i can use the database items to call images and display content
<ul class='projects'>
{% for project in projects.with_media() %}
{% if loop.index <= 3 %}
<li class='project_w'>
<img src="{{project.media_post()}}" alt="">
<a href="{{url_for('project', id=project.id)}}">
<h2>{{project.name}}</h2>
</a>
</li>
{% else %}
<li class='project_h'>
<img src="{{project.post.media.media}}" alt="">
<a href="{{url_for('project', id=project.id)}}">
<h2>{{project.name}}</h2>
</a>
</li>
{% endif %}
{% endfor %}
</ul>
The problem:
.where(Post.id == Media.post_id
and
Project.id == Post.project_id))
Instead of "and" you must use "&". Please see http://docs.peewee-orm.com/en/latest/peewee/query_operators.html

Sorting a filtered list in ascending/descending order in django

I have created an Employee management system using Django. I have done a filtering method in it and is based on a choice selected from a drop down menu and a text input. the filtering is working fine. On the first page it gives the entire employee list which can be shown in both ascending and descending order. On the same page is given the filtering method. The filtered data is shown in another page. Now i want to give a button on the filtered data page, clicking on that button shows the data in ascending/descending. I have written a separate function for ascending and descending in views for the full employee listing. How can it be used for this functionality. I will paste my code here. Please help me to find a solution as i am new to django programming.
I have given 2 separate images for ascending and descending.I want it this way: Clicking on 1 image lists in ascending order; and clicking on other image lists it in descending order.
Filter()
def filter(request):
val3=''
if request.GET.has_key('choices'):
val2=request.GET.get('choices')
if request.GET.has_key('textField'):
val3=request.GET.get('textField')
if request.POST:
val2=request.POST.get('choices')
val3=request.POST.get('textField')
if val2=='Designation':
newData = EmployeeDetails.objects.filter(designation=val3)
flag=True
elif val2=='Name':
newData = EmployeeDetails.objects.filter(userName__icontains=val3)
flag=True
elif val2=='EmployeeID':
newData = EmployeeDetails.objects.filter(employeeID=val3)
flag=True
elif val2=='Project':
newData = EmployeeDetails.objects.filter(project=val3)
flag=True
elif val2=='DateOfJoin':
newData = EmployeeDetails.objects.filter(dateOfJoin=val3)
flag=True
else:
return HttpResponseRedirect('/employeeList/')
#tableList = EmployeeDetails.objects.all()
paginator = Paginator(newData, 10)
try:
page = int(request.GET.get('page', '1'))
except ValueError:
page = 1
try:
contacts = paginator.page(page)
except (EmptyPage, InvalidPage):
contacts = paginator.page(0)
return render_to_response('filter.html',{'newData':newData,'emp_list': contacts,'val2':val2,'val3':val3,'flag':flag})
filter.html
<div>
Employees List
<a STYLE="text-decoration:none" align=center href="http://10.1.0.90:8080/sortAscend/ "> <img src="/static/sort_asc.gif " border="1" height="12" /> </a>
<h4 align="left">
{%for data in newData%}
<a STYLE="text-decoration:none" href ="http://10.1.0.90:8080/singleEmployee/{{data.id}}?choices={{val2}}&textField={{val3}}&flag=1 ">
{{ data.userName}}<br>
{%endfor%}
</h4>
</div>
ascending and descending functions
def sortAscend(request):
tableList = EmployeeDetails.objects.all().order_by('userName')
paginator = Paginator(tableList, 12)
try:
page = int(request.GET.get('page', '1'))
except ValueError:
page = 1
try:
contacts = paginator.page(page)
except (EmptyPage, InvalidPage):
contacts = paginator.page(0)
return render_to_response('sortAscend.html', {'emp_list': contacts})
#Method for listing the employees in descending order
def sortDescend(request):
tableList = EmployeeDetails.objects.all().order_by('-userName')
paginator = Paginator(tableList, 12)
try:
page = int(request.GET.get('page', '1'))
except ValueError:
page = 1
try:
contacts = paginator.page(page)
except (EmptyPage, InvalidPage):
contacts = paginator.page(0)
return render_to_response('sortDescend.html', {'emp_list': contacts})
sortAscending.html
{%for emp in emp_list.object_list%}
<tr> <td><a STYLE="text-decoration:none" href ="http://10.1.0.90:8080/singleEmployee/{{emp.id}} "> {{ emp.userName }} </a></td> </tr><td>
{%endfor%}
Another alternative to handling sorting in the view level is to do it on the templates. For this reason, you might want to checkout jquery tablesorter (since you are using a table in the display as well). It handles sorting in ascending/descending order.
So if you have the results after filtering that is ready to be displayed to a page, say filtered_results.html, you can do it like this.
<!-- filtered_results.html -->
<head>
...
<script type="text/javascript" src="/path/to/jquery-latest.js"></script>
<script type="text/javascript" src="/path/to/jquery.tablesorter.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$("#myTable").tablesorter();
});
</script>
</head>
<body>
<table id="myTable">
<thead><tr><th>Some-Label</th></tr></thead>
<tbody>
{% for emp in emp_list.object_list %}
<tr><td>{{emp.userName}}</td></tr>
{% endfor %}
</tbody>
</table>
</body>
Clicking on the cell of 'Some-Label' will toggle the sorting in ascending/descending order.
Furthermore, it has a plugin for handling pagination. Check out this link for the demo.
I'm not sure I get the question, but if you want to apply the sorting to the filtered objects, you might want to add some sort of caching (different from django's builtin caching), that stores the filtered queryset and sort that. Or you can pass the filter option around using django's session management and redo the sorting query. This would require to refactor filter so the if/elif chain is independant of that view and returns the filtered queryset.
ex:
def filterHandler(request):
val3=''
if request.GET.has_key('choices'):
val2=request.GET.get('choices')
if request.GET.has_key('textField'):
val3=request.GET.get('textField')
if request.POST:
val2=request.POST.get('choices')
val3=request.POST.get('textField')
newData , flag = filter(val2, val3)
if newData is None:
return HttpResponseRedirect('/employeeList/')
#tableList = EmployeeDetails.objects.all()
paginator = Paginator(newData, 10)
try:
page = int(request.GET.get('page', '1'))
except ValueError:
page = 1
try:
contacts = paginator.page(page)
except (EmptyPage, InvalidPage):
contacts = paginator.page(0)
request.session['val2'] = val2
request.session['val3'] = val3
return render_to_response('filter.html',{'newData':newData,'emp_list': contacts,'val2':val2,'val3':val3,'flag':flag})
def filter(val2, val3):
newData = None
flag = False
if val2=='Designation':
newData = EmployeeDetails.objects.filter(designation=val3)
flag=True
elif val2=='Name':
newData = EmployeeDetails.objects.filter(userName__icontains=val3)
flag=True
elif val2=='EmployeeID':
newData = EmployeeDetails.objects.filter(employeeID=val3)
flag=True
elif val2=='Project':
newData = EmployeeDetails.objects.filter(project=val3)
flag=True
elif val2=='DateOfJoin':
newData = EmployeeDetails.objects.filter(dateOfJoin=val3)
flag=True
return newData, flag
Now your sorting methods can get the filter values that was passed originally. Optionally you can add them as get parameters to the views url also.

Categories

Resources