I'm trying to paginate with different things to maximize elements, on the first page (5) and on all the others (maximum 6).
I do like in this answer
class MyPaginator(Paginator):
def __init__(self, **kw):
self.deltafirst = kw.pop('deltafirst', 0)
Paginator.__init__(self, **kw)
def page(self, number):
number = self.validate_number(number)
if number == 1:
bottom = 0
top = self.per_page - self.deltafirst
else:
bottom = (number - 1) * self.per_page - self.deltafirst
top = bottom + self.per_page
if top + self.orphans >= self.count:
top = self.count
return Page(self.object_list[bottom:top], number, self)
from django.core.paginator import Paginator
from django.core.paginator import EmptyPage
from django.core.paginator import PageNotAnInteger
class NewsView(ListView):
model = News
template_name="mysite/news.html"
paginate_by = 5
def get_context_data(self, **kwargs):
context = super(NewsView, self).get_context_data(**kwargs)
all_news = News.objects.all().order_by("-date_news")
paginator = MyPaginator(all_news, self.paginate_by,deltafirst=1)
page = self.request.GET.get('page')
try:
file_exams = paginator.page(page)
except PageNotAnInteger:
file_exams = paginator.page(1)
except EmptyPage:
file_exams = paginator.page(paginator.num_pages)
context['all_news'] = file_exams
return context
But I get an error and I can't figure out what I'm doing wrong. The error itself
paginator = MyPaginator(all_news, self.paginate_by,deltafirst=1)
TypeError: __init__() takes 1 positional argument but 3 were given
Firstly change your __init__ method in MyPaginator to fix the error:
from math import ceil
class MyPaginator(Paginator):
def __init__(self, *args, **kw):
self.deltafirst = kw.pop('deltafirst', 0)
super().__init__(*args, **kw)
def page(self, number):
number = self.validate_number(number)
if number == 1:
bottom = 0
top = self.per_page - self.deltafirst
else:
bottom = (number - 1) * self.per_page - self.deltafirst
top = bottom + self.per_page
if top + self.orphans >= self.count:
top = self.count
return Page(self.object_list[bottom:top], number, self)
#property
def num_pages(self):
if self.count == 0 and not self.allow_empty_first_page:
return 0
count = max(self.count - self.per_page + self.deltafirst, 0)
hits = max(0, count - self.orphans)
return 1 + ceil(hits / self.per_page)
Next to make your view simpler instead of overriding get_context_data override get_paginator and also set deltafirst as a class attribute:
class NewsView(ListView):
model = News
template_name="mysite/news.html"
paginate_by = 5
paginator_class = MyPaginator
deltafirst = 1
def get_paginator(self, *args, **kwargs):
if self.deltafirst:
kwargs['deltafirst'] = self.deltafirst
return super().get_paginator(*args, **kwargs)
Related
I am trying to render a generic detail view page with a form with errors
My post method in my generic detail view is
def post(self, request, slug):
if 'submit-edit-roster' in request.POST:
edit_roster_form = EditRosterForm(request.POST, team=self.request.user.playerprofile.team)
if edit_roster_form.is_valid():
edit_roster_form.save()
return redirect ('tcl-team', slug=self.request.user.playerprofile.team.urlslug)
my edit roster form is
class EditRosterForm(forms.Form):
members = 0
team = None
sublist = []
playerlist = []
def __init__(self, *args, **kwargs):
self.team = kwargs.pop('team', None)
self.members = 0
self.sublist = []
self.playerlist = []
super(EditRosterForm, self).__init__(*args, **kwargs)
currentroster = Roster.objects.filter(team=self.team)[0]
for member in Playerprofile.objects.filter(team=self.team).order_by('name'):
if member in currentroster.players.all():
self.fields[str(member.name)] = forms.ChoiceField(choices=ROSTER_CHOICES)
self.initial[str(member.name)] = '1'
elif member in currentroster.subs.all():
self.fields[str(member.name)] = forms.ChoiceField(choices=ROSTER_CHOICES)
self.initial[str(member.name)] = '2'
self.members += 1
def clean(self):
cleaned_data = super().clean()
i = 0
for member in Playerprofile.objects.filter(team=self.team):
if cleaned_data[member.name] == '1':
self.playerlist.append(member)
elif cleaned_data[member.name] == '2':
self.sublist.append(member)
i += 1
print(len(self.sublist))
if len(self.sublist) > 2:
raise ValidationError("Maximum of 2 subs allowed")
if len(self.playerlist) > 5:
raise ValidationError("Maximum of 5 players allowed")
if len(self.playerlist) + len(self.sublist) > i:
raise ValidationError("Team members must be a sub or a player")
return cleaned_data
def save(self):
cleaned_data = self.cleaned_data
print(cleaned_data)
UpdateRoster(roster=self.team.GetCurrentRoster(), players=self.playerlist, subs=self.sublist)
When my form has errors I get
The view team.views.TeamEditView didn't return an HttpResponse object. It returned None instead.
I know I need to add something to pass my form the form object with errors but can't find how to do this.
if edit_roster_form.is_valid():
edit_roster_form.save()
return redirect ('tcl-team', slug=self.request.user.playerprofile.team.urlslug)
else:
# Render detail view page with form
Apologies if my question is incoherent, I'm new to django and stackoverflow
I think you have to add request as parameter to the render shortcut
I have this ListView that paginates the context, but i want to add also car types in my context, for that i need to built it in json which i don't know how, or is any other way around this, any help would be very much appreciated.
class CarListView(ListView):
model = Car
template_name = 'listings.html'
context_object_name = 'cars'
ordering = ['-created']
paginate_by = 5
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
print(context)
paginator = context['paginator']
page_numbers_range = 10 # Display 5 page numbers
max_index = len(paginator.page_range)
page = self.request.GET.get('page')
print(self.request)
current_page = int(page) if page else 1
start_index = int((current_page - 1) / page_numbers_range) * page_numbers_range
end_index = start_index + page_numbers_range
if end_index >= max_index:
end_index = max_index
page_range = paginator.page_range[start_index:end_index]
# context['page_range'] = page_range
# return context
cars = Car.objects.all()[:10]
car_types = CarType.objects.all()
context = {'cars': cars, 'car_types': car_types}
return context
You are overriding your entire context on the last statement....
Change
context = {'cars': cars, 'car_types': car_types}
for
context['cars']=cars
context['car_types']=car_types
I'm upgrading things as the title says, and now doing a rebuild_index seems to do nothing.
The output is a simple:
$ ./manage.py rebuild_index --noinput
Removing all documents from your index because you said so.
All documents removed.
Indexing 17019 users
Indexing 76 gears
Indexing 186523 images
and all of my prepare_FOO functions are not run.
These are my settings:
HAYSTACK_DEFAULT_OPERATOR = 'AND'
HAYSTACK_SEARCH_RESULTS_PER_PAGE = 70
HAYSTACK_CONNECTIONS = {
'default': {
'engine': 'haystack.backends.solr_backend.SolrEngine',
'URL': 'http://127.0.0.1:8983/solr',
'EXCLUDED_INDEXES': [
'threaded_messages.search_indexes.Thread',
'threaded_messages.search_indexes.ThreadIndex',
],
},
}
And these are my indexes:
# Python
import string
import re
import datetime
# Django
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from django.db.models import Q
# Third party apps
from haystack.indexes import *
from hitcount.models import HitCount
from toggleproperties.models import ToggleProperty
# This app
from astrobin.models import Image
from astrobin.models import DeepSky_Acquisition
from astrobin.models import SolarSystem_Acquisition
from astrobin.models import UserProfile
from astrobin.models import Gear, CommercialGear, RetailedGear
from astrobin.utils import unique_items
# Other AstroBin apps
from nested_comments.models import NestedComment
def _get_integration(image):
deep_sky_acquisitions = DeepSky_Acquisition.objects.filter(image=image)
solar_system_acquisition = None
integration = 0
try:
solar_system_acquisition = SolarSystem_Acquisition.objects.get(image=image)
except:
pass
if deep_sky_acquisitions:
for a in deep_sky_acquisitions:
if a.duration and a.number:
integration += (a.duration * a.number)
elif solar_system_acquisition:
return 0
return integration
def _prepare_likes(obj):
return ToggleProperty.objects.toggleproperties_for_object("like", obj).count()
def _prepare_moon_phase(obj):
from moon import MoonPhase
deep_sky_acquisitions = DeepSky_Acquisition.objects.filter(image=obj)
moon_illuminated_list = []
if deep_sky_acquisitions:
for a in deep_sky_acquisitions:
if a.date is not None:
m = MoonPhase(a.date)
moon_illuminated_list.append(m.illuminated * 100.0)
if len(moon_illuminated_list) == 0:
# We must make an assumption between 0 and 100, or this won't
# show up in any searches.
return 0
return sum(moon_illuminated_list) / float(len(moon_illuminated_list))
def _prepare_first_acquisition_date(obj):
deep_sky_acquisitions = DeepSky_Acquisition.objects.filter(image=obj)
solar_system_acquisition = None
try:
solar_system_acquisition = SolarSystem_Acquisition.objects.get(image=obj)
except:
pass
date = None
if deep_sky_acquisitions:
date = deep_sky_acquisitions[0].date
for a in deep_sky_acquisitions:
if a.date is not None and date is not None:
if a.date < date:
date = a.date
elif solar_system_acquisition:
date = solar_system_acquisition.date
return date
def _prepare_last_acquisition_date(obj):
deep_sky_acquisitions = DeepSky_Acquisition.objects.filter(image=obj)
solar_system_acquisition = None
try:
solar_system_acquisition = SolarSystem_Acquisition.objects.get(image=obj)
except:
pass
date = None
if deep_sky_acquisitions:
date = deep_sky_acquisitions[0].date
for a in deep_sky_acquisitions:
if a.date is not None and date is not None:
if a.date > date:
date = a.date
elif solar_system_acquisition:
date = solar_system_acquisition.date
return date if date else datetime.datetime.min
def _prepare_views(obj, content_type):
views = 0
try:
views = HitCount.objects.get(object_pk = obj.pk, content_type__name = content_type).hits
except:
pass
return views
def _prepare_min_aperture(obj):
d = 0
for telescope in obj.imaging_telescopes.all():
if telescope.aperture is not None and (d == 0 or telescope.aperture < d):
d = int(telescope.aperture)
return d
def _prepare_max_aperture(obj):
import sys
d = sys.maxint
for telescope in obj.imaging_telescopes.all():
if telescope.aperture is not None and (d == sys.maxint or telescope.aperture > d):
d = int(telescope.aperture)
return d
def _prepare_min_pixel_size(obj):
s = 0
for camera in obj.imaging_cameras.all():
if camera.pixel_size is not None and (s == 0 or camera.pixel_size < s):
s = int(camera.pixel_size)
return s
def _prepare_max_pixel_size(obj):
import sys
s = sys.maxint
for camera in obj.imaging_cameras.all():
if camera.pixel_size is not None and (s == sys.maxint or camera.pixel_size > s):
s = int(camera.pixel_size)
return s
def _prepare_telescope_types(obj):
return [x.type for x in obj.imaging_telescopes.all()]
def _prepare_camera_types(obj):
return [x.type for x in obj.imaging_cameras.all()]
def _prepare_comments(obj):
ct = ContentType.objects.get(app_label = 'astrobin', model = 'image')
return NestedComment.objects.filter(
content_type = ct,
object_id = obj.id,
deleted = False).count()
class GearIndex(SearchIndex, Indexable):
model_weight = IntegerField()
text = CharField(document=True, use_template=True)
images = IntegerField()
# Total likes of all images taken with this item.
likes = IntegerField()
# Total integration of images taken with this item.
integration = FloatField()
# Total views on images taken with this item.
views = IntegerField()
# Number of bookmarks on images taken with this item.
bookmarks = IntegerField()
# Number of comments on images taken with this item.
comments = IntegerField()
producers = MultiValueField()
retailers = MultiValueField()
def index_queryset(self, using = None):
return self.get_model().objects\
.exclude(commercial = None)\
.filter(commercial__producer__groups__name = 'Paying')
def get_model(self):
return Gear
def get_images(self, obj):
filters = (\
Q(imaging_telescopes = obj) |\
Q(guiding_telescopes = obj) |\
Q(mounts = obj) |\
Q(imaging_cameras = obj) |\
Q(guiding_cameras = obj) |\
Q(focal_reducers = obj) |\
Q(software = obj) |\
Q(filters = obj) |\
Q(accessories = obj)\
)
return Image.objects.filter(filters).distinct()
def prepare_model_weight(self, obj):
# Printing here just because it's the first "prepare" function.
print "%s: %d" % (obj.__class__.__name__, obj.pk)
return 100;
def prepare_images(self, obj):
return len(self.get_images(obj))
def prepare_likes(self, obj):
likes = 0
for i in self.get_images(obj):
likes += ToggleProperty.objects.toggleproperties_for_object("like", i).count()
return likes
def prepare_integration(self, obj):
integration = 0
for i in self.get_images(obj):
integration += _get_integration(i)
return integration / 3600.0
def prepare_views(self, obj):
views = 0
for i in self.get_images(obj):
views += _prepare_views(i, 'image')
return views
def prepare_bookmarks(self, obj):
bookmarks = 0
for i in self.get_images(obj):
bookmarks += ToggleProperty.objects.toggleproperties_for_object("bookmark", i).count()
return bookmarks
def prepare_comments(self, obj):
comments = 0
for i in self.get_images(obj):
comments += _prepare_comments(i)
return comments
def prepare_producers(self, obj):
producers = CommercialGear.objects\
.filter(base_gear = obj)\
.exclude(Q(producer__userprofile__company_name = None) | Q(producer__userprofile__company_name = ""))
return ["%s" % x.producer.userprofile.company_name for x in producers]
def prepare_retailers(self, obj):
retailers = RetailedGear.objects\
.filter(gear = obj)\
.exclude(Q(retailer__userprofile__company_name = None) | Q(retailer__userprofile__company_name = ""))
return ["%s" % x.retailer.userprofile.company_name for x in retailers]
class UserIndex(SearchIndex, Indexable):
model_weight = IntegerField()
text = CharField(document=True, use_template=True)
images = IntegerField()
avg_integration = FloatField()
# Total likes of all user's images.
likes = IntegerField()
# Total likes of all user's images.
average_likes = FloatField()
# Normalized likes (best images only)
normalized_likes = FloatField()
# Number of followers
followers = IntegerField()
# Total user ingegration.
integration = FloatField()
# Average moon phase under which this user has operated.
moon_phase = FloatField()
# First and last acquisition dates, including all images of course.
first_acquisition_date = DateTimeField()
last_acquisition_date = DateTimeField()
# Total views from all images.
views = IntegerField()
# Min and max aperture of all telescopes used in this user's images.
min_aperture = IntegerField()
max_aperture = IntegerField()
# Min and max pixel size of all cameras used in this user's images.
min_pixel_size = IntegerField()
max_pixel_size = IntegerField()
# Number of bookmarks on own images
bookmarks = IntegerField()
# Types of telescopes and cameras with which this user has imaged.
telescope_types = MultiValueField()
camera_types = MultiValueField()
comments = IntegerField()
comments_written = IntegerField()
username = CharField(model_attr = 'username')
def index_queryset(self, using = None):
return self.get_model().objects.all()
def get_model(self):
return User
def prepare_model_weight(self, obj):
# Printing here just because it's the first "prepare" function.
print "%s: %d" % (obj.__class__.__name__, obj.pk)
return 200;
def prepare_images(self, obj):
return Image.objects.filter(user = obj).count()
def prepare_avg_integration(self, obj):
integration = 0
images = 0
for i in Image.objects.filter(user = obj):
image_integration = _get_integration(i)
if image_integration:
images += 1
integration += image_integration
return (integration / 3600.0) / images if images else 0
def prepare_likes(self, obj):
likes = 0
for i in Image.objects.filter(user = obj):
likes += ToggleProperty.objects.toggleproperties_for_object("like", i).count()
return likes
def prepare_average_likes(self, obj):
likes = self.prepare_likes(obj)
images = self.prepare_images(obj)
return likes / float(images) if images > 0 else 0
def prepare_normalized_likes(self, obj):
def average(values):
if len(values):
return sum(values) / float(len(values))
return 0
def index(values):
import math
return average(values) * math.log(len(values)+1, 10)
avg = self.prepare_average_likes(obj)
norm = []
for i in Image.objects.filter(user = obj):
likes = i.likes()
if likes >= avg:
norm.append(likes)
if len(norm) == 0:
return 0
return index(norm)
def prepare_followers(self, obj):
return ToggleProperty.objects.filter(
property_type = "follow",
content_type = ContentType.objects.get_for_model(User),
object_id = obj.pk
).count()
def prepare_integration(self, obj):
integration = 0
for i in Image.objects.filter(user = obj):
integration += _get_integration(i)
return integration / 3600.0
def prepare_moon_phase(self, obj):
l = []
for i in Image.objects.filter(user = obj):
l.append(_prepare_moon_phase(i))
if len(l) == 0:
return 0
return reduce(lambda x, y: x + y, l) / len(l)
def prepare_first_acquisition_date(self, obj):
l = []
for i in Image.objects.filter(user = obj):
l.append(_prepare_first_acquisition_date(obj))
if len(l) == 0:
return None
return min(l)
def prepare_last_acquisition_date(self, obj):
l = []
for i in Image.objects.filter(user = obj):
l.append(_prepare_last_acquisition_date(obj))
if len(l) == 0:
return None
return max(l)
def prepare_views(self, obj):
views = 0
for i in Image.objects.filter(user = obj):
views += _prepare_views(i, 'image')
return views
def prepare_min_aperture(self, obj):
l = []
for i in Image.objects.filter(user = obj):
l.append(_prepare_min_aperture(i))
if len(l) == 0:
return 0
return min(l)
def prepare_max_aperture(self, obj):
l = []
for i in Image.objects.filter(user = obj):
l.append(_prepare_max_aperture(i))
if len(l) == 0:
return 0
return max(l)
def prepare_min_pixel_size(self, obj):
l = []
for i in Image.objects.filter(user = obj):
l.append(_prepare_min_pixel_size(i))
if len(l) == 0:
return 0
return min(l)
def prepare_max_pixel_size(self, obj):
l = []
for i in Image.objects.filter(user = obj):
l.append(_prepare_max_pixel_size(i))
if len(l) == 0:
return 0
return max(l)
def prepare_bookmarks(self, obj):
bookmarks = 0
for i in Image.objects.filter(user = obj):
bookmarks += ToggleProperty.objects.toggleproperties_for_object("bookmark", i).count()
return bookmarks
def prepare_telescope_types(self, obj):
l = []
for i in Image.objects.filter(user = obj):
l += _prepare_telescope_types(i)
return unique_items(l)
def prepare_camera_types(self, obj):
l = []
for i in Image.objects.filter(user = obj):
l += _prepare_camera_types(i)
return unique_items(l)
def prepare_comments(self, obj):
comments = 0
for i in Image.objects.filter(user = obj):
comments += _prepare_comments(i)
return comments
def prepare_comments_written(self, obj):
return NestedComment.objects.filter(author = obj, deleted = False).count()
class ImageIndex(SearchIndex, Indexable):
model_weight = IntegerField()
text = CharField(document=True, use_template=True)
uploaded = DateTimeField(model_attr='uploaded')
likes = IntegerField()
integration = FloatField()
moon_phase = FloatField()
first_acquisition_date = DateTimeField()
last_acquisition_date = DateTimeField()
views = IntegerField()
solar_system_main_subject = IntegerField()
is_deep_sky = BooleanField()
is_clusters = BooleanField()
is_nebulae = BooleanField()
is_galaxies = BooleanField()
is_solar_system = BooleanField()
is_sun = BooleanField()
is_moon = BooleanField()
is_planets = BooleanField()
is_comets = BooleanField()
license = IntegerField(model_attr = 'license')
min_aperture = IntegerField()
max_aperture = IntegerField()
min_pixel_size = IntegerField()
max_pixel_size = IntegerField()
bookmarks = IntegerField()
telescope_types = MultiValueField()
camera_types = MultiValueField()
comments = IntegerField()
is_commercial = BooleanField()
subject_type = IntegerField(model_attr = 'subject_type')
username = CharField(model_attr = 'user__username')
def index_queryset(self, using = None):
return self.get_model().objects.filter(moderator_decision = 1)
def get_model(self):
return Image
def prepare_model_weight(self, obj):
# Printing here just because it's the first "prepare" function.
print "%s: %d" % (obj.__class__.__name__, obj.pk)
return 300;
def prepare_likes(self, obj):
return _prepare_likes(obj)
def prepare_integration(self, obj):
return _get_integration(obj)
def prepare_moon_phase(self, obj):
return _prepare_moon_phase(obj)
def prepare_first_acquisition_date(self, obj):
return _prepare_first_acquisition_date(obj)
def prepare_last_acquisition_date(self, obj):
return _prepare_last_acquisition_date(obj)
def prepare_views(self, obj):
return _prepare_views(obj, 'image')
def prepare_solar_system_main_subject(self, obj):
return obj.solar_system_main_subject
def prepare_is_deep_sky(self, obj):
return DeepSky_Acquisition.objects.filter(image = obj).count() > 0
def prepare_is_solar_system(self, obj):
if obj.solar_system_main_subject:
return True
if SolarSystem_Acquisition.objects.filter(image = obj):
return True
return False
def prepare_is_sun(self, obj):
return obj.solar_system_main_subject == 0
def prepare_is_moon(self, obj):
return obj.solar_system_main_subject == 1
def prepare_is_planets(self, obj):
return obj.solar_system_main_subject in range(2, 8)
def prepare_is_comets(self, obj):
return obj.solar_system_main_subject == 10
def prepare_min_aperture(self, obj):
return _prepare_min_aperture(obj)
def prepare_max_aperture(self, obj):
return _prepare_max_aperture(obj)
def prepare_min_pixel_size(self, obj):
return _prepare_min_pixel_size(obj)
s = 0
for camera in obj.imaging_cameras.all():
if camera.pixel_size is not None and (s == 0 or camera.pixel_size < s):
s = int(camera.pixel_size)
return s
def prepare_max_pixel_size(self, obj):
return _prepare_max_pixel_size(obj)
import sys
s = sys.maxint
for camera in obj.imaging_cameras.all():
if camera.pixel_size is not None and (s == sys.maxint or camera.pixel_size > s):
s = int(camera.pixel_size)
return s
def prepare_bookmarks(self, obj):
return ToggleProperty.objects.toggleproperties_for_object("bookmark", obj).count()
def prepare_telescope_types(self, obj):
return _prepare_telescope_types(obj)
def prepare_camera_types(self, obj):
return _prepare_camera_types(obj)
def prepare_comments(self, obj):
return _prepare_comments(obj)
def prepare_is_commercial(self, obj):
commercial_gear = CommercialGear.objects.filter(image = obj)
return commercial_gear.count() > 0
Any idea what I might be missing? Thanks!
Got it. 'ENGINE' should be all capitals, in the settings.
I am attempting to make my API get return a maximum of 10 per page. This helps me with infinite loading. The API url will be I am trying looks like this:
www.mysite.com/api/test/?user=5&page=1
However, this does not work.
I've followed the official docs here without success.
I have only modified two files, settings.py & rest_views.py.
settings.py-
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination'
}
rest_views.py-
from django.core.paginator import Paginator
...
wardrobematch = {
'user': lambda x: ('user__pk', x)
}
class WardrobeListView(APIView):
renderer_classes = (JSONRenderer, )
paginate_by = 10
paginate_by_param = 'page_size'
max_paginate_by = 100
def get(self, request, *args, **kwargs):
filters = {}
for key, value in request.GET.items():
key = key.lower()
if key in wardrobematch:
lookup, val = wardrobematch[key](value.lower())
filters[lookup] = val
qset = (
Analytic.objects
.filter(like=True,**filters)
.order_by('-updated',)
# .distinct('product_id',)
.values('product_id', 'product__name', 'product__brand', 'product__store__store_name', 'product__variation__image__image', 'product__variation__price__price',)
)
return Response(qset)
When using regular ApiView, you should call the pagination API yourself, it will not perform pagination automatically.
I have created a pagination and a serializer mixim. I'm not sure it is best method, but it worked for me.
class SerializerMixim(object):
def serialize_object(self,obj):
"""Serilize only needed fields"""
return NotImplementedError
class PaginationMixim(object):
_serializer = None
def paginate(self,queryset,num=10):
page = self.request.GET.get('page')
paginator = Paginator(queryset, num)
try:
queryset = paginator.page(page)
except PageNotAnInteger:
queryset = paginator.page(1)
except EmptyPage:
queryset = paginator.page(paginator.num_pages)
count = paginator.count
previous = None if not queryset.has_previous() else queryset.previous_page_number()
next = None if not queryset.has_next() else queryset.next_page_number()
if self._serializer:
objects = self._serializer(queryset.object_list,many=True).data
else:
objects = [self.serialize_object(i) for i in queryset.object_list]
data = {'count':count,'previous':previous,
'next':next,'object_list':objects}
return Response(data)
def serialize_object(self,obj):
return {'id':obj.pk}
class WardrobeListView(APIView,PaginationMixim,SerializerMixim):
renderer_classes = (JSONRenderer, )
#_serializer = AnalyticSerializer
def get(self, request, *args, **kwargs):
filters = {}
for key, value in request.GET.items():
key = key.lower()
if key in wardrobematch:
lookup, val = wardrobematch[key](value.lower())
filters[lookup] = val
qset = (
Analytic.objects
.filter(like=True,**filters)
.order_by('-updated',)
# .distinct('product_id',)
return self.paginate(qset)
def serialize_object(self,obj):
return obj.serilized
then you need to create a propery for Analytic model like,
class Analytic(models.Model):
.....
#property
def serilized(self):
summary = {
'id':self.product.id,
'image':self.product.name,
.......
}
return summary
this will also work with django rest serializers
I got your first example working- to me it was clearer and more basic. All I did was add ".object_list" to stop the "is not JSON serializable" error.
This is your answer with my tiny tweak:
class WardrobeListView(APIView):
renderer_classes = (JSONRenderer, )
def get(self, request, *args, **kwargs):
filters = {}
for key, value in request.GET.items():
key = key.lower()
if key in wardrobematch:
lookup, val = wardrobematch[key](value.lower())
filters[lookup] = val
qset = (
Analytic.objects
.filter(like=True,**filters)
.order_by('-updated',)
# .distinct('product_id',)
.values('product_id', 'product__name', 'product__brand', 'product__store__store_name', 'product__variation__image__image', 'product__variation__price__price',)
)
paginator = Paginator(qset, 2) # Show 25 items per page
page = request.GET.get('page')
try:
qset = paginator.page(page)
except PageNotAnInteger:
# If page is not an integer, deliver first page.
qset = paginator.page(1)
except EmptyPage:
# If page is out of range (e.g. 9999), deliver last page of results.
qset = paginator.page(paginator.num_pages)
return Response(qset.object_list)
I've upgraded haystack but I'm getting an issue with using django_ct I've indexed the model for movie with python manage.py update_index movies but when I try to get a filter by model using either of the two
result = SearchQuerySet().raw_search('django_ct:movies.movie')
result = SearchQuerySet().filter(django_ct='movies.movie')
I get no result
>>> from haystack.query import SearchQuerySet
>>> result = SearchQuerySet().filter(django_ct='movies.movie')
>>> len(result.all())
0
>>> len(result)
0
>>> result = SearchQuerySet().raw_search('django_ct:movies.movie')
>>> len(result)
0
>>> len(result.all())
0
>>> all_result = SearchQuerySet()
>>> len(all_result)
10924
>>>
The index for Movies is
import datetime
from django.db.models import Q
from haystack import indexes
from search.base_search_index import BaseSearchIndex
from search.fields import MultiValueDateField
from movies.models import Movie, Show
class MovieIndex(BaseSearchIndex, indexes.Indexable):
dates = MultiValueDateField(null=True,)
areas = indexes.MultiValueField(null=True)
categories = indexes.MultiValueField(null=True)
venues = indexes.MultiValueField(null=True)
hot = indexes.BooleanField(model_attr='is_hot')
showing = indexes.BooleanField(model_attr='now_showing')
sortorder = indexes.IntegerField(model_attr='sortorder')
name = indexes.CharField(model_attr='name')
def prepare_areas(self, obj):
shows = obj.shows.all()
areas = []
if shows:
for s in shows:
if s.venue and s.venue.area_id:
areas.append(s.venue.area_id)
return self.get_list_for_multivalue_field(areas)
def prepare_venues(self, obj):
shows = obj.shows.all()
if shows:
return [show.venue_id for show in shows]
return None
def prepare_categories(self, obj):
cats = []
for category in obj.categories.all():
cats.extend([c.id for c in category.get_ancestors(include_self=True)])
return self.get_list_for_multivalue_field(cats)
def prepare_dates(self, obj):
dates = [d for d in obj.start_dates()]
return dates
def get_model(self):
return Movie
def index_queryset(self, using=None):
"""Used when the entire index for model is updated."""
return self.get_model().objects.filter(
Q(visible=True) &
Q(publish__lte=datetime.date.today()) &
(Q(expires__isnull=True) | Q(expires__gte=datetime.date.today())) &
Q(shows__starts__gte=datetime.date.today()),
).distinct()
class ShowIndex(BaseSearchIndex, indexes.Indexable):
movie = indexes.IntegerField(null=True)
venue = indexes.IntegerField(null=True)
starts = indexes.DateField(model_attr='starts')
area = indexes.IntegerField(null=True,)
categories = indexes.MultiValueField(null=True)
hot = indexes.BooleanField()
i = indexes.IntegerField(model_attr='movie__pk')
shows = indexes.IntegerField(model_attr='pk')
def prepare_movie(self, obj):
if obj.movie_id:
return obj.movie_id
return -1
def prepare_venue(self, obj):
if obj.venue_id:
return obj.venue_id
return -1
def prepare_area(self, obj):
if obj.venue.area_id:
return obj.venue.area_id
return -1
def prepare_categories(self, obj):
cats = []
for category in obj.movie.categories.all():
cats.extend([c.id for c in category.get_ancestors(include_self=True)])
return self.get_list_for_multivalue_field(cats)
def prepare_hot(self, obj):
return obj.movie.is_hot()
def prepare_slug(self, obj):
return u''
def prepare(self, obj):
today = datetime.datetime.now()
data = super(BaseSearchIndex, self).prepare(obj)
data['boost'] = 1
return data
def get_model(self):
return Show
def index_queryset(self, using=None):
"""Used when the entire index for model is updated."""
return self.get_model().objects.filter(starts__gte=datetime.date.today()).distinct()
and it's inheritance
import datetime
from django.db.models import Q
from haystack import indexes
class BaseSearchIndex(indexes.SearchIndex):
text = indexes.CharField(document=True, use_template=True)
html = indexes.CharField(use_template=True, indexed=False)
json = indexes.CharField(use_template=True, indexed=False)
slug = indexes.CharField()
#pk_xapian = indexes.IntegerField(model_attr='pk')
i = indexes.IntegerField(model_attr='pk')
def prepare_slug(self, obj):
return u'unique%sunique' % obj.slug
def get_updated_field(self):
return 'modified'
def index_queryset(self, using=None):
"""Used when the entire index for model is updated."""
today = datetime.date.today()
return self.get_model().objects.filter(
Q(visible=True) &
Q(publish__lte=today) &
(Q(expires__isnull=True) | Q(expires__gte=today))
).distinct()
def prepare(self, obj):
today = datetime.datetime.now()
data = super(BaseSearchIndex, self).prepare(obj)
weeks = (today - obj.created).days / 7 + 1
data['boost'] = 1 + (1.0 / weeks)
return data
def get_list_for_multivalue_field(self, value):
if len(value) == 0:
return []
elif len(value) == 1:
return [value[0],]
return value
The search works but the logic used to get the data to json for an app has the logic with searchqueryset and filters per model and returns nothing.