Python Django createview创建没有外键的额外实例

Python Django createview创建没有外键的额外实例,python,django,django-models,django-forms,Python,Django,Django Models,Django Forms,我正在使用Django createview在拍卖网站中创建出价项目。createview将创建新对象,但它会创建一个没有相应外键的额外对象实例。我使用@staticmethod来确定提交的出价是否确实是相关列表中创建的最高出价。如果你能指出我做错了什么,请提前谢谢你 models.py class Bid(TimeStampMixin): """model representing bid obj""" auction

我正在使用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}."
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
显示不带外键的额外bid对象的DB表


删除
返回super().form\u valid(form)

这行代码将从继承的类调用form_valid,该类将保存对象-这是创建的没有外键的额外对象


相反,您会希望返回某种http响应(例如,render\u to\u响应、重定向等)。

非常有效,谢谢。只是想澄清一下super().form\u valid(form)会调用form\u valid两次,创建额外的对象吗?抱歉,我是python中oop的新手,我正在尝试更好地理解。我可以尝试解释:您的视图继承自CreateView,CreateView中有一个form\u有效函数将运行
form.save()
,这将基于表单中的值创建对象-这是CreateView的默认行为。您最终创建了两个对象,因为您在表单中调用Bid.high\u Bid\u valid(最终创建了一个Bid对象),然后通过调用创建另一个Bid对象的
super.form\u valid(form)
调用默认的CreateView行为。
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