向Django ModelForm添加不在mod中的字段

2024-05-14 16:13:16 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个模型看起来像:

class MySchedule(models.Model):
  start_datetime=models.DateTimeField()
  name=models.CharField('Name',max_length=75)

随之而来的是它的模型:

class MyScheduleForm(forms.ModelForm):
  startdate=forms.DateField()
  starthour=forms.ChoiceField(choices=((6,"6am"),(7,"7am"),(8,"8am"),(9,"9am"),(10,"10am"),(11,"11am"),
      (12,"noon"),(13,"1pm"),(14,"2pm"),(15,"3pm"),(16,"4pm"),(17,"5pm"),
      (18,"6pm"
  startminute=forms.ChoiceField(choices=((0,":00"),(15,":15"),(30,":30"),(45,":45")))),(19,"7pm"),(20,"8pm"),(21,"9pm"),(22,"10pm"),(23,"11pm")))

  class Meta:
    model=MySchedule

  def clean(self):
    starttime=time(int(self.cleaned_data.get('starthour')),int(self.cleaned_data.get('startminute')))
    return self.cleaned_data

  try:
    self.instance.start_datetime=datetime.combine(self.cleaned_data.get("startdate"),starttime)

  except TypeError:
    raise forms.ValidationError("There's a problem with your start or end date")

基本上,我试图将模型中的DateTime字段分解为3个更容易使用的表单字段——日期选择器、一小时下拉列表和一分钟下拉列表。然后,一旦我得到了这三个输入,我就把它们重新组合成一个日期时间并保存到模型中。

几个问题:

1)这样做完全是错误的吗?我不想在模型中创建几个小时、几分钟等的字段,因为这些基本上只是中间数据,所以我想用一种方法将DateTime字段分解成子字段。

2)我遇到的困难是当startdate字段为空时——它似乎永远不会被检查为非空,而只是在程序期望日期而没有得到日期时,在稍后抛出一个TypeError。Django在哪里检查空白输入,并引发最终返回表单的错误?这是我的责任吗?如果是,我该怎么做,因为它不计算clean_startdate(),因为startdate不在模型中。

3)有没有更好的方法来继承遗产?也许在BetterScheduleForm中继承MyScheduleForm并在那里添加字段?我该怎么做?(我已经玩了一个多小时了,好像不明白)

谢谢!

[编辑:]关闭返回的自清理数据--在最初的复制/粘贴中丢失


Tags: 模型selfdatagetdatetimemodelsformsstart
3条回答

他说:我不认为这是错的,因为你有一些非常具体的事情要做:

  • 特定时间条目(中午,下午5点结束….)
  • 每分钟15分钟递增一次

2:Update:comment下面说默认情况下您的字段应该是required=True。是的,如果字段为空,那么您应该在表单中得到一个ValidationError

你能把你说的TypeError贴出来吗?它是否发生在clean()区之外?因为如果您没有像示例中那样从干净的函数返回cleaned_data,那么即使表单最初通过不引发任何ValidationErrors而签出,它也不会有任何数据可供使用。

无论如何,您可以探索每个字段验证的clean_方法。

def clean_startdate(self):  
    if not self.cleaned_data['startdate']:
            raise forms.ValidationError("Must enter a start date")

http://docs.djangoproject.com/en/dev/topics/forms/modelforms/#overriding-the-clean-method

他说:你能在这里澄清一下你想用遗产做什么吗?看起来您的字段定义非常特定于此表单,所以它就属于这里的MyScheduleForm。继承用于重新使用代码:)

如果您希望对多个DateTimeFields重复使用它,可以使用表单继承。您可以像现在一样定义一个ModelForm,对其进行子类化,并覆盖父级的Meta,如文档中所示,以便在多个模型上使用它: http://docs.djangoproject.com/en/dev/topics/forms/modelforms/#form-inheritance

我还想看看django如何执行SplitDateTimeWidget(检查源代码): http://docs.djangoproject.com/en/dev/ref/forms/widgets/#django.forms.SplitDateTimeWidget

还有一些其他的'第三方'分裂日期时间窗口小部件也值得一看在互联网上!

好吧,我想我明白了:

从Django 1.2开始,运行is_valid()将触发ModelForms上的模型验证。我假设在调用model clean()函数之前会检查字段是否有空值,所以clean函数不会检查空值或无类型。基本上,模型中的clean()看起来像:

def clean(self):
  if self.start_datetime >  datetime.now():
        raise ValidationError('Start date can\'t be in the future')

所以我想这基本上回答了我的问题。不过,我还有一个问题:

最好是在model clean()中检查空白值,还是有更好的方法?检查模型中的空白而不是模型表单中的空白似乎有些老套——表单字段上的验证是否应该标记必需字段上缺少的输入?

谢谢大家的帮助。

  1. 如果我是你,我会用customised Django-admin date/time widget(s)输入日期/时间条目。

  2. 关于表单验证,请确保传递与请求相关联的表单,以显示基于表单的错误。(下面的示例代码)

  3. 至于使用继承,对于这个用例来说这是一个过度的消耗,因为它不会有任何用途,最好保持简单。

示例代码:

if request.POST:
    form = MyScheduleForm(request.POST)
    if form.is_valid():
        # Specific stuff with the variables here
        pass
else:
    form = MyScheduleForm()

相关问题 更多 >

    热门问题