【问题标题】:Django render_to_string Returns NoneType ErrorDjango render_to_string 返回 NoneType 错误
【发布时间】:2021-12-29 16:51:43
【问题描述】:

使用 Django Pagination 我正在尝试使用 AJAX 进行无休止的分页。我按照这里的例子:https://www.progerhub.com/tutorial/adding-pagination-with-infinite-scroll-in-django/

我的视图可以很好地返回结果的第一页,但是当我尝试为其他页面构建内容并使用 render_to_string 将其作为 JSON 返回时,将数据附加到我的内容变量时出现错误。

错误信息

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 class="card media-item p-0 mb-4" onclick="parent.location='/media/{{ media.pk }}'">
    {% if media.poster %}
    {% thumbnail media.poster "400x600" crop="center" as thumb %}
    <img class="w-100 img-fluid rounded" src="{{ thumb.url }}" width="{{ thumb.width }}" height="{{ thumb.height }}" onclick="parent.location='{{ media.poster.url }}'">
    {% endthumbnail %}
    {% else %}
    <img class="w-100 media-poster img-fluid rounded" src="{% static 'images/no_poster.png' %}">
    {% endif %}
    <div class="media-overlay text-right pr-1">
        <i class="fas fa-circle fa-2x pt-1 pr-0 d-none
        {% for status in status_list %}
            {% if status.media == media and status.watch == True %}
                d-inline
            {% elif status.media == media and status.watch == False %}
                d-none
            {% endif %}
        {% endfor %}" style="color: #00bb8c;"></i>
        <i class="fas fa-circle fa-2x pt-1 pr-0 {% if not media.download %}d-none{% endif %}" style="color: #e74c3c;"></i>
        <i class="fas fa-circle fa-2x pt-1 pr-0 {% if not media.fix %}d-none{% endif %}" style="color: #f39c12;"></i>
    </div>
    <div class="card-header p-2">
        {% if media.imdb_rating %}
        <i class="fas fa-star" 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 %}
        " class="pl-3" 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' %}" class="pl-3" 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 class="card-body p-2">
        <p class="card-title m-0 mb-2">
            {{ media.title|truncatewords:10 }}
        </p>
        {% if media.content_rating %}
        <p class="card-subtitle text-muted">
            {{ media.content_rating }}
        </p>
        {% endif %}
    </div>
</div>
<!-- wrap cards after certain number -->
{% if forloop.counter|divisibleby:2 %}<div class="w-100 d-none d-sm-block d-md-none"><!-- wrap every 3 on sm--></div>{% endif %}
{% if forloop.counter|divisibleby:2 %}<div class="w-100 d-none d-md-block d-lg-none"><!-- wrap every 4 on md--></div>{% endif %}
{% if forloop.counter|divisibleby:4 %}<div class="w-100 d-none d-lg-block d-xl-none"><!-- wrap every 5 on lg--></div>{% endif %}
{% if forloop.counter|divisibleby:6 %}<div class="w-100 d-none d-xl-block"><!-- wrap every 6 on xl--></div>{% endif %}

显然,我的render_to_string 中的{'media': media} 有问题,但我不确定是什么问题。这里有什么我忽略的吗?

【问题讨论】:

  • 可以分享media_item.html的内容吗,好像是模板出错了
  • 我添加了完整的媒体模型和 media_item.html 的内容。
  • 模板底部的所有{% if forloop.counter|divisibleby:... %} 是怎么回事?他们甚至不在 for 循环中
  • media.html 模板中,media_item.html 模板用于 for 循环。这似乎是破坏事物的原因。我将不得不重新考虑媒体项目的格式。

标签: python django ajax


【解决方案1】:

代替:

{% if forloop.counter|divisibleby:2 %}<div class="w-100 d-none d-sm-block d-md-none"><!-- wrap every 3 on sm--></div>{% endif %}
{% if forloop.counter|divisibleby:2 %}<div class="w-100 d-none d-md-block d-lg-none"><!-- wrap every 4 on md--></div>{% endif %}
{% if forloop.counter|divisibleby:4 %}<div class="w-100 d-none d-lg-block d-xl-none"><!-- wrap every 5 on lg--></div>{% endif %}
{% if forloop.counter|divisibleby:6 %}<div class="w-100 d-none d-xl-block"><!-- wrap every 6 on xl--></div>{% endif %}

尝试:

{% if forloop.counter %}
    {% if forloop.counter|divisibleby:2 %}<div class="w-100 d-none d-sm-block d-md-none"><!-- wrap every 3 on sm--></div>{% endif %}
    {% if forloop.counter|divisibleby:2 %}<div class="w-100 d-none d-md-block d-lg-none"><!-- wrap every 4 on md--></div>{% endif %}
    {% if forloop.counter|divisibleby:4 %}<div class="w-100 d-none d-lg-block d-xl-none"><!-- wrap every 5 on lg--></div>{% endif %}
    {% if forloop.counter|divisibleby:6 %}<div class="w-100 d-none d-xl-block"><!-- wrap every 6 on xl--></div>{% endif %}
{% endif %}

【讨论】:

  • 这解决了我的问题并返回了我想要的东西。看起来我将不得不在不使用 for 循环的情况下进行一些修改以使格式正确。谢谢!
  • 很高兴为您提供帮助,祝您好运:)
猜你喜欢
  • 1970-01-01
  • 2010-10-07
  • 1970-01-01
  • 2017-08-25
  • 1970-01-01
  • 1970-01-01
  • 2023-04-02
  • 2023-02-07
  • 2021-08-09
相关资源
最近更新 更多