Django, python, redis sorting - python

I used redis to sort out the most viewed items in a project I am working on. I would like to sort out only the most viewed for the day and out the overall most viewed. In other words, viewing count should restart everyday. Here is my code
#login_required
def image_ranking(request):
image_ranking = r.zrange('image_ranking', 0, -1, desc=True[:110000]
image_ranking_ids = [int(id) for id in image_ranking]
most_viewed = list(Image.objects.filter(id__in=image_ranking_ids))
most_viewed.sort(key=lambda x: image_ranking_ids.index(x.id))
paginator = Paginator(most_viewed, 24)
page = request.GET.get('page')
try:
most_viewed = paginator.page(page)
except PageNotAnInteger:
most_viewed = paginator.page(1)
except EmptyPage:
if request.is_ajax():
return HttpResponse('')
most_viewed = paginator.page(paginator.num_pages)
if request.is_ajax():
return render(request, 'images/image/ranking_ajax', {'section': 'images', 'most_viewed': most_viewed})
return render(request, 'images/image/ranking.html', {'section': 'images', 'most_viewed': most_viewed})

Related

Is there a way to combine view functions of similar structures into one? Django

I'm a beginner at Django. Recently, I started writing a web app for inventory management and I realised that when i was writing the views, there were a lot of them with similar structures. For instance:
def invoices(request):
"""The page for displaying invoices."""
invoice_list = Document.objects.filter(type_name__name='Invoice')
page = request.GET.get('page', 1)
paginator = Paginator(invoice_list, 10)
try:
invoices = paginator.page(page)
except PageNotAnInteger:
invoices = paginator.page(1)
except EmptyPage:
invoices = paginator.page(paginator.num_pages)
context = {'invoices':invoices}
return render(request, 'imsapp/invoices.html', context)
and this one:
def credit_notes(request):
"""The page for displaying credit notes."""
credit_notes_list = Document.objects.filter(type_name__name='Credit Note')
page = request.GET.get('page', 1)
paginator = Paginator(credit_notes_list, 10)
try:
credit_notes = paginator.page(page)
except PageNotAnInteger:
credit_notes = paginator.page(1)
except EmptyPage:
credit_notes = paginator.page(paginator.num_pages)
context = {'credit_notes':credit_notes}
return render(request, 'imsapp/credit_notes.html', context)
So, I'm just thinking if there is a more elegant way to represent the above function definitions. Is Class-based view what I'm looking for?
You could refactor the logic such that a function handles the common logic or you can use a class based view.
def paginate(request, queryset):
page_index = request.GET.get('page', 1)
paginator = Paginator(queryset, 10)
try:
page = paginator.page(page_index)
except PageNotAnInteger:
page = paginator.page(1)
except EmptyPage:
page = paginator.page(paginator.num_pages)
return page
def credit_notes(request):
"""The page for displaying credit notes."""
credit_notes_list = Document.objects.filter(type_name__name='Credit Note')
credit_notes = paginate(request, credit_notes_list)
context = {'credit_notes':credit_notes}
return render(request, 'imsapp/credit_notes.html', context)
Or you can use ListView
from django.views.generic.list import ListView
class CreditNoteListView(ListView):
queryset = Document.objects.filter(type_name__name='Credit Note')
paginate_by = 10
template_name = 'imsapp/credit_notes.html'
You'll need to change your template in that case though since the template context will be slightly different.
Views are just Python functions - and as such, tehy can call further functions.
In the above code, it looks like the only things that change are the type object name and the template.
Simply create a new function that takes these two as parameters
def paged_view(request, type_name, template, name_in_context):
"""The page for displaying various items in a paginated way."""
item_list = Document.objects.filter(type_name__name=time_name)
page = request.GET.get('page', 1)
paginator = Paginator(item_list, 10)
try:
items = paginator.page(page)
except PageNotAnInteger:
items = paginator.page(1)
except EmptyPage:
items = paginator.page(paginator.num_pages)
context = {name_in_context:items}
return render(request, template, context)
def invoices(request):
"""The page for displaying invoices."""
return paged_view(requests, 'imsapp/invoices.html', 'Invoice', 'invoices')
def credit_notes(request):
"""The page for displaying credit notes."""
return paged_view(requests, 'imsapp/credit_notes.html', 'Credit Note', 'credit_notes')

How lo load Stripe objects in Django pagination

I want to paginate invoices from Stripe
#login_required
def invoice_list(request):
customer = stripe.Customer.list(email=request.user.username)
for invoice_search in customer['data']:
customer_invoice_list = stripe.Invoice.list(customer=invoice_search['id'])
page = request.GET.get("page", 1)
paginator = Paginator(customer_invoice_list, 20)
try:
invoices = paginator.page(page)
except PageNotAnInteger:
invoices = paginator.page(1)
except EmptyPage:
invoices = paginator.page(paginator.num_pages)
context = {
'invoices': invoices,
}
return render(request, 'invoice_list.html', context)
That is my code, I got error: Unhashable type
In Django 1.11 documentation say can load list or queryset, I obtain Invoices List, why can't paginate??
Try Convert this to a tuple before creating the pagination object.
please note i have not tested this myself - possible you're having the same issue as this person was - Pagination doesn't accept dict as data - unhashable type
#login_required
def invoice_list(request):
customer = stripe.Customer.list(email=request.user.username)
for invoice_search in customer['data']:
customer_invoice_list = stripe.Invoice.list(customer=invoice_search['id'])
page = request.GET.get("page", 1)
customer_invoice_list = tuple(customer_invoice_list)
page = tuple(page)
paginator = Paginator(customer_invoice_list, 20)
try:
invoices = paginator.page(page)
except PageNotAnInteger:
invoices = paginator.page(1)
except EmptyPage:
invoices = paginator.page(paginator.num_pages)
context = {
'invoices': invoices,
}
return render(request, 'invoice_list.html', context)
The soution is based on #Taylor code:
#login_required
def invoice_list(request):
customer = stripe.Customer.list(email=request.user.username)
for invoice_search in customer['data']:
customer_invoice_list = stripe.Invoice.list(customer=invoice_search['id'])
page = request.GET.get("page", 1)
customer_invoice_list = tuple(customer_invoice_list)
paginator = Paginator(customer_invoice_list, 20)
try:
invoices = paginator.page(page)
except PageNotAnInteger:
invoices = paginator.page(1)
except EmptyPage:
invoices = paginator.page(paginator.num_pages)
context = {
'invoices': invoices,
}
return render(request, 'invoice_list.html', context)

How to implement pagination in Search results in django?

I found a resource where it has code like this:
from django.contrib.auth.models import User
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
def index(request):
user_list = User.objects.all()
page = request.GET.get('page', 1)
paginator = Paginator(user_list, 10)
try:
users = paginator.page(page)
except PageNotAnInteger:
users = paginator.page(1)
except EmptyPage:
users = paginator.page(paginator.num_pages)
return render(request, 'core/user_list.html', { 'users': users })
I have a code like this:
def product_list(request, category_slug=None):
category = None
categories = Category.objects.all().order_by("-rating")
#paginator = Paginator(categories, 10)
products = Product.objects.all().order_by("-number")
users = User.objects.exclude(id=request.user.id)
query = request.GET.get('q')
if query=='':
return HttpResponseRedirect('/')
if query:
categories = Category.objects.filter(Q(slug__icontains=query)| Q(url__icontains=query)).order_by("-rating")
products = Product.objects.filter(Q(slug__icontains=query) | Q(name__icontains=query) | Q(description__icontains=query)).order_by("number")
if category_slug:
category = get_object_or_404(Category, slug=category_slug)
products = Product.objects.filter(category=category)
categories_counter = products.annotate(Count('id'))
categories_count = len(categories_counter)
#contacts = paginator.get_page(query)
context = {
'category': category,
'categories': categories,
'products': products,
'categories_count':categories_count,
'query':query,
'users':users,
#'contacts':contacts,
}
return render(request, 'shop/product/list.html', context)
I have retrieved objects from two models, Category, and Product. How do I implement the pagination code in this view? It's not a normal pagination but pagination in search results.
user_list = User.objects.all() # this is the full queryset, contains all objects
page = request.GET.get('page', 1) # this is the page number of page whose data you want to retrieve, you need to pass page value as query params
paginator = Paginator(user_list, 10) # this will paginate the full queryset in pages of 10 objects
try:
users = paginator.page(page) # this will return data of that particular page
except PageNotAnInteger:
users = paginator.page(1) # if the passed page is not Integer then first page is returned, you can customize this
except EmptyPage:
users = paginator.page(paginator.num_pages) # if that page contains no element, then last page is returned, you can customize this also
You can apply same logic to retrieve categories in category_page and other data.

Django : view calls an other template (Pagination )

I have this view:
class DamageListCriteria(TemplateView):
template_name = "damage/damagelist_criteria.html"
def get(self, request):
form = DamageListCriteriaForm()
general = General.objects.get(pk=1)
args = {
'form': form,
'general': general
}
return render(request, self.template_name, args)
def post(self, request):
general = General.objects.get(pk=1)
form = DamageListCriteriaForm(request.POST)
form.non_field_errors()
if form.is_valid():
fromdate = request.POST.get('fromdate')
fdate = datetime.strptime(fromdate, '%d/%m/%Y')
fdate = datetime.combine(fdate, datetime.min.time(), tzinfo=pytz.UTC)
print('fdate ', fdate)
todate = form.cleaned_data['todate']
#tdate = datetime.strptime(todate, '%d/%m/%Y') + timedelta(days=1)
tdate = datetime.strptime(todate, '%d/%m/%Y')
tdate = datetime.combine(tdate, datetime.max.time(), tzinfo=pytz.UTC)
print('tdate ', tdate)
d_list = Damage.objects.filter(entry_date__range=(fdate, tdate))
paginator = Paginator(d_list, 1)
page = request.GET.get('page')
try:
damage_list = paginator.page(page)
except PageNotAnInteger:
# If page is not an integer, deliver first page.
damage_list = paginator.page(1)
except EmptyPage:
# If page is out of range (e.g. 9999), deliver last page of results.
damage_list = paginator.page(paginator.num_pages)
template = "damage/damagelist_table.html"
form = DamageListForm()
general = General.objects.get(pk=1)
fromdatetext = fdate.strftime('%d/%m/%Y')
todatetext = tdate.strftime('%d/%m/%Y')
args = {
'form': form,
'damage_list': damage_list,
'general': general,
'fromdate': fromdatetext,
'todate': todatetext
}
return render(request, template, args)
else:
print('form is not valid')
print(form.errors)
# form = DamageEntryForm()
args = {'form': form,
'general': general
}
return render(request, self.template_name, args)
I want to get some criteria to make a filtering listing of my database.
It worked this way , until the moment i tried to add pagination.
The url is http://127.0.0.1:8000/damage/damage/list/criteria/
url(r'damage/list/criteria/$', views.DamageListCriteria.as_view(), name="damage-list-criteria"),
Next and Previous don't work because I am still at this url after the
return render(request, template, args)
Can i redirect somehow?
I understand that this might be the wrong way to do the listing. Can you help me , how to do it?
Thanks a lot
Kostas
The easiest thing to do would be not use Django itself but use Django REST framework and reuse its serializer classes along with APIView (or one of its subclasses). Are you in a position to use it or are you constrained?

how to set urls in django to prevent similar job?

I practice how to use django to write a website
I finished one with model name = Traveltime
But I still have many to do (like: aaaaa,bbbbb,ccccc below)
They are do similar job ,just the model name is different
I feel it duplicate and don't know how to do.
how can I edit my urls.py?? Please help me thank you!
urls.py:
urlpatterns = patterns('',
url(r'^travel/$', views.object_list, {'model': models.Traveltime}),
url(r'^travel/result/$', views.object_result, {'model': models.Traveltime}),
url(r'^travel/update/$', views.update),
#I have many urls to set (below)
url(r'^aaaaa/$', views.object_list, {'model': models.aaaaa}),
url(r'^aaaaa/result/$', views.object_result, {'model': models.aaaaa}),
url(r'^aaaaa/update/$', views.update),
url(r'^bbbbb/$', views.object_list, {'model': models.bbbbb}),
url(r'^bbbbb/result/$', views.object_result, {'model': models.bbbbb}),
url(r'^bbbbb/update/$', views.update),
url(r'^ccccc/$', views.object_list, {'model': models.ccccc}),
url(r'^ccccc/result/$', views.object_result, {'model': models.ccccc}),
url(r'^ccccc/update/$', views.ccccc),
views.py
def object_list(request, model):
obj_list = model.objects.filter(image_elect='')
paginator = Paginator(obj_list, 10)
page = request.GET.get('page')
try:
contacts = paginator.page(page)
except PageNotAnInteger:
contacts = paginator.page(1)
except EmptyPage:
contacts = paginator.page(paginator.num_pages)
template_name = 'filterimgs/%s_list.html' % model.__name__.lower()
return render_to_response(template_name, {'object_list': obj_list,"contacts": contacts},
context_instance=RequestContext(request))
def update(request):
travel = Traveltime.objects.filter(title=request.POST['title'])
# travel.update(image_elect='asd')
return redirect(object_result)
def object_result(request, model):
obj_list = model.objects.all()
paginator = Paginator(obj_list, 10)
page = request.GET.get('page')
try:
contacts = paginator.page(page)
except PageNotAnInteger:
contacts = paginator.page(1)
except EmptyPage:
contacts = paginator.page(paginator.num_pages)
template_name = 'filterimgs/%s_result.html' % model.__name__.lower()
return render_to_response(template_name, {'object_list': obj_list,"contacts": contacts},
context_instance=RequestContext(request))
Django url patterns are regular expressions, any grouped expression will be passed into the appropriate view as an additional parameter.
urlpatterns = patterns('',
url(r'^([a-zA-Z]+)/$', views.object_list),
url(r'^([a-zA-Z]+)/result/$', views.object_result),
url(r'^([a-zA-Z]+)/update/$', views.update),
)
Then in your request you can
import importlib
def object_list(request, model_type):
# use the model_type which is passed in from
# the URL to actually grab the proper model
found = importlib.import_module('models.{0}'.format(model_type))
Python is gracious enough to allow you to import modules using a string .
Also, found is a lame name, so you should name it accordingly depending on what it's purpose is.

Categories

Resources