Django能在一个视图中处理多个ID吗?

1 投票
1 回答
31 浏览
提问于 2025-04-13 13:17

为了在Django 4.2和Python中做一些练习,我正在创建一个项目,让用户可以查询和评价他们读过的书籍。现在,"library"应用中的"Book"表里已经有一些书籍了。我的目标是让用户可以把这些书籍添加到他们的个人区域,这些书籍会保存在"readers"应用的"UserBook"表中,以便他们可以后续添加笔记或分类。

为了实现这个功能,用户可以搜索一本书,如果这本书在"library"应用的"Book"数据库中存在,用户就可以进入书籍页面,点击“添加到我的书籍”按钮,这样书籍的信息就会自动复制到"readers"应用的"UserBook"表中,并在用户区域的书籍页面上显示出来。

这是"library"应用中的"Book"表:

class Book(Base):

class Meta:
    verbose_name = 'Book'
    verbose_name_plural = 'Books'
    db_table = 'books'

cover = models.ImageField(upload_to='pictures/cover', blank=True, default='')
title = models.CharField('Title', max_length=100)
publisher = models.CharField('Publisher', max_length=100)
isbn = models.CharField('ISBN', unique=True, max_length=100)
nr_pages = models.IntegerField('Pages',  null=True, blank=True)
synopsis = models.TextField('Synopsis', null=True, blank=True)
author = models.ManyToManyField(Author, verbose_name='Author(s)', related_name='book')

def __str__(self) -> str:
    return self.title

这是url路径的代码,路径是'book/int:id/',对应的视图是views.single_book,按钮是“添加到我的书籍”:

<main class="main-content"> 
    <div class="main-bg">
        <section class="hero">
            <img class="hero-content-img" src= {{ book.cover.url }} alt="Book cover of {{ book.title }}" >
            <header class="hero-content">
                <h2 class="hero-content-title">{{ book.title }}</h2>
                <a class="hero-content-subtitle">
                    {% for author in book.author.all %}
                        {{ author.name }}{% if not forloop.last %}, {% endif %}
                    {% endfor %}
                </a>
                <div class="data-meta">
                    <span class="data-meta-text">ISBN: {{ book.isbn }}</span>
                    <span class="data-meta-text">Publisher: {{ book.publisher }}</span>
                    <span class="data-meta-text">Pages: {{ book.nr_pages }}</span>
                </div>
                <form action="{% url 'readers:book_review' book.id %}" method="post">
                    {% csrf_token %}
                    <button type="submit" class="start-reading-button">Add to My Books</button>
                </form>
            </header>
        </section>
    </div>
</main>

这是"readers"应用中的"UserBook"表:

class UserBook(Base):

class Meta:
    verbose_name = 'My Book'
    verbose_name_plural = 'My Books'
    db_table = 'user_books'

cover = models.ImageField(upload_to='readers/cover', blank=True, default='')
title = models.CharField('Title', max_length=100)
publisher = models.CharField('Publisher', max_length=100)
isbn = models.CharField('ISBN', unique=True, max_length=100)
nr_pages = models.IntegerField('Pages',  null=True, blank=True)
synopsis = models.TextField('Synopsis', null=True, blank=True)
author = models.CharField('Author(s)', max_length=255, null=True, blank=True)
owner = models.ForeignKey(User, related_name='books', on_delete=models.CASCADE,)

def __str__(self) -> str:
        return self.title

这是展示书籍在用户区域的页面的视图,路径是'review/my_books/int:user_book_id/',对应的视图是views.book_review:

def book_review(request, user_book_id):
user_book = None  # Inicialize user_book com None

if request.method == 'POST':
    # Verifica se o livro existe
    book = get_object_or_404(Book, pk=user_book_id)
    
    # Verifica se o usuário já possui este livro
    user_book_exists = UserBook.objects.filter(isbn=book.isbn, owner=request.user).exists()

    if user_book_exists:
        messages.error(request, "You already have this book in your collection.")
        # Se o livro já existe, redirecione para a página de revisão do livro existente
        user_book = UserBook.objects.get(isbn=book.isbn, owner=request.user)
        return redirect('readers:book_review', user_book_id=user_book.id)
    else:
        # Cria um novo UserBook com os dados do livro
        user_book = UserBook.objects.create(
            cover=book.cover,
            title=book.title,
            publisher=book.publisher,
            isbn=book.isbn,
            nr_pages=book.nr_pages,
            synopsis=book.synopsis,
            author=", ".join([author.name for author in book.author.all()]),
            owner=request.user
        )
        # Redireciona para a página de revisão do UserBook recém-criado
        return redirect('readers:book_review', user_book_id=user_book.id)

print("User Book:", user_book)
# Redireciona para a página de revisão do UserBook correspondente (se existir)
if user_book is not None:
    return redirect('readers:book_review', user_book_id=user_book.id)
else:
    # Caso não haja user_book, renderize um template vazio ou redirecione para outra página
    # Por exemplo, você pode retornar uma resposta HTTP com um status 404 (página não encontrada)
    return HttpResponse("User Book not found", status=404)

我在这里遇到了困难,因为尽管在数据库的"UserBook"表中成功记录了数据,但在访问'review/my_books/int:user_book_id'时,显示的却是"Book"表中的id,而不是"UserBook"表中新生成的id,这样就导致了在展示正确的url时出现错误。请问有没有办法修改这个视图以保持这个逻辑,或者我该如何处理呢?

1 个回答

0

问题

我觉得问题出在第6行 book = get_object_or_404(Book, pk=user_book_id)。你是在 Book 表里查找,但用的是来自 UserBook 表的主键来过滤。

解决方案

在HTML中,不要发送 user_book_id,而是应该发送 book_id

撰写回答