Django开发eBay类拍卖网站 创建Bid关联Listing时报id期望数字错误
报错原因及解决方案
核心问题梳理
- 模型字段默认值类型不匹配
你在Bid模型的listing外键字段、Listing模型的category外键字段都设置了default="",外键字段本质存储的是关联表的主键ID(数字类型),空字符串是字符串类型,赋值时就会触发「期望得到数字但拿到空字符串」的报错。 - 外键关联操作方法错误
ForeignKey是单对多关联,不是多对多ManyToManyField,不能使用.add()方法关联对象,你写的b.listing.add(l.id)是完全错误的用法。 - 额外代码隐患
Bid模型的__str__方法中调用了self.slug,但你的Bid模型根本没有定义slug字段,后续运行到相关逻辑时也会触发属性不存在的报错。
修正后代码
models.py
class Listing(models.Model): title = models.CharField(max_length=200) description = models.CharField(max_length=500) url = models.URLField() author = models.ForeignKey('User', on_delete=models.CASCADE, related_name='listings') # 移除错误的空字符串默认值,外键默认值不能为字符串类型 category = models.ForeignKey('Category', on_delete=models.CASCADE, related_name='listings') def __str__(self): return f'{self.id}: {self.title}' class Bid(models.Model): price = models.DecimalField(decimal_places=2, max_digits=10) bid_count = models.IntegerField(default=0) # 直接设置默认值更合理 # 移除错误的空字符串默认值 listing = models.ForeignKey('Listing', on_delete=models.CASCADE, related_name='bids') def __str__(self): # 替换不存在的slug字段,避免后续报错 return f'Bid {self.id} for {self.listing.title} ({self.price})'
views.py
def newListing(request): try: if request.method == "POST": newListingForm = NewListingForm(request.POST) if newListingForm.is_valid(): title = newListingForm.cleaned_data['title'] description = newListingForm.cleaned_data['description'] url = newListingForm.cleaned_data['url'] bid = newListingForm.cleaned_data['bid'] # ModelChoiceField的cleaned_data直接返回模型实例,不需要额外查询 category = newListingForm.cleaned_data['category'] current_user = request.user l = Listing(title=title, description=description, url=url, author=current_user, category=category) l.save() # 直接在创建Bid时传入关联的Listing实例,不需要调用add方法 Bid.objects.create(price=bid, bid_count=0, listing=l) return HttpResponseRedirect(reverse("index")) else: newListingForm = NewListingForm() return render(request, "auctions/newListing.html", { 'form': newListingForm }) except Exception as exc: exc_type, exc_obj, exc_tb = sys.exc_info() fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] print(exc_type, exc_obj, fname, exc_tb.tb_lineno) newListingForm = NewListingForm() return render(request, 'auctions/newListing.html', { 'form': newListingForm })
内容的提问来源于stack exchange,提问作者amiller_lite
相关产品推荐
相关产品推荐

