首页 > 解决方案 > Django - “NoneType”对象没有属性“线程”

问题描述

大家好,所以我正在尝试按照本网站https://djangopy.org/how-to/how-to-implement-categories-in-django/上的教程为帖子添加类别系统(我更改了我的代码一点)

'NoneType' object has no attribute 'threads'每次我尝试转到类别页面查看该类别中的帖子时都会收到此错误。

模型.py:

from django.db import models
from django.urls import reverse
from django.utils.text import slugify

class Category(models.Model):
    name = models.CharField(max_length=100)
    short_desc = models.CharField(max_length=160)
    slug = models.SlugField()
    parent = models.ForeignKey('self', blank=True, null=True, related_name='children', on_delete=models.CASCADE)

    class Meta:
        unique_together = ('slug', 'parent',)
        verbose_name_plural = "Categories"

    def __str__(self):
        full_path = [self.name]
        k = self.parent

        while k is not None:
            full_path.append(k.name)
            k = k.parent

        return ' -> '.join(full_path[::-1])

    def save(self, *args, **kwargs):
        value = self.name
        self.slug = slugify(value, allow_unicode=True)
        super().save(*args, **kwargs)


class Thread(models.Model):
    ...
    category = models.ForeignKey('Category', null=True, blank=True, on_delete=models.CASCADE, related_name='threads')
    ...

    def get_cat_list(self):
        k = self.category
        breadcrumb = ["dummy"]
        while k is not None:
            breadcrumb.append(k.slug)
            k = k.parent

        for i in range(len(breadcrumb)-1):
            breadcrumb[i] = '/'.join(breadcrumb[-1:i-1:-1])
        return breadcrumb[-1:0:-1]

    ...

视图.py:

from django.shortcuts import render, HttpResponseRedirect
from django.contrib import messages
from .models import Category, Thread
from .forms import SubmitScamNumber

def show_category_view(request, hierarchy=None):
    category_slug = hierarchy.split('/')
    category_queryset = list(Category.objects.all())
    all_slugs = [ x.slug for x in category_queryset ]
    parent = None
    for slug in category_slug:
        if slug in all_slugs:
            #parent = get_object_or_404(Category, slug=slug, parent=parent)
            parent = Category.objects.filter(slug__in=category_slug, parent=None).first()

    context = {
        'category': parent,
        'threads': parent.threads.all(),
        'sub_categories': parent.children.all(),
    }
    return render(request, "categories.html", context)

 ...

类别.html:

{% extends 'base.html' %}
{% block content %}

{% if sub_categories %}
    <h3>Sub Categories</h3>
    {% for i in sub_categories %}
        <a href="{{ i.slug }}"> {{ i.name }} </a>
    {% endfor %}
{% endif %}

{% if threads %}
{% for i in threads %}
    <div class="columns">
        <div class=" card-article-hover card">
          <a href="{{ i.slug }}">
            <img  src="{{ i.cover_photo.url }}">
          </a>
          <div class="card-section">
            <a href="{{ i.slug }}">
              <h6 class="article-title">{{ i.title | truncatechars:30}}</h6>
            </a>
          </div>
          <div class="card-divider flex-container align-middle">
            <a href="" class="author">{{ i.user.get_full_name }}</a>
          </div>
          <div class="hover-border">
          </div>
        </div>
    </div>
{% endfor %}
{% endif %}

{% endblock content %}

标签: djangodjango-models

解决方案


show_category_view你设置parent = None. hierarchy然后,如果parent有任何从Category. 但是,如果没有 slugcategory_slug 或者在 slug 中找不到all_slugs 或者该行Category.objects.filter(slug__in=category_slug, parent=None).first()没有返回 的实例,那么当您尝试访问对象上的属性时Category, 的值parent将保持为在这里做...NonethreadsNone

parent.threads.all()  # parent = None

...您看到的异常将会发生。

所以,正如错误告诉你的那样,'NoneType' object has no attribute 'threads', 因为parent仍然None是最初定义的。

此函数中潜伏着另一个空值检查错误。

def show_category_view(request, hierarchy=None):
    category_slug = hierarchy.split('/')

您将hierarchy参数的默认值设置为None,然后调用split它,即使该值可能是None。如果你调用splitNone会抛出一个类似的AttributeError.

你也不需要投list过来category_queryset = list(Category.objects.all())。Querysets 已经是可以循环的对象列表,实现迭代器协议等(实际上,这样做你丢掉了 queryset 接口为你提供的所有好处。)在这里你可以这样做:

all_slugs = [x.slug for x in Category.objects.all()]

推荐阅读