Django拍卖应用创建Listing时遇TypeError:字段'id'需数字却获内置函数id
Django拍卖应用创建Listing时TypeError问题排查与修复
问题现象
开发基于Django的拍卖应用时,创建新Listing触发TypeError:
Type Error at /create "Field 'id' expected a number but got
"
错误指向views.py第81行代码:
viewListing = Listing.objects.get(pk=id)
期望创建完成后重定向到包含新Listing的index视图,需修复代码使其正常运行。
相关代码片段
views.py 创建视图
@login_required def create(request): if request.method == "GET": categories = Category.objects.all() return render(request, "auctions/create.html", { "categories": categories }) else: title = request.POST["title"] description = request.POST["description"] image = request.POST["image"] price = request.POST["price"] category = request.POST["category"] categories = Category.objects.get(categoryType=category) sessionUser = request.user viewListing = Listing.objects.get(pk=id) viewListing.watchlist.add(sessionUser) bid = Bid(bid=float(price), user=sessionUser) bid.save() listing = Listing( title=title, description=description, image=image, price=bid, category=categories, owner=sessionUser ) listing.save() return HttpResponseRedirect(reverse(index))
urls.py 路由配置
from django.urls import path from . import views urlpatterns = [ path("", views.index, name="index"), path("login", views.login_view, name="login"), path("logout", views.logout_view, name="logout"), path("register", views.register, name="register"), path("create", views.create, name="create"), path("categories/", views.categories, name="categories"), path("filter/<int:category_id>", views.filter, name="filter"), path("listing/<int:id>", views.listing, name="listing"), path("remove/<int:id>", views.remove, name="remove"), path("add/<int:id>", views.add, name="add"), path("watchlist", views.watchlist, name="watchlist"), path("comment/<int:id>", views.comment, name="comment"), path("bid/<int:id>", views.bid, name="bid"), path("close/<int:id>", views.close, name="close") ]
models.py 核心模型
from django.contrib.auth.models import AbstractUser from django.db import models class User(AbstractUser): pass class Bid(models.Model): bid = models.DecimalField(decimal_places=2, max_digits=7) user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="userBid", null=True, blank=True) def __str__(self): return f"{self.bid}" class Listing(models.Model): title = models.CharField(max_length=64) description = models.CharField(max_length=500) price = models.ForeignKey(Bid, on_delete=models.CASCADE, related_name="currentbid", null=True, blank=True) active = models.BooleanField(default=True) owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name="user", null=True, blank=True) image = models.CharField(max_length=900) category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name="category", null=True, blank=True) watchlist = models.ManyToManyField(User, null=True, blank=True, related_name="watchlist") def __str__(self): return self.title class Comment(models.Model): author = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True, related_name="author") listing = models.ForeignKey(Listing, on_delete=models.CASCADE, blank=True, null=True, related_name="comment") message = models.CharField(max_length=500) def __str__(self): return f"{self.author} comment on {self.listing}"
错误原因分析
- 变量名冲突:代码中使用的
id是Python内置函数,并非新创建Listing的ID,此时新Listing还未生成,Listing.objects.get(pk=id)自然无法获取到有效对象,触发类型错误。 - 逻辑顺序错误:尝试先获取不存在的Listing,再创建Listing,违背了数据生成的先后逻辑。
- 重定向参数错误:
reverse(index)直接传入视图函数,不符合Djangoreverse函数的使用规范,应传入路由名称字符串。 - 价格类型不匹配:用
float(price)转换价格,与Bid模型中的DecimalField类型不匹配,易引发精度问题。
修复后的代码(views.py)
from decimal import Decimal # 需要导入Decimal @login_required def create(request): if request.method == "GET": categories = Category.objects.all() return render(request, "auctions/create.html", { "categories": categories }) else: title = request.POST["title"] description = request.POST["description"] image = request.POST["image"] price = request.POST["price"] category = request.POST["category"] categories = Category.objects.get(categoryType=category) sessionUser = request.user # 用Decimal处理价格,匹配模型字段类型 bid = Bid(bid=Decimal(price), user=sessionUser) bid.save() # 先创建并保存Listing对象 listing = Listing( title=title, description=description, image=image, price=bid, category=categories, owner=sessionUser ) listing.save() # 若需将创建者加入该Listing的关注列表,执行此操作 listing.watchlist.add(sessionUser) # 用路由名称执行重定向 return HttpResponseRedirect(reverse("index"))
关键修复点说明
- 移除错误的
Listing.objects.get(pk=id)及后续无效操作,改为创建Listing后再处理关注列表(如果业务需要)。 - 替换
float(price)为Decimal(price),确保价格类型与模型字段一致,避免精度丢失。 - 重定向时使用
reverse("index"),对应urls.py中name="index"的路由配置,保证跳转正确性。
内容的提问来源于stack exchange,提问作者GStreet71
相关产品推荐
相关产品推荐

