Skip to content

Commit

Permalink
Added DateField (#13)
Browse files Browse the repository at this point in the history
Added DateField
  • Loading branch information
M1ha-Shvn authored Jul 26, 2019
1 parent 3f332d3 commit 1463f09
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 15 deletions.
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

setup(
name='django-rest-form-fields',
version='1.2.8',
version='1.3.0',
packages=['django_rest_form_fields'],
package_dir={'': 'src'},
url='https://github.com/M1hacka/django-rest-form-fields',
Expand Down
34 changes: 29 additions & 5 deletions src/django_rest_form_fields/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@

import datetime
import json
import os
import re

import jsonschema
import os
import pytz
import re
import six
from django import forms
from django.core.exceptions import ValidationError
Expand All @@ -26,6 +25,7 @@ class BaseField(forms.Field):
All library fields are inherited from this base
Adds source
"""

def __init__(self, *args, **kwargs):
self.source = kwargs.pop('source', None)
super(BaseField, self).__init__(*args, **kwargs)
Expand Down Expand Up @@ -94,11 +94,12 @@ class RegexField(RestCharField):
"""
Wraps CharField to validate via regular expression
"""

def __init__(self, *args, **kwargs):
self.regex = kwargs.pop('regex', None)
self.flags = kwargs.pop('flags', 0)

assert self.regex is None or isinstance(self.regex, (six.string_types, get_pattern_type())),\
assert self.regex is None or isinstance(self.regex, (six.string_types, get_pattern_type())), \
'regex must be string if given'
assert isinstance(self.flags, int), 'flags must be integer'

Expand Down Expand Up @@ -223,6 +224,7 @@ class DateTimeField(RestCharField):
"""
Parses given string as datetime by given mask with datetime.datetime.strptime() method
"""
base_type = datetime.datetime

def __init__(self, *args, **kwargs):
"""
Expand All @@ -240,7 +242,7 @@ def __init__(self, *args, **kwargs):

def clean(self, value): # type: (Any) -> datetime.datetime
value = super(DateTimeField, self).clean(value)
if value is not None and not isinstance(value, datetime.datetime):
if value is not None and not isinstance(value, self.base_type):
try:
dt = datetime.datetime.strptime(value, self.mask)
except (ValueError, TypeError):
Expand All @@ -251,6 +253,28 @@ def clean(self, value): # type: (Any) -> datetime.datetime
return value


class DateField(DateTimeField):
"""
Parses month with datetime.datetime.strptime() method. Default format is %Y-%m.
Returns datetime.date with first day of month.
"""
base_type = datetime.date

def __init__(self, *args, **kwargs):
"""
Initializes field
:param args: Positional arguments
:param mask: Mask to parse month string with datetime.datetime.strptime() method
:param kwargs: Named arguments
"""
mask = kwargs.pop("mask", "%Y-%m-%d")
super(DateField, self).__init__(*args, mask=mask, **kwargs)

def clean(self, value): # type (Any) -> datetime.date
value = super(DateField, self).clean(value)
return value.date() if isinstance(value, datetime.datetime) else value


class MonthField(DateTimeField):
"""
Parses month with datetime.datetime.strptime() method. Default format is %Y-%m.
Expand Down
46 changes: 37 additions & 9 deletions tests/test_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,20 @@
import json
import random
import re
import six
import uuid

from django.core.exceptions import ValidationError
from django.core.validators import BaseValidator
from django.utils import timezone
from django.utils.timezone import utc
from io import BytesIO
from unittest import TestCase

import six
from django.core.exceptions import ValidationError
from django.utils.timezone import utc

from django_rest_form_fields.compatibility import to_timestamp
from django_rest_form_fields.fields import RestBooleanField, LowerCaseEmailField, TimestampField, DateUnitField, \
ColorField, IdArrayField, IdSetField, TruncatedCharField, JsonField, ArrayField, UrlField, RestCharField, \
RestChoiceField, RestIntegerField, RegexField, UUIDField, DateTimeField, MonthField, FileField, RestFloatField
RestChoiceField, RestIntegerField, RegexField, UUIDField, DateTimeField, MonthField, FileField, RestFloatField, \
DateField


class TestErrorValidator(BaseValidator):
Expand Down Expand Up @@ -463,6 +462,35 @@ def test_empty_value_validators(self):
f.clean('')


class DateFieldTest(TestCase):
def test_today(self):
today = datetime.date.today()
f = DateField()
res = f.clean(today.isoformat())
self.assertEqual(today, res)

def test_initial(self):
today = datetime.date.today()
f = DateField(initial=today, required=False)
res = f.clean(None)
self.assertEqual(today, res)

def test_required(self):
f = DateField(required=False)
self.assertEqual(None, f.clean(None))

f = DateField()
with self.assertRaises(ValidationError):
f.clean(None)

def test_empty_value_validators(self):
# By default django ignores skips run_validators methods, if value is in empty_values
# It's not correct for REST, as empty value is not equal to None value now
f = DateField(validators=[TestErrorValidator(0)])
with self.assertRaises(ValidationError):
f.clean('')


class MonthFieldTest(TestCase):
def test_now(self):
now = timezone.now().replace(microsecond=0)
Expand Down Expand Up @@ -879,10 +907,10 @@ def test_file_size(self):

test_file = self._get_test_file('pdf')

f = FileField(max_size=2*1024*1024)
f = FileField(max_size=2 * 1024 * 1024)
self.assertEqual(test_file, f.clean(test_file))

test_file.size = 1*1024*1024
test_file.size = 1 * 1024 * 1024
self.assertEqual(test_file, f.clean(test_file))

test_file.size = 2 * 1024 * 1024 - 1
Expand All @@ -906,4 +934,4 @@ def test_empty_value_validators(self):
# It's not correct for REST, as empty value is not equal to None value now
f = FileField(validators=[TestErrorValidator(0)])
with self.assertRaises(ValidationError):
f.clean('')
f.clean('')

0 comments on commit 1463f09

Please sign in to comment.