Skip to content

Commit

Permalink
Process EnumFields even if their are not marked as required 🧈
Browse files Browse the repository at this point in the history
  • Loading branch information
Sibyx committed Dec 19, 2019
1 parent c09073a commit a02e869
Show file tree
Hide file tree
Showing 9 changed files with 69 additions and 12 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.5.1 : 19.12.2019

- **Fix**: Process `EnumField` even if it's not marked as required

## 0.5.0 : 16.12.2019

- **Change**: Use native `django.form.fields` if possible
Expand Down
22 changes: 17 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ python setup.py install
```json
{
"title": "Unknown Pleasures",
"type": "vinyl",
"artist": {
"name": "Joy division",
"genres": [
Expand Down Expand Up @@ -79,11 +80,19 @@ python setup.py install
**DjangoRequestFormatter equivalent + validation**

```python
from django_request_formatter.fields import FieldList, FormField, FormFieldList, DictionaryField
from django_request_formatter.forms import Form
from enum import Enum

from django.core.exceptions import ValidationError
from django.forms import fields

from django_request_formatter.fields import FieldList, FormField, FormFieldList, DictionaryField, EnumField
from django_request_formatter.forms import Form


class AlbumType(Enum):
CD = 'cd'
VINYL = 'vinyl'


class ArtistForm(Form):
name = fields.CharField(required=True, max_length=100)
Expand All @@ -101,16 +110,19 @@ class AlbumForm(Form):
year = fields.IntegerField()
artist = FormField(form=ArtistForm)
songs = FormFieldList(form=SongForm)
type = EnumField(enum=AlbumType, required=True)
metadata = DictionaryField(fields.DateTimeField())

def clean_year(self):
if self.cleaned_data['year'] == 1992:
raise ValidationError("Year 1992 is forbidden!")
raise ValidationError("Year 1992 is forbidden!", 'forbidden-value')
return self.cleaned_data['year']

def clean(self):
if (self.cleaned_data['year'] == "1998") and (self.cleaned_data['artist'] == "Nirvana"):
raise ValidationError("Sounds like a bullshit")
if (self.cleaned_data['year'] == 1998) and (self.cleaned_data['artist']['name'] == "Nirvana"):
raise ValidationError("Sounds like a bullshit", code='time-traveling')
return self.cleaned_data


"""
Django view example
Expand Down
2 changes: 1 addition & 1 deletion django_request_formatter/__version__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '0.5.0'
__version__ = '0.5.1'
11 changes: 8 additions & 3 deletions django_request_formatter/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def __init__(self, field, **kwargs):

super().__init__(**kwargs)

def to_python(self, value):
def to_python(self, value) -> typing.List:
if not isinstance(value, list):
raise ValidationError(self.error_messages['not_list'], code='not_list')

Expand Down Expand Up @@ -53,6 +53,10 @@ def __init__(self, form: typing.Type, **kwargs):

super().__init__(**kwargs)

@property
def form(self):
return self._form

def to_python(self, value) -> dict:
form = self._form(value)
if form.is_valid():
Expand Down Expand Up @@ -99,12 +103,13 @@ def __init__(self, enum: typing.Type, **kwargs):

super().__init__(**kwargs)

def to_python(self, value):
if self.required and value is not None:
def to_python(self, value) -> typing.Union[typing.Type[Enum], None]:
if value is not None:
try:
return self.enum(value)
except ValueError:
raise ValidationError(f"Invalid enum value {value} passed to {type(self.enum)}")
return None


class DictionaryField(Field):
Expand Down
1 change: 1 addition & 0 deletions tests/data/invalid.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"title": "Unknown Pleasures",
"type": "vinyl",
"artist": {
"name": "Nirvana",
"genres": [
Expand Down
1 change: 1 addition & 0 deletions tests/data/valid.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"title": "Unknown Pleasures",
"type": "vinyl",
"artist": {
"name": "Joy Division",
"genres": [
Expand Down
3 changes: 2 additions & 1 deletion tests/test_valid.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from django.test import RequestFactory

from tests.testapp.forms import AlbumForm
from tests.testapp.forms import AlbumForm, AlbumType

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

Expand All @@ -12,6 +12,7 @@ def test_valid(rf: RequestFactory):
expected = {
'title': "Unknown Pleasures",
'year': 1979,
'type': AlbumType.VINYL,
'artist': {
'name': "Joy Division",
'genres': ['rock', 'punk'],
Expand Down
12 changes: 10 additions & 2 deletions tests/testapp/forms.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
from enum import Enum

from django.core.exceptions import ValidationError
from django.forms import fields

from django_request_formatter.fields import FieldList, FormField, FormFieldList, DictionaryField
from django_request_formatter.fields import FieldList, FormField, FormFieldList, DictionaryField, EnumField
from django_request_formatter.forms import Form


class AlbumType(Enum):
CD = 'cd'
VINYL = 'vinyl'


class ArtistForm(Form):
name = fields.CharField(required=True, max_length=100)
genres = FieldList(field=fields.CharField(max_length=30))
Expand All @@ -21,11 +28,12 @@ class AlbumForm(Form):
year = fields.IntegerField()
artist = FormField(form=ArtistForm)
songs = FormFieldList(form=SongForm)
type = EnumField(enum=AlbumType, required=True)
metadata = DictionaryField(fields.DateTimeField())

def clean_year(self):
if self.cleaned_data['year'] == 1992:
raise ValidationError("Year 1992 is forbidden!")
raise ValidationError("Year 1992 is forbidden!", 'forbidden-value')
return self.cleaned_data['year']

def clean(self):
Expand Down
25 changes: 25 additions & 0 deletions tests/testapp/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import datetime
from dataclasses import dataclass, field
from typing import List, Dict


@dataclass
class Artist:
name: str = ""
members: int = 0
genres: List[str] = field(default_factory=list)


@dataclass
class Song:
title: str = ""
duration: datetime.timedelta = None


@dataclass
class Album:
title: str = ""
year: int = 0
artist: Artist = Artist()
songs: List[Song] = field(default_factory=list)
metadata: Dict = field(default_factory=dict)

0 comments on commit a02e869

Please sign in to comment.