【问题标题】:I am not able to make the favourite and unfavourite view work in Django application我无法在 Django 应用程序中使最喜欢和不喜欢的视图工作
【发布时间】:2021-03-05 11:40:25
【问题描述】:

我正在尝试在我的应用程序中实现一些最喜欢的功能。但是当使用 get_objects_or_404 时,我遇到了这个奇怪的错误。

我试图让用户单击图标将产品添加到收藏列表中,在我遵循的教程中,我注意到只有当他有帖子详细信息时才有可能,所以他只添加了点击权限在帖子详细信息页面上将帖子添加到收藏夹的图标,因此他能够在将 id 传递给请求时执行类似“post = get_object_or_404(Post, id=id)”的操作。但在我的情况下情况有所不同,我将所有产品都放在一个页面上,并且我没有使用产品详细信息页面,因此我希望用户也能够单击产品页面上的图标

models.py

class Product(models.Model):
    name = models.CharField(max_length=36)
    price = models.PositiveIntegerField()
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    is_favourite = models.ManyToManyField(User, related_name='favourite', blank=True)

views.py

def my_favourite_list(request):
    user = request.user
    favourite_posts = user.is_favourite.all()
    context = {"favourite_posts":favourite_posts}
    return render(request, "core/my-fav-products.html", context)

@login_required
def Products(request):
    title = "All Products"

    products = Product.objects.annotate(
        favourited_by_user=Count(Case(
            When(
                is_favourite=request.user,
                then=1
            ),
            default=0,
            output_field=BooleanField(),
        )),
    ).order_by('-id')

    my_products = Product.objects.filter(user=request.user).order_by('-id')

    context = {"products":products, "my_products":my_products, "title":title}

    return render(request, 'core/products.html', context)

def change_favourite(request, pk):
    product = get_object_or_404(Product, pk=pk)
    if request.method == "POST":
        if Product.objects.filter(pk=pk, is_favourite=request.user).exists():
            product.is_favourite.remove(request.user)
        else:
            product.is_favourite.add(request.user)
    return redirect('product')

products.html

{% for product in products %}
<div class="col-md-4">
    <div class="card">
        <img class="card-img-top" style="height: 200px!important;" src="{{product.image.url}}" alt="Card image cap">
        <div class="card-body">
            <div class="card-title mb-3">
                <span>{{product.name}}</span>
                <span style="float: right;">
                    <form action="{% url 'add-favourite' product.id %}" method="post" style="display: inline-flex;">
                        {% csrf_token %}
                        <button type="submit">
                            {% if product.favourited_by_user %}
                                <i style="font-size: 22px!important;" class="fas fa-star m-r-10"></i>
                            {% else %}
                                <i style="font-size: 22px!important;" class="far fa-star m-r-10"></i>
                            {% endif %}
                        </button>
                    </form>
                    <a href="{% url 'edit-product' product.id %}"><i style="font-size: 22px!important;" class="zmdi zmdi-edit m-r-10"></i></a>
                    <a href="{% url 'delete-product' product.id %}"><i style="font-size: 22px!important;" class="zmdi zmdi-delete"></i></a>
                </span>
            </div>
            <p class="card-text">
                <span>Price: {{product.price}}</span>
                <span style="float: right;">Quantity: {{product.quantity}}</span>
            </p>
        </div>
    </div>
</div>
{% endfor %}

【问题讨论】:

  • 这意味着有 多个 这些元素,如果您的数据库由于 get_object_or_404(Product) 没有过滤像 pk 这样的任何东西而具有多个元素,则会发生这种情况等。
  • 如果您想要一个列表,请尝试使用get_list_or_404。虽然我注意到你只是在下面的行中得到它。您甚至不使用变量 product 只需删除行 product = get_object_or_404(Product) 然后。
  • 您能否解释一下您的目标,并分享您的模型(相关部分)。
  • 我试图让用户单击图标将产品添加到收藏列表中,在我遵循的教程中,我注意到只有当他有帖子详细信息时才有可能,所以他只是添加访问权限以单击图标以将帖子添加到帖子详细信息页面上的收藏夹,因此他能够在将 id 传递给请求时执行类似“post = get_object_or_404(Post, id=id)”的操作。但在我的情况下情况有所不同,我将所有产品都放在一个页面上,并且我没有使用产品详细信息页面,所以我希望用户也能够单击产品页面上的图标。跨度>
  • @coderboy:那么你应该创建一个单独的视图来处理点击,并重定向回列表页面。

标签: python django django-models django-views django-forms


【解决方案1】:

首先修正你的观点Products。 (理想情况下,函数名称应该在snake_case 中,这意味着它应该命名为products)。

from django.db.models import Case, Count, BooleanField, When

def Products(request):
    title = "All Products"
    products = Product.objects.annotate(
        favourited_by_user=Count(Case(
            When(
                is_favourite=request.user,
                then=1
            ),
            output_field=BooleanField(),
        )),
    ).order_by('-id')
    my_products = Product.objects.filter(user=request.user).order_by('-id')

    context = {"products":products, "my_products":my_products, "title":title}

    return render(request, 'core/products.html', context)

现在为收藏逻辑编写另一个视图:

from django.shortcuts import redirect


def change_favourite(request, pk):
    product = get_object_or_404(Product, pk=pk)
    if request.method == "POST":
        if Product.objects.filter(pk=pk, is_favourite=request.user).exists():
            product.is_favourite.remove(request.user)
        else:
            product.is_favourite.add(request.user)
    return redirect('view-name-of-products-list')

现在为这个视图添加一个 url:

urlpatterns = [
    ...
    path('add-to-favourite/<int:pk>/', change_favourite, name='add-favourite'),
    ...
]

现在在您的 html 中,只需将这些按钮放在一个表单中:

<form action="{% url 'add-favourite' product.pk %}" method="post">
    <button type="submit">{% if product.favourited_by_user %}Un-favourite Product{% else %}Favourite Product{% endif %}</button>
</form>

根据需要设置按钮样式。

【讨论】:

  • 感谢先生的详细解答。
  • 看来答案不起作用先生。我已经进行了必要的修改,但是在点击星号后,它并没有从普通星形变为实心星形以表明它已被收藏。
  • 有没有一种方法可以检查该产品是否已被该用户收藏,并且还有一个列表供所有用户查看他们收藏的产品。
  • @coderboy 注释中的小错误。修好了,现在应该可以了。 (删除default=0,
  • @coderboy 您设置了related_name='favourite',这意味着对于User 的实例,您可以编写user.favourite.all() 以获取所有喜欢的产品。
猜你喜欢
  • 1970-01-01
  • 2016-03-10
  • 1970-01-01
  • 1970-01-01
  • 2021-07-18
  • 1970-01-01
  • 2017-03-09
  • 1970-01-01
  • 2020-11-04
相关资源
最近更新 更多