Django开发拍卖站点:如何自动将表单创建者传入表单并保存?
解决方案
错误原因
你遇到的BaseModelForm.__init__() got an unexpected keyword argument 'user'错误,核心是视图中表单初始化的逻辑顺序有误,且将user字段暴露在表单中存在安全隐患——前端可篡改隐藏字段。
最优修复方案
我们可以完全避开在表单中处理user字段,直接在视图里通过当前登录用户设置创建者信息,步骤如下:
1. 修改表单(forms.py)
移除表单中所有与user相关的配置,无需将user字段加入表单:
class CreateListing(forms.ModelForm): category = forms.ModelChoiceField(queryset=Category.objects.all(), empty_label="No category") class Meta: model = AuctionListing fields = ('title', 'description', 'starting_bid', 'url', 'category') widgets = { 'title': forms.TextInput(attrs={'placeholder':'Write your listing title here...'}), 'description': forms.Textarea(attrs={'placeholder':'Write your comment here...', 'rows':3}), }
2. 修改视图函数(views.py)
表单验证通过后,用commit=False先创建实例但不保存到数据库,手动设置user为当前登录用户后再完成保存:
def create_listing(request): if request.method == "POST": form = CreateListing(request.POST) if form.is_valid(): # 创建实例但暂不提交到数据库 listing = form.save(commit=False) # 设置创建者为当前登录用户 listing.user = request.user listing.save() return HttpResponseRedirect(reverse("index")) return render(request, "auctions/create_listing.html", {"form": form}) # GET请求时初始化空表单 form = CreateListing() return render(request, "auctions/create_listing.html", {"form": form})
3. 修改模板(auctions/create_listing.html)
移除模板中的{{ form.user }}字段,因为表单已不再包含该字段:
<h1> Create new listing </h1> <form action="" method="POST"> {% csrf_token %} <label>Name*</label> <br> {{ form.title }} <br> <label >Description*</label> <br> {{ form.description }} <br> <label >Starting bid*</label> <br> {{ form.starting_bid }} <br> <label > Image url (optional) </label> <br> {{ form.url }} <br> <label > Category (optional) </label> <br> {{ form.category }} <br> <button type="submit" class="btn btn-primary save">Create your listing</button> </form>
原方案的快速修复(不推荐)
如果坚持保留原表单写法,只需调整视图中表单初始化的顺序,确保仅在对应请求方法中正确传递参数:
def create_listing(request): if request.method == "POST": form = CreateListing(request.POST, user=request.user) if form.is_valid(): form.save() return HttpResponseRedirect(reverse("index")) return render(request, "auctions/create_listing.html", {"form": form}) # GET请求时初始化表单并传递user参数 form = CreateListing(user=request.user) return render(request, "auctions/create_listing.html", {"form": form})
但这种方式仍存在前端篡改隐藏字段的风险,因此优先推荐第一种方案。
内容的提问来源于stack exchange,提问作者Annelotte
相关产品推荐
相关产品推荐

