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

如何在Django中扩展用户模型实现图书收藏功能?

Django收藏夹功能问题解决

我是Django新手,正在搭建一个可查看图书及作者数据库、将任意图书添加至“收藏夹”的网站。尝试通过扩展UserModel添加关联收藏图书的字段,已在后台管理界面看到UserProfile的收藏内容,但无法将视图与bookfavs.html关联以让用户查看自己的收藏图书,页面仅显示用户名,不展示收藏内容。项目app名称为bookshelf,相关代码如下:

Models.py

class UserProfile(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    favorites = models.ManyToManyField(Book, related_name='favourites')

class Author(models.Model):
    first_name=models.CharField(max_length=30)
    last_name=models.CharField(max_length=30)
    dob = models.DateField()
    bio = models.CharField(max_length=300)
    
    def __str__(self):
        return self.first_name + " " + self.last_name

    def get_absolute_url(self):
            return reverse('authorlist')

class Book(models.Model):
    id = models.AutoField(primary_key=True)
    users = models.ManyToManyField(User)
    title = models.CharField(max_length=50)
    num_page = models.IntegerField()
    date_pub = models.DateField()
    tags = models.CharField(max_length=200)
    blurb = models.CharField(max_length=300)

    def get_absolute_url(self):
            return reverse('')

views.py

#Add favourite button...?
def favorite(request, pk):
    if request.method == 'POST':
        favorite = Book.objects.get(pk=pk)
        user = request.user
        user.favorites.add(favorite)
        messages.add_message(request, messages.INFO, 'Book Favorited.')
        return redirect('home')


#List ALL books
class BookList(ListView):
    model = Book
    template_name='bookshelf/booklist.html'

#List favourite books
class BookFavs(TemplateView):
    model = UserProfile
    template_name = 'bookshelf/bookfavs.html'
    def get_context_data(self,*args, **kwargs):
        context = super(BookFavs, self).get_context_data(*args,**kwargs)
        context['users'] = UserProfile.objects.all()
        return context

bookfavs.html

{% if user.username %} 
<h4 class="header-greet">Welcome {{ user.username }} to your books!</h4> 
{% endif %}

{% if user.is_authenticated %}
    {% with userprofile.favorites.all as favourite_books %}
      {% for book in book_list %}
        {% if book in favorite_book %}
        <p>{{ book.title }}</p>
        {% endif %}
      {% endfor %}
    {% endwith %}
{% endif %}

问题修复步骤

1. 修正UserProfile与User的关联关系

一个用户对应唯一的UserProfile,把ForeignKey改成OneToOneField:

class UserProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)  # 修改此处
    favorites = models.ManyToManyField(Book, related_name='favourites')

2. 修复添加收藏的视图函数

favorites字段属于UserProfile而非User本身,需先获取当前用户的UserProfile再添加收藏:

def favorite(request, pk):
    if request.method == 'POST':
        favorite_book = Book.objects.get(pk=pk)
        # 获取当前用户的UserProfile
        user_profile = UserProfile.objects.get(user=request.user)
        user_profile.favorites.add(favorite_book)
        messages.add_message(request, messages.INFO, '图书已收藏')
        return redirect('home')

3. 调整收藏列表视图,传递当前用户的收藏数据

不要传递所有UserProfile,仅获取当前登录用户的收藏图书:

class BookFavs(TemplateView):
    template_name = 'bookshelf/bookfavs.html'
    def get_context_data(self,*args, **kwargs):
        context = super().get_context_data(*args,**kwargs)
        # 获取当前用户的UserProfile及收藏图书
        user_profile = UserProfile.objects.get(user=self.request.user)
        context['favorite_books'] = user_profile.favorites.all()
        return context

4. 修复模板渲染逻辑

模板中无userprofile和book_list变量,直接使用视图传递的favorite_books循环,同时修正变量名拼写错误:

{% if user.username %} 
<h4 class="header-greet">欢迎 {{ user.username }} 查看你的收藏!</h4> 
{% endif %}

{% if user.is_authenticated %}
    {% if favorite_books %}
        {% for book in favorite_books %}
            <p>{{ book.title }}</p>
        {% endfor %}
    {% else %}
        <p>你还没有收藏任何图书哦~</p>
    {% endif %}
{% endif %}

5. 补充用户创建时自动生成UserProfile的信号(可选但重要)

避免用户创建后无对应UserProfile导致报错,在models.py末尾添加:

from django.db.models.signals import post_save
from django.contrib.auth.models import User
from django.dispatch import receiver

@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    if created:
        UserProfile.objects.create(user=instance)

@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
    instance.userprofile.save()

6. 确保路由配置正确

在urls.py中配置收藏列表的路由:

from django.urls import path
from . import views

urlpatterns = [
    # 其他路由...
    path('favorites/', views.BookFavs.as_view(), name='bookfavs'),
    path('favorite/<int:pk>/', views.favorite, name='favorite'),
]

内容的提问来源于stack exchange,提问作者Steve W

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 13:33:11