我目前正在Django项目中工作,该项目定义了一个自定义DateTimeField
,如下所示(dashboard/forms/fields
):
import pytz
from datetime import date, datetime
from django import forms
from django.core.exceptions import ValidationError
from dashboard.forms.widgets import DateTimeWidget
class DateTimeField(forms.MultiValueField):
widget = DateTimeWidget
DATE_FORMAT = '%B %d, %Y'
TIME_FORMAT = '%I:%M %p'
DATETIME_FORMAT = f'{DATE_FORMAT} {TIME_FORMAT}'
def __init__(self, timezone_choices=None, timezone=None, **kwargs):
fields = (forms.CharField(), forms.CharField(), forms.CharField())
super().__init__(fields=fields, **kwargs)
self.timezone_choices = timezone_choices
self.timezone = timezone
@property
def timezone_choices(self):
return self._timezone_choices
@timezone_choices.setter
def timezone_choices(self, value):
self._timezone_choices = self.widget.timezone_choices = value
@property
def timezone(self):
return self._timezone
@timezone.setter
def timezone(self, value):
self._timezone = self.widget.timezone = value
def compress(self, data_list):
try:
date, time, zone = data_list
tz = pytz.timezone(zone)
dt = datetime.strptime(f'{date} {time}', self.DATETIME_FORMAT)
return tz.localize(dt)
except ValueError:
return None
此字段以SessionForm
形式使用,如下所示:
class SessionForm(forms.ModelForm):
class Meta:
model = Session
fields = [
'scheduled_for',
]
scheduled_for = DateTimeField(
required=False,
timezone_choices=Family.TIMEZONE_CHOICES
)
此表单包含以下clean()
方法,我想测试一下:
def clean(self):
cleaned_data = super().clean()
status = cleaned_data.get('status')
location = cleaned_data.get('location')
if status in [Session.SCHEDULED, Session.SCHEDULED_CALENDARED] and not cleaned_data.get('scheduled_for'):
self.add_error(
'scheduled_for',
f"This field is required if the status is '{Session.SCHEDULED}' or '{Session.SCHEDULED_CALENDARED}'.")
return cleaned_data
为此,我尝试编写以下测试:
class SessionCreateTest(TestCase):
def test_scheduled_session_with_scheduled_time_and_expert_and_location_is_valid(self):
scheduled_time = dateutil.parser.parse("5 January 2019 at 1:30 PM")
date = scheduled_time.strftime(DateTimeField.DATE_FORMAT)
time = scheduled_time.strftime(DateTimeField.TIME_FORMAT)
zone = pytz.country_timezones('US')[20] # 'America/Los_Angeles'
scheduled_for = (date, time, zone)
self.data.update(
status=Session.SCHEDULED,
scheduled_for=scheduled_for,
expert=ExpertFactory().id,
location=Session.AT_HOME)
form = SessionForm(data=self.data)
import ipdb; ipdb.set_trace()
不幸的是,当我进入调试器时,我发现表单仍有错误:
> /Users/kurtpeek/Documents/Dev/lucy2/lucy-web/dashboard/tests/test_sessions.py(666)test_scheduled_session_with_scheduled_time_and_expert_and_location_is_valid()
665 import ipdb; ipdb.set_trace()
--> 666 self.assertTrue(form.is_valid())
667
ipdb> form.errors
{'scheduled_for': ["This field is required if the status is 'Scheduled' or 'Scheduled & Calendared'."]}
但是,如果我将此字段的输入传递给字段的compress()
方法,则可能会将其解析为'正确地:
ipdb> field = DateTimeField()
ipdb> field.compress(scheduled_for)
datetime.datetime(2019, 1, 5, 13, 30, tzinfo=<DstTzInfo 'America/Los_Angeles' PST-1 day, 16:00:00 STD>)
我不明白为什么这个测试没有通过?我怎么能打破这个呢?&#39;进一步?
答案 0 :(得分:0)
我建议您将断点放在表单的 clean 方法内。检查 cleaned_data 字典中的 scheduled_for 的结构。它应该为您提供测试所需的答案。