Using Django Pagination I'm trying to do endless pagination using AJAX. I followed the example here: https://www.progerhub.com/tutorial/adding-pagination-with-infinite-scroll-in-django/
My view returns the first page of results just fine, but when I attempt to build the content for the additional pages and return it as JSON using render_to_string
I get an error while appending data onto my content variable.
error message
web_1 | Traceback (most recent call last):
...
web_1 | File "/usr/src/django/media/views.py", line 74, in get
web_1 | content = render_to_string('media_item.html', {'media': media, }, request=request)
...
web_1 | new_obj = func(obj, *arg_vals)
web_1 | File "/usr/local/lib/python3.8/site-packages/django/template/defaultfilters.py", line 784, in divisibleby
web_1 | return int(value) % int(arg) == 0
web_1 | TypeError: int() argument must be a string, a bytes-like object or a number, not 'NoneType'
models.py
class Media(Audit):
def get_poster_path(instance, filename):
new_filename = "%s-%s" % (instance.sort_title, instance.year)
filename = "%s.jpg" % (slugify(new_filename))
upload_path = "posters/%s" % (filename)
return upload_path
imdb_id = models.CharField(
max_length=255,
blank=True,
null=True)
media_type = models.CharField(
max_length=16,
blank=False,
null=False,
choices=media_type_choices)
title = models.CharField(
max_length=255)
sort_title = models.CharField(
max_length=255,
blank=True,
null=True)
year = models.IntegerField(
blank=True,
null=True)
content_rating = models.CharField(
max_length=16,
blank=True,
null=True,
choices=media_content_rating_choices)
runtime = models.CharField(
max_length=16,
blank=True,
null=True)
release_date = models.DateField(
blank=True,
null=True)
genre_primary = models.ForeignKey(
Genre,
blank=True,
null=True,
on_delete=models.SET_NULL,
related_name='genre_primary')
genre_secondary = models.ForeignKey(
Genre,
blank=True,
null=True,
on_delete=models.SET_NULL,
related_name='genre_secondary')
quality = models.CharField(
max_length=16,
blank=True,
null=True,
choices=quality_choices)
language = models.CharField(
max_length=16,
blank=True,
null=True,
choices=language_choices)
description = models.CharField(
max_length=500,
blank=True,
null=True)
imdb_rating = models.DecimalField(
max_digits=3,
decimal_places=1,
blank=True,
null=True)
rotten_tomato_rating = models.IntegerField(
blank=True,
null=True)
metacritic_rating = models.IntegerField(
blank=True,
null=True)
download = models.BooleanField(
default=False,
help_text="Check this if media needs to be downloaded.")
fix = models.BooleanField(
default=False,
help_text="Check this if media needs to be fixed.")
notes = models.CharField(
max_length=500,
blank=True,
null=True)
omdb_date = models.DateField(
blank=True,
null=True)
poster = ProcessedImageField(
blank=True,
null=True,
format='JPEG',
options={'quality': 100},
processors=[ResizeToFill(1000, 1500)],
upload_to=get_poster_path)
class Meta:
ordering = (
'sort_title',
'title',
'year')
def __str__(self):
return self.title
views.py
class MediaView(LoginRequiredMixin, JsonMixin, View):
def get(self, request, *args, **kwargs):
context = self.get_context_data()
context['status_list'] = models.MediaStatus.objects.filter(user=self.request.user)
media = models.Media.objects.filter()
page = int(request.GET.get('page', 1))
p = paginator.Paginator(media, 24) # number of media per page
# try to get media for the given page
try:
media_page = p.page(page)
except paginator.EmptyPage:
media_page = paginator.Page([], page, p)
# get initial media list
if not request.is_ajax():
context['media_list'] = media_page
return render(request, 'media.html', context)
# get more media using ajax
else:
content = ''
for media in media_page:
content = render_to_string('media_item.html', {'media': media}, request=request)
data = {
'content': content,
'end_pagination': True if page >= p.num_pages else False,
}
print(data)
return self.render_to_json_response(data)
media_item.html
{% load static %}
{% load thumbnail %}
<div onclick="parent.location='/media/{{ media.pk }}'">
{% if media.poster %}
{% thumbnail media.poster "400x600" crop="center" as thumb %}
<img src="{{ thumb.url }}" width="{{ thumb.width }}" height="{{ thumb.height }}" onclick="parent.location='{{ media.poster.url }}'">
{% endthumbnail %}
{% else %}
<img src="{% static 'images/no_poster.png' %}">
{% endif %}
<div >
<i style="color: #00bb8c;"></i>
<i style="color: #e74c3c;"></i>
<i style="color: #f39c12;"></i>
</div>
<div >
{% if media.imdb_rating %}
<i style="color: #efc63c;"></i> <span>{{ media.imdb_rating }}</span>
{% endif %}
{% if media.rotten_tomato_rating %}
<img src="
{% if media.rotten_tomato_rating > 60 %}
{% static 'images/icons/tomatometer.svg' %}
{% else %}
{% static 'images/icons/tomatometer_rotten.svg' %}
{% endif %}
" style="margin: -3px 0 0 0; height: 18px;"> <span>{{ media.rotten_tomato_rating }}%</span>
{% endif %}
{% if media.metacritic_rating %}
<img src="{% static 'images/icons/metacritic.svg' %}" style="margin: -3px 0 0 0; height: 18px;"> <span>{{ media.metacritic_rating }}</span>
{% endif %}
{% if not media.imdb_rating and not media.rotten_tomato_rating and not media.metacritic_rating %}
{% endif %}
</div>
<div >
<p >
{{ media.title|truncatewords:10 }}
</p>
{% if media.content_rating %}
<p >
{{ media.content_rating }}
</p>
{% endif %}
</div>
</div>
<!-- wrap cards after certain number -->
{% if forloop.counter|divisibleby:2 %}<div ><!-- wrap every 3 on sm--></div>{% endif %}
{% if forloop.counter|divisibleby:2 %}<div ><!-- wrap every 4 on md--></div>{% endif %}
{% if forloop.counter|divisibleby:4 %}<div ><!-- wrap every 5 on lg--></div>{% endif %}
{% if forloop.counter|divisibleby:6 %}<div ><!-- wrap every 6 on xl--></div>{% endif %}
Apparently, there is something wrong with {'media': media}
in my render_to_string
, but I'm not sure what it is. Is there something I've overlooked here?
CodePudding user response:
Instead of:
{% if forloop.counter|divisibleby:2 %}<div ><!-- wrap every 3 on sm--></div>{% endif %}
{% if forloop.counter|divisibleby:2 %}<div ><!-- wrap every 4 on md--></div>{% endif %}
{% if forloop.counter|divisibleby:4 %}<div ><!-- wrap every 5 on lg--></div>{% endif %}
{% if forloop.counter|divisibleby:6 %}<div ><!-- wrap every 6 on xl--></div>{% endif %}
try:
{% if forloop.counter %}
{% if forloop.counter|divisibleby:2 %}<div ><!-- wrap every 3 on sm--></div>{% endif %}
{% if forloop.counter|divisibleby:2 %}<div ><!-- wrap every 4 on md--></div>{% endif %}
{% if forloop.counter|divisibleby:4 %}<div ><!-- wrap every 5 on lg--></div>{% endif %}
{% if forloop.counter|divisibleby:6 %}<div ><!-- wrap every 6 on xl--></div>{% endif %}
{% endif %}