Modelform和模型验证一起播放



我有以下模型:

class Advertisement(models.Model):
    slug = models.UUIDField(default=uuid4, blank=True, editable=False)
    advertiser = models.ForeignKey(Advertiser)
    position = models.SmallIntegerField(choices=POSITION_CHOICES)
    share_type = models.CharField(max_length=80)
    country = CountryField(countries=MyCountries, default='DE')
    postal_code = models.CharField(max_length=8, null=True, blank=True)
    date_from = models.DateField()
    date_to = models.DateField()

基于广告商,位置,类型国家/地区和邮政代码,此存储具有范围date_from and date_to。

的副本
advertiser, position, share_type, country and postal_code

来自请求,并在

中获取
class CreateAdvertisment(LoginRequiredMixin, CreateView):
    # Some usefull stuff
    def dispatch(self, request, *args, **kwargs):
        self.advertiser = Advertiser.objects.get(user=self.request.user)
        self.share_type = self.kwargs.get('share_type', None)
        self.country = self.kwargs.get('country', None)
        self.postal_code = self.kwargs.get('postal_code', None)
        self.position = int(self.kwargs.get('position', None))
        self.position_verbose = verbose_position(self.position)
        ret = super(CreateAdvertisment, self).dispatch(request, *args, **kwargs)
        return ret

无需检查date_from,date_to的任何验证。我可以简单地做

def form_valid(self, form):
    form.instance.advertiser = self.advertiser
    form.instance.share_type = self.share_type
    form.instance.country = self.country
    form.instance.postal_code = self.postal_code
    form.instance.position = self.position
    ret = super(CreateAdvertisment, self).form_valid(form)
    return ret

我完成了。不幸的是,我不能这样做,因为我确实必须检查广告的有效时间范围,以避免同时预订。我在模型中使用以下方式进行此操作:

def clean(self):
    ret = super(Advertisement, self).clean()
    print ("country [%s] position [%s] share_type [%s] postal_code [%s]" % (self.country,
           self.position, self.share_type, self.postal_code))
    if self.between_conflict():
        raise ValidationError("Blocks between timeframe")
    elif self.end_conflict():
        raise ValidationError("End occupied")
    elif self.during_conflict():
        raise ValidationError("Time Frame complete occupied")
    elif self.start_conflict():
        raise ValidationError("Start Occupied")
    return ret
def start_conflict(self):
    start_conflict = Advertisement.objects.filter(country=self.country,
                                                  position=self.position,
                                                  share_type=self.share_type,
                                                  postal_code=self.postal_code).filter(
        date_from__range=(self.date_from, self.date_to))
    return start_conflict

这效果很好,我在给定时期内过滤了任何冲突。问题是,我没有实例变量在view.form_valid((和model.clean((中设置为实例变量。

我在这里确实有鸡蛋问题。我正在考虑将请求参数设置为

中的Kwargs表单
def get_form_kwargs(self, **kwargs):
    kwargs = super(CreateAdvertisment, self).get_form_kwargs()
    kwargs['advertiser'] = self.advertiser
    kwargs['position'] = self.position
    ....

然后以形式将它们放入form实例中。 init ((

def __init__(self, *args, **kwargs):
    advertiser = kwargs.pop('advertiser')
    position = kwargs.pop('position')
    # .. and so on
    super(AdvertismentCreateForm, self).__init__(*args, **kwargs)

由于某些原因,我认为这不是很好的Pythonic。有人有更好的主意吗?我将发布解决方案。

我认为覆盖get_form_kwargs还可以。如果所有夸尔格斯都是实例属性,那么我将在get_form_kwargs方法中更新该实例。那么,您不必覆盖表格的__init__,也不应该在form_valid方法中更新实例的属性。

def get_form_kwargs(self, **kwargs):
    kwargs = super(CreateAdvertisment, self).get_form_kwargs()
    if kwargs['instance'] is None:
        kwargs['instance'] = Advertisement()
    kwargs['instance'].advertiser = self.advertiser
    ...
    return kwargs

在模型的干净方法中,您现在可以访问self.advertiser

alasdairs提案效果很好,我现在有以下内容:

def get_form_kwargs(self, **kwargs):
    kwargs = super(CreateAdvertisment, self).get_form_kwargs()
    if kwargs['instance'] is None:
        kwargs['instance'] = Advertisement()
    kwargs['instance'].advertiser = self.advertiser
    kwargs['instance'].share_type = self.share_type
    kwargs['instance'].country = self.country
    kwargs['instance'].postal_code = self.postal_code
    kwargs['instance'].position = self.position
    return kwargs
def form_valid(self, form):
    ret = super(CreateAdvertisment, self).form_valid(form)
    return ret

当然,不再需要覆盖form_valid。我刚刚在这里包括在内,以显示我们不再设置实例字段,因为这已经在get_form_kwargs((已经完成了

最新更新