【问题标题】:Django: NameError: Slug is not definedDjango: NameError: Slug 未定义
【发布时间】:2021-01-01 15:38:25
【问题描述】:

任何人都可以建议如何查询要在我的 HTML 中显示的帖子的 `total_likes,我试过了,但出现了这个错误:

NameError: Slug is not defined

一位专家建议我使用我不熟悉的通用类视图,有没有其他方法可以查询正确的帖子并定义 slug?不确定为什么它不适用于主页提要视图,但它确实适用于详细博客视图。其实怎么回事。我不能在主页视图中包含 slug 参数,因为 url 不包含 .真的没有别的办法了吗?

views.py

def home_feed_view(request, slug=None):
    context = {}
    blog_posts = sorted(BlogPost.objects.all(), key= attrgetter('date_updated'), reverse = True)

    if slug:
        blog_post = get_object_or_404(BlogPost, slug=slug)
        context['blog_post'] = blog_post
        total_likes = blog_post.total_likes()
        context['total_likes'] = total_likes
        liked = False
        if blog_post.likes.filter(id=request.user.id).exists():
            liked = True
    context['blog_posts'] = blog_posts 

    return render(request, "HomeFeed/snippets/home.html", context)


def LikeView(request, slug):
    context = {}

    post = get_object_or_404(BlogPost, slug=slug)
    liked = False
    if post.likes.filter(id=request.user.id).exists():
        post.likes.remove(request.user)
        liked = False
    else:
        post.likes.add(request.user)
        liked = True 
    return redirect('HomeFeed:detail', slug=slug)

.html

{% for post in blog_posts %} 

   <td class="table-primary">
       <form action="{% url 'HomeFeed:like_post' post.slug %}" method="POST">{% csrf_token %} 
        {% if liked %}
           <button type="submit" name="mysubmitbuttonname"  value="{{post.slug}}" class='btn btn-primary btn-sm'>Unlike</button> 
           {% else %}
           <button type="submit" name="mysubmitbuttonname"  value="{{post.slug}}" class='btn btn-primary btn-sm'>Like</button> 
           {% endif %}
           {{ total_likes }}  Like{{ total_likes|pluralize }}

        </form>
    </td>  
{% endfor %}

models.py

class BlogPost(models.Model):
    likes = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='blog_posts', blank=True)
    slug = models.SlugField(blank=True, unique=True)
 

    def total_likes(self):
        return self.likes.count()
  

urls.py

from django.urls import path
from HomeFeed.views import(
    home_feed_view,
    LikeView,
)

urlpatterns = [
    path('', home_feed_view , name= "main"),
    path('<slug>/like/', LikeView, name='like_post'),
]

追溯

Traceback (most recent call last):
  File "lib/python3.8/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "lib/python3.8/site-packages/django/core/handlers/base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "lib/python3.8/site-packages/django/core/handlers/base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/HomeFeed/views.py", line 81, in home_feed_view
    blog_post = get_object_or_404(BlogPost, slug=slug)
NameError: name 'slug' is not defined

【问题讨论】:

  • 分享完整回溯。
  • @WillemVanOnsem 共享 :)
  • @WillemVanOnsem 实际上我尝试使用 blog_post = get_object_or_404(BlogPost, slug=request.POST.get('blog_post_slug')) 而不是 blog_post = get_object_or_404(BlogPost, slug=slug) 但后来我无法查询博客文章,并收到 404 错误。我也知道如何使用通用类视图..知道如何正确查询 slug 吗?
  • 你的home_feed_view 没有slug 参数,因此它不能使用它...
  • @WillemVanOnsem 是的,我之前设法弄清楚了,如果我不使用通用 django 类视图,我是否无法查询。因为我没有学到很多关于通用 django 类视图的知识

标签: python django


【解决方案1】:

我会给你一个使用基于类的视图的解决方案,向你展示它们是多么清晰(没有样板代码)

urls.py

from .views import LikeView, PostDetailView, HomeFeedView

urlpatterns = [
    ...
    path("home/", HomeFeedView.as_view(), name="home"),
    path("like-post/<str:post_slug>/", LikeView.as_view(), name="like_post"),
    path("post-detail/<str:post_slug>/", PostDetailView.as_view(), name="post_detail"),
]

然后在你的views.py

from django.views import View
from django.views.generic import DetailView, ListView
from django.shortcuts import get_object_or_404
from django.http import HttpResponseRedirect


class HomeFeedView(ListView):
    model = Post
    template_name "HomeFeed/snippets/home.html"
    context_object_name = "blog_posts"
    ordering = ("-date_updated",)


class LikeView(View):

    def dispatch(self, request, *args, **kwargs):
        self.post = get_object_or_404(Post, slug=kwargs["post_slug"])
        # If you get a 404 error here, then your `slug` is not valid.
        return super().dispatch(request, *args, **kwargs)

    def get(self, request, *args, **kwargs):
        if self.post.likes.filter(id=request.user.id).exists():
            self.post.likes.remove(request.user)
        else:
            self.post.likes.add(request.user)
        return HttpResponseRedirect(reverse_lazy("HomeFeed:post_detail", kwargs={"post_slug": self.post.slug}))

class PostDetailView(DetailView):
    model = Post
    template_name = "HomeFeed/detail_blog.html"
    context_object_name = "blog_post"
    slug_url_kwarg = "post_slug"
    slug_field = "slug"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        post = self.object
        context.update({
            "total_likes": post.total_likes,
            "liked": self.request.user in post.likes.all(),
        })
        return context

并考虑到您的 HTML sn-p 中的更改:

<!-- Template -->

{% for post in blog_posts %}
    <!-- Other markup-->
    <a href="{% url 'HomeFeed:post_detail' post.slug %}">View Post</a>
    <a href="{% url 'HomeFeed:like_post' post.slug %}">Like Post</a>
    <!-- Other markup -->
{% endfor %}

然后显示总喜欢等,仅在您的模板中执行此操作。要检查用户是否喜欢某个帖子,请使用模板标签/过滤器,例如,当循环时:

{% with post|liked_by:user as liked %}
    <!-- 'liked' will be a bool, then do whatever you want with it.
{% endwith %}

这是一种方法,但不是最好的方法。您可能还需要使用查询集上的注释来查找(无论用户是否喜欢帖子),以便所有逻辑(尤其是涉及到数据库查询的逻辑)都在视图级别而不是模板内部处理。

【讨论】:

  • 谢谢你 Redgren,我将冒险进入通用类视图以及你所写的内容。真的很欣赏这些代码,当我开始练习编写它们时,它会对我有很大帮助。祝你有个快乐的一天!
【解决方案2】:

问题是home_feed_view 并非设计为采用另一个参数(“slug”)

你可以拥有(基于你的表单的 action 属性):

views.py

def home_feed_view(request, slug=None):
    
    context = {}
    ...
    if slug:
        blog_post = get_object_or_404(BlogPost, slug=slug)
        ## add blogpost to content only if it exists
        context['blog_post'] = blog_post
        total_likes = blog_post.total_likes()
        liked = False
        if blog_post.likes.filter(id=request.user.id).exists():
            liked = True
        context['total_likes'] = total_likes

    ...

【讨论】:

  • 嗨 Mugoma,感谢您的输入,我已经尝试了代码,但不幸的是它说在分配之前已经引用了局部变量 'blog_post' 和 'total_likes'。因此,我在代码上方移动了context['blog_post'] = blog_post 和 'context['total_likes'] = total_likes`。错误消失了,但我无法查询总喜欢。当我按下它时,like 按钮也没有变为不同
  • 检查编辑。但是,我看到你找到了答案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-03-15
  • 2022-10-16
  • 2023-01-17
  • 2018-07-14
  • 2017-12-25
  • 2021-07-17
  • 2012-05-13
相关资源
最近更新 更多