Home > Enterprise >  Django render_to_string Returns NoneType Error
Django render_to_string Returns NoneType Error

Time:12-30

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 %}
        &nbsp;
        {% 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 %}
  • Related