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

Django电商:实现登录用户在商品页添加商品到指定心愿单

问题

需求:实现已登录用户可将当前商品添加至自己此前创建的指定心愿单,需在商品页提供一个带复选框的下拉菜单,展示该用户的所有心愿单。

尝试两种方案均未达预期:

  • 在forms.py中使用request.user过滤Wishlist查询集时,出现「request not defined」错误;
  • 采用自定义字段后,查询集会获取所有心愿单,而非当前登录用户的。

附相关代码:

models.py

class Wishlist(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True, blank=True)
    title = models.CharField(max_length=50, null=True,blank=True)
    slug = models.SlugField(max_length=50, null=True,blank=True)
    wishlist_cover_image = models.ImageField(upload_to='media/WISHLIST_COVER_IMAGES/', null=True,blank=True)
    description = RichTextField(max_length=500, null=True,blank=True)
    products = models.ManyToManyField(Product, null=True,blank=True)
    date_created = models.DateTimeField(auto_now_add=True)
    date_updated = models.DateTimeField(auto_now_add=False ,null=True,blank=True)

    def get_absolute_url(self):
        return reverse('ecommerce:wishlist', args=[self.slug])

    def __str__(self):
        return self.title

第一种尝试的forms.py

class AddToWishlistForm(forms.ModelForm):
    wishlists = CustomWLMenu(queryset=Wishlist.objects.filter(user=request.user), widget=forms.CheckboxSelectMultiple)
    class Meta:
        model = Profile
        fields = ['wishlists']

第二种尝试的forms.py

class CustomWLMenu(forms.ModelMultipleChoiceField):
    def label_from_instance(self, user):
        return "%s" % user      
class AddToWishlistForm(forms.ModelForm):
    wishlists = CustomWLMenu(queryset=Wishlist.objects.filter(), widget=forms.CheckboxSelectMultiple)
    class Meta:
        model = Profile
        fields = ['wishlists']
解决方案

核心问题是表单定义阶段无法直接获取request对象,必须在实例化表单时动态传入用户信息过滤查询集。以下是正确实现步骤:

1. 修正表单定义

先定义自定义字段,表单中不直接指定queryset,留到实例化时设置:

class CustomWLMenu(forms.ModelMultipleChoiceField):
    def label_from_instance(self, wishlist):
        return wishlist.title  # 修正:参数是Wishlist实例,之前命名为user是错误的

class AddToWishlistForm(forms.Form):
    # 初始设为空查询集,后续动态赋值
    wishlists = CustomWLMenu(queryset=Wishlist.objects.none(), widget=forms.CheckboxSelectMultiple)

2. 在视图中动态过滤查询集

在商品详情视图里,给登录用户实例化表单时,动态设置wishlists字段的查询集:

from django.contrib.auth.decorators import login_required
from django.shortcuts import get_object_or_404, render
from .models import Product, Wishlist
from .forms import AddToWishlistForm

@login_required
def product_detail(request, slug):
    product = get_object_or_404(Product, slug=slug)
    form = AddToWishlistForm()
    # 过滤当前用户的心愿单
    form.fields['wishlists'].queryset = Wishlist.objects.filter(user=request.user)
    
    if request.method == 'POST':
        form = AddToWishlistForm(request.POST)
        if form.is_valid():
            selected_wishlists = form.cleaned_data['wishlists']
            # 将商品添加到选中的所有心愿单
            for wishlist in selected_wishlists:
                wishlist.products.add(product)
            return render(request, 'product_detail.html', {'product': product, 'form': form, 'success': True})
    
    return render(request, 'product_detail.html', {'product': product, 'form': form})

3. 模板渲染表单

在商品页模板中渲染带复选框的心愿单选择菜单:

<form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">添加到选中的心愿单</button>
</form>
{% if success %}
<p>商品已成功添加到选中的心愿单!</p>
{% endif %}

关键说明

  • 表单定义时用Wishlist.objects.none()作为初始空查询集,避免加载无关数据;
  • 自定义字段的label_from_instance方法参数是Wishlist实例,需返回其title作为显示标签;
  • 视图必须用@login_required装饰,确保只有登录用户能访问该功能;
  • 提交表单后,遍历选中的心愿单,通过add()方法完成商品与心愿单的多对多关联。

内容的提问来源于stack exchange,提问作者Arnold Schwartzkopf

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 05:43:16