You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Django类视图(DetailView)实现文章收藏标记系统?

How to Implement Article Favorite/Unfavorite Using Django CBV (Instead of FBV)

Great question! Converting your existing favorite functionality from FBV to CBV is totally doable, and there are a couple of clean approaches depending on whether you want a dedicated view for the action or to integrate it directly into your existing ArticleDetailView. Let's walk through both options:

Option 1: Create a Dedicated CBV for Favorite/Unfavorite Action

This keeps your logic separated and follows the single responsibility principle. We'll use Django's base View class plus LoginRequiredMixin to ensure only logged-in users can interact with the feature.

Step 1: Update Your Views

Replace your favorite_post FBV with this CBV:

from django.views import View
from django.shortcuts import get_object_or_404, redirect
from django.contrib.auth.mixins import LoginRequiredMixin
from .models import Article

class FavoriteArticleView(LoginRequiredMixin, View):
    def post(self, request, pk):
        # Fetch the article or return 404 if it doesn't exist
        article = get_object_or_404(Article, pk=pk)
        user = request.user
        
        # Toggle the favorite status
        if user in article.favorite.all():
            article.favorite.remove(user)
        else:
            article.favorite.add(user)
        
        # Redirect back to the article detail page
        return redirect('article_detail', pk=pk)

Step 2: Update Your URL Configuration

Swap out the FBV path with the CBV's as_view() method:

urlpatterns = [
    path('<int:pk>/edit/', ArticleUpdateView.as_view(), name='article_update'),
    # Replace the old FBV path with this
    path('<int:pk>/favorite/', FavoriteArticleView.as_view(), name='favorite_post'),
]

Option 2: Integrate Favorite Logic into Your Existing ArticleDetailView

If you prefer to keep related logic together, you can extend your existing DetailView to handle POST requests for the favorite action.

Step 1: Modify ArticleDetailView

Add LoginRequiredMixin (to restrict access) and override the post method. We'll also update get_context_data to pass a flag for whether the user has favorited the article (useful for your template):

from django.contrib.auth.mixins import LoginRequiredMixin

class ArticleDetailView(LoginRequiredMixin, ObjectViewMixin, DetailView):
    model = Article
    context_object_name = 'article'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        # Add a flag to check if the current user has favorited the article
        context['is_favorited'] = self.object.favorite.filter(id=self.request.user.id).exists()
        return context

    def post(self, request, *args, **kwargs):
        self.object = self.get_object()
        user = request.user
        
        # Toggle favorite status
        if user in self.object.favorite.all():
            self.object.favorite.remove(user)
        else:
            self.object.favorite.add(user)
        
        # Redirect back to the article detail page using the model's get_absolute_url
        return redirect(self.object.get_absolute_url())

Step 3: Update Your Template

For either option, you'll need a form to trigger the POST request. Here's how to set it up:

If Using Option 1 (Dedicated CBV):

<form method="POST" action="{% url 'favorite_post' article.pk %}">
    {% csrf_token %}
    <button type="submit">
        {% if article.favorite.all %}取消收藏{% else %}收藏{% endif %}
    </button>
</form>

If Using Option 2 (Integrated into DetailView):

<form method="POST" action="{% url 'article_detail' article.pk %}">
    {% csrf_token %}
    <button type="submit">
        {% if is_favorited %}取消收藏{% else %}收藏{% endif %}
    </button>
</form>

Key Notes

  • Login Required: The LoginRequiredMixin is critical here—anonymous users can't be added to a ManyToManyField, so this prevents errors and ensures only authenticated users can favorite articles.
  • CSRF Protection: Always include {% csrf_token %} in your POST forms to avoid Django's CSRF validation errors.
  • User Experience: Passing the is_favorited flag to the template lets you show context-aware button text, which makes the interface more intuitive.

内容的提问来源于stack exchange,提问作者Tareq Monwer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:49:00