Skip to content

Commit

Permalink
Infer ChoiceField type from model field when in ModelSerializer
Browse files Browse the repository at this point in the history
Fixes part of issue #69
  • Loading branch information
axnsan12 committed Feb 26, 2018
1 parent 3f7ad62 commit ee46f59
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 13 deletions.
6 changes: 3 additions & 3 deletions .idea/drf-yasg.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,17 @@ Changelog
#########


*********
**1.4.4**
*********

*Release date: Feb 26, 2018*

- **IMPROVED:** ``type`` for ``ChoiceField`` generated by a ``ModelSerializer`` from a model field with ``choices=...``
will now be set according to the associated model field (:issue:`69`)
- **FIXED:** ``lookup_field`` and ``lookup_value_regex`` on the same ``ViewSet`` will no longer trigger an exception
(:issue:`68`)

*********
**1.4.3**
*********
Expand Down
29 changes: 20 additions & 9 deletions src/drf_yasg/inspectors/field.py
Original file line number Diff line number Diff line change
Expand Up @@ -397,16 +397,27 @@ class ChoiceFieldInspector(FieldInspector):
def field_to_swagger_object(self, field, swagger_object_type, use_references, **kwargs):
SwaggerType, ChildSwaggerType = self._get_partial_types(field, swagger_object_type, use_references, **kwargs)

if isinstance(field, serializers.MultipleChoiceField):
return SwaggerType(
type=openapi.TYPE_ARRAY,
items=ChildSwaggerType(
type=openapi.TYPE_STRING,
enum=list(field.choices.keys())
if isinstance(field, serializers.ChoiceField):
enum_type = openapi.TYPE_STRING

# for ModelSerializer, try to infer the type from the associated model field
serializer = get_parent_serializer(field)
if isinstance(serializer, serializers.ModelSerializer):
model = getattr(getattr(serializer, 'Meta'), 'model')
model_field = get_model_field(model, field.source)
if model_field:
enum_type = get_basic_type_info(model_field).get('type', enum_type)

if isinstance(field, serializers.MultipleChoiceField):
return SwaggerType(
type=openapi.TYPE_ARRAY,
items=ChildSwaggerType(
type=enum_type,
enum=list(field.choices.keys())
)
)
)
elif isinstance(field, serializers.ChoiceField):
return SwaggerType(type=openapi.TYPE_STRING, enum=list(field.choices.keys()))

return SwaggerType(type=enum_type, enum=list(field.choices.keys()))

return NotHandled

Expand Down
18 changes: 18 additions & 0 deletions testproj/articles/migrations/0002_article_article_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 2.0.1 on 2018-02-26 18:32

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('articles', '0001_initial'),
]

operations = [
migrations.AddField(
model_name='article',
name='article_type',
field=models.PositiveSmallIntegerField(choices=[(1, 'first'), (2, 'second'), (3, 'third'), (7, 'seven'), (8, 'eight')], help_text='IntegerField declared on model with choices=(...) and exposed via ModelSerializer', null=True),
),
]
4 changes: 4 additions & 0 deletions testproj/articles/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,9 @@ class Article(models.Model):
date_created = models.DateTimeField(auto_now_add=True)
date_modified = models.DateTimeField(auto_now=True)
author = models.ForeignKey('auth.User', related_name='articles', on_delete=models.CASCADE)
article_type = models.PositiveSmallIntegerField(
help_text="IntegerField declared on model with choices=(...) and exposed via ModelSerializer",
choices=((1, "first"), (2, "second"), (3, "third"), (7, "seven"), (8, "eight")), null=True
)

cover = models.ImageField(upload_to='article/original/', blank=True)
2 changes: 1 addition & 1 deletion testproj/articles/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = ('title', 'author', 'body', 'slug', 'date_created', 'date_modified',
'references', 'uuid', 'cover', 'cover_name')
'references', 'uuid', 'cover', 'cover_name', 'article_type')
read_only_fields = ('date_created', 'date_modified',
'references', 'uuid', 'cover_name')
lookup_field = 'slug'
Expand Down
10 changes: 10 additions & 0 deletions tests/reference.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,16 @@ definitions:
cover_name:
type: string
readOnly: true
article_type:
description: IntegerField declared on model with choices=(...) and exposed
via ModelSerializer
type: integer
enum:
- 1
- 2
- 3
- 7
- 8
Project:
required:
- projectName
Expand Down

0 comments on commit ee46f59

Please sign in to comment.