mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-07-23 06:29:58 +03:00
Merge b6841df16a
into 02b7196ad4
This commit is contained in:
commit
045239442a
|
@ -236,6 +236,8 @@ For example:
|
||||||
model = Account
|
model = Account
|
||||||
exclude = ('id',)
|
exclude = ('id',)
|
||||||
|
|
||||||
|
**Note**: All fields names in either `fields` or `exclude` must already be defined in the model or set explicitly, with the exception of `pk` which is a shortcut field to the actual primary key field of the model (by default Django sets this to `id` but can be overidden).
|
||||||
|
|
||||||
## Specifiying nested serialization
|
## Specifiying nested serialization
|
||||||
|
|
||||||
The default `ModelSerializer` uses primary keys for relationships, but you can also easily generate nested representations using the `depth` option:
|
The default `ModelSerializer` uses primary keys for relationships, but you can also easily generate nested representations using the `depth` option:
|
||||||
|
|
|
@ -201,7 +201,7 @@ Open the file `snippets/serializers.py` again, and edit the `SnippetSerializer`
|
||||||
class SnippetSerializer(serializers.ModelSerializer):
|
class SnippetSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Snippet
|
model = Snippet
|
||||||
fields = ('id', 'title', 'code', 'linenos', 'language', 'style')
|
fields = ('pk', 'title', 'code', 'linenos', 'language', 'style')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ Now that we've got some users to work with, we'd better add representations of t
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = User
|
model = User
|
||||||
fields = ('id', 'username', 'snippets')
|
fields = ('pk', 'username', 'snippets')
|
||||||
|
|
||||||
Because `'snippets'` is a *reverse* relationship on the User model, it will not be included by default when using the `ModelSerializer` class, so we've needed to add an explicit field for it.
|
Because `'snippets'` is a *reverse* relationship on the User model, it will not be included by default when using the `ModelSerializer` class, so we've needed to add an explicit field for it.
|
||||||
|
|
||||||
|
|
|
@ -130,22 +130,37 @@ class BaseSerializer(Field):
|
||||||
# Set up the field
|
# Set up the field
|
||||||
field.initialize(parent=self, field_name=key)
|
field.initialize(parent=self, field_name=key)
|
||||||
|
|
||||||
|
pk_field = None
|
||||||
|
|
||||||
# Add in the default fields
|
# Add in the default fields
|
||||||
fields = self.default_fields(nested)
|
fields = self.default_fields(nested)
|
||||||
for key, val in fields.items():
|
for key, val in fields.items():
|
||||||
if key not in ret:
|
if key not in ret:
|
||||||
ret[key] = val
|
ret[key] = val
|
||||||
|
try:
|
||||||
|
# Test if field was marked as pk_field
|
||||||
|
if getattr(val, 'is_pk_field'):
|
||||||
|
pk_field = key
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
# If 'fields' is specified, use those fields, in that order.
|
# If 'fields' is specified, use those fields, in that order.
|
||||||
if self.opts.fields:
|
if self.opts.fields:
|
||||||
new = SortedDict()
|
new = SortedDict()
|
||||||
for key in self.opts.fields:
|
for key in self.opts.fields:
|
||||||
|
if key == 'pk':
|
||||||
|
# 'pk' shortcut: use the primary key found
|
||||||
|
new[key] = ret[pk_field]
|
||||||
|
continue
|
||||||
new[key] = ret[key]
|
new[key] = ret[key]
|
||||||
ret = new
|
ret = new
|
||||||
|
|
||||||
# Remove anything in 'exclude'
|
# Remove anything in 'exclude'
|
||||||
if self.opts.exclude:
|
if self.opts.exclude:
|
||||||
for key in self.opts.exclude:
|
for key in self.opts.exclude:
|
||||||
|
if key == 'pk':
|
||||||
|
# 'pk' shortcut: remove the primary key found
|
||||||
|
ret.pop(pk_field)
|
||||||
ret.pop(key, None)
|
ret.pop(key, None)
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
@ -350,12 +365,11 @@ class ModelSerializer(Serializer):
|
||||||
fields += [field for field in opts.many_to_many if field.serialize]
|
fields += [field for field in opts.many_to_many if field.serialize]
|
||||||
|
|
||||||
ret = SortedDict()
|
ret = SortedDict()
|
||||||
is_pk = True # First field in the list is the pk
|
|
||||||
|
|
||||||
for model_field in fields:
|
for model_field in fields:
|
||||||
if is_pk:
|
if model_field.primary_key:
|
||||||
|
# Django requires models to have only one primary_key so this should be safe
|
||||||
field = self.get_pk_field(model_field)
|
field = self.get_pk_field(model_field)
|
||||||
is_pk = False
|
|
||||||
elif model_field.rel and nested:
|
elif model_field.rel and nested:
|
||||||
field = self.get_nested_field(model_field)
|
field = self.get_nested_field(model_field)
|
||||||
elif model_field.rel:
|
elif model_field.rel:
|
||||||
|
@ -375,7 +389,10 @@ class ModelSerializer(Serializer):
|
||||||
"""
|
"""
|
||||||
Returns a default instance of the pk field.
|
Returns a default instance of the pk field.
|
||||||
"""
|
"""
|
||||||
return Field()
|
field = Field()
|
||||||
|
# Mark field as primary key
|
||||||
|
field.is_pk_field = True
|
||||||
|
return field
|
||||||
|
|
||||||
def get_nested_field(self, model_field):
|
def get_nested_field(self, model_field):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -50,7 +50,7 @@ class PersonSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Person
|
model = Person
|
||||||
fields = ('name', 'age', 'info')
|
fields = ('pk', 'name', 'age', 'info')
|
||||||
|
|
||||||
|
|
||||||
class BasicTests(TestCase):
|
class BasicTests(TestCase):
|
||||||
|
@ -112,7 +112,7 @@ class BasicTests(TestCase):
|
||||||
"""
|
"""
|
||||||
serializer = PersonSerializer(self.person)
|
serializer = PersonSerializer(self.person)
|
||||||
self.assertEquals(set(serializer.data.keys()),
|
self.assertEquals(set(serializer.data.keys()),
|
||||||
set(['name', 'age', 'info']))
|
set(['pk', 'name', 'age', 'info']))
|
||||||
|
|
||||||
def test_field_with_dictionary(self):
|
def test_field_with_dictionary(self):
|
||||||
""" Make sure that dictionaries from fields are left intact
|
""" Make sure that dictionaries from fields are left intact
|
||||||
|
@ -121,6 +121,14 @@ class BasicTests(TestCase):
|
||||||
expected = self.person_data
|
expected = self.person_data
|
||||||
self.assertEquals(serializer.data['info'], expected)
|
self.assertEquals(serializer.data['info'], expected)
|
||||||
|
|
||||||
|
def test_pk_field_exists(self):
|
||||||
|
"""
|
||||||
|
Verify the `pk` shortcut for primary key (by default: `id`)
|
||||||
|
"""
|
||||||
|
|
||||||
|
serializer = PersonSerializer(self.person)
|
||||||
|
self.assertEquals(serializer.data['pk'], self.person.id)
|
||||||
|
|
||||||
|
|
||||||
class ValidationTests(TestCase):
|
class ValidationTests(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
|
Loading…
Reference in New Issue
Block a user