我正在使用Django createview在拍卖网站中创建出价项目。 createview将创建新对象,但会创建一个没有相应外键的额外对象实例。我正在使用@staticmethod来确定提交的出价是否确实是然后在相关清单中创建的最高出价。如果您能指出即时消息做错了什么,请先谢谢您。
models.py
class Bid(TimeStampMixin):
"""model representing bid obj"""
auction = models.ForeignKey(
Listing,
on_delete=models.SET_NULL,
related_name='offer',
null=True)
bidder = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.SET_NULL,
null=True,
related_name='bid_user')
amount = models.PositiveIntegerField()
objects = BidQuerySet.as_manager()
def __str__(self):
return f"{self.amount} in Listing No: {self.auction.id}"
class Meta:
ordering = ['amount']
@staticmethod
def high_bid(auction, bidder, bid_amount):
"""util method to ascertain highest bid in auction then create in related auction obj
:param auction---listing being bid on, bid__auction
:param bidder---user bidding
:param amount--- current highest bid
"""
###error checks, is auction running? is current bid less than start bid? etc
if bid_amount < auction.start_bid:
return
if (auction.highest_offer and bid_amount < auction.highest_offer.amount):
return
if bidder.id is auction.user.id:
raise PermissionDenied
##after checks create highest bid object in listing model
new_high_bid = Bid.objects.create(
auction= auction,
bidder = bidder,
amount = bid_amount
)
auction.highest_offer = new_high_bid
auction.save()
class Listing(TimeStampMixin):
user = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name="seller")
product = models.ForeignKey(
Product,
on_delete=models.CASCADE,
related_name="item")
start_bid = models.PositiveIntegerField(
default=0)
date_end = models.DateTimeField()
duration = models.ForeignKey(
Duration,
on_delete=models.SET_NULL,
null=True,
blank=True,
)
###static method in Bid model creates this
highest_offer = models.ForeignKey(
'Bid',
related_name = 'highest_bid',
on_delete = models.SET_NULL,
null = True,
blank = True,
)
def __str__(self):
return f"Listing for {self.product} by {self.user}."
views.py
class BidCreateView(LoginRequiredMixin, CreateView):
"""View to create auction bid"""
model = Bid
form_class = BidForm
template_name = "auction/auction_detail.html"
##define url redirected to when form is valid
def get_success_url(self):
return reverse ('detail', kwargs = { 'pk' : self.auction.pk })
###get context data to be passed to view
def get_context_data(self, **kwargs):
bidder = self.request.user
###call parent class to init
c = super().get_context_data(**kwargs)
c["auction"] = self.auction
###check if user is bidding on own item
if bidder.id is self.auction.user.id:
c["form"] = None
return c
###get_form_kwargs() method to supply user and listing during form creation
def get_form_kwargs(self):
###call parent class
kwargs = super().get_form_kwargs()
###extrack PK from kwargs so we can query for related listing obj
pk_ = self.kwargs.get('pk')
auction = Listing.objects.get(pk = pk_)
kwargs["auction"] = auction
self.auction = auction
print(kwargs)
return kwargs
def form_invalid(self, form):
return super().form_invalid(form)
def form_valid(self, form):
bid_amount = form.cleaned_data["amount"]
try:
###use transaction.atomic to tie this method with a succesful form submission
with transaction.atomic():
Bid.high_bid(
self.auction,
self.request.user,
bid_amount
)
except IntegrityError:
messages.error(self.request, "An unexpected error has occured")
messages.success(self.request, "Bid submitted successfully!")
return super().form_valid(form)
forms.py
class BidForm(forms.ModelForm):
class Meta:
model = Bid
fields = [
'amount',
]
widgets = {
'amount' : forms.NumberInput(attrs={'class' : 'form-control'}),
}
def __init__(self, *args, **kwargs):
"""override __init__ pop related auction from kwargs"""
self.auction = kwargs.pop("auction", None)
##call super with related obj
super().__init__(*args, **kwargs)
##clean data/validate, ensuring bid is larger than highest bid and starting bid
def clean_amount(self):
amount = self.cleaned_data["amount"]
##check if less than starting bid
if self.auction.start_bid > amount:
raise ValidationError(_('Bid is less than starting bid'))
if (self.auction.highest_offer.amount >= amount):
raise ValidationError(_('Bid is less than current highest bid'))
return amount
显示不带外键的额外出价对象的数据库表
答案 0 :(得分:0)
从form_valid删除return super().form_valid(form)
行。
这行代码将从继承的类中调用form_valid,该类将保存对象-这是没有外键创建的额外对象。
相反,您将需要返回某种http响应(例如render_to_response,重定向等)。