mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-02-03 05:04:31 +03:00
Drop out attribute
This commit is contained in:
parent
81c3b4f250
commit
21ae3a6691
|
@ -374,16 +374,20 @@ Returns the field instance that should be used to represent the pk field.
|
||||||
|
|
||||||
### get_nested_field
|
### get_nested_field
|
||||||
|
|
||||||
**Signature**: `.get_nested_field(self, model_field)`
|
**Signature**: `.get_nested_field(self, model_field, related_model, to_many)`
|
||||||
|
|
||||||
Returns the field instance that should be used to represent a related field when `depth` is specified as being non-zero.
|
Returns the field instance that should be used to represent a related field when `depth` is specified as being non-zero.
|
||||||
|
|
||||||
|
Note that the `model_field` argument will be `None` for reverse relationships. The `related_model` argument will be the model class for the target of the field. The `to_many` argument will be a boolean indicating if this is a to-one or to-many relationship.
|
||||||
|
|
||||||
### get_related_field
|
### get_related_field
|
||||||
|
|
||||||
**Signature**: `.get_related_field(self, model_field, to_many=False)`
|
**Signature**: `.get_related_field(self, model_field, related_model, to_many)`
|
||||||
|
|
||||||
Returns the field instance that should be used to represent a related field when `depth` is not specified, or when nested representations are being used and the depth reaches zero.
|
Returns the field instance that should be used to represent a related field when `depth` is not specified, or when nested representations are being used and the depth reaches zero.
|
||||||
|
|
||||||
|
Note that the `model_field` argument will be `None` for reverse relationships. The `related_model` argument will be the model class for the target of the field. The `to_many` argument will be a boolean indicating if this is a to-one or to-many relationship.
|
||||||
|
|
||||||
### get_field
|
### get_field
|
||||||
|
|
||||||
**Signature**: `.get_field(self, model_field)`
|
**Signature**: `.get_field(self, model_field)`
|
||||||
|
|
|
@ -79,34 +79,26 @@ Let's take a look at a quick example of using REST framework to build a simple m
|
||||||
|
|
||||||
We'll create a read-write API for accessing users and groups.
|
We'll create a read-write API for accessing users and groups.
|
||||||
|
|
||||||
Here's our `views.py` module:
|
Here's our project's root `urls.py` module:
|
||||||
|
|
||||||
from django.conf.urls.defaults import url, patterns, include
|
from django.conf.urls.defaults import url, patterns, include
|
||||||
from django.contrib.auth.models import User, Group
|
from django.contrib.auth.models import User, Group
|
||||||
from rest_framework import viewsets, routers
|
from rest_framework import viewsets, routers
|
||||||
|
|
||||||
|
|
||||||
# ViewSets define the view behavior.
|
# ViewSets define the view behavior.
|
||||||
class UserViewSet(viewsets.ModelViewSet):
|
class UserViewSet(viewsets.ModelViewSet):
|
||||||
queryset = User.objects.all()
|
model = User
|
||||||
fields = ('url', 'email', 'is_staff', 'groups')
|
|
||||||
|
|
||||||
|
|
||||||
class GroupViewSet(viewsets.ModelViewSet):
|
class GroupViewSet(viewsets.ModelViewSet):
|
||||||
queryset = Group.objects.all()
|
model = Group
|
||||||
fields = ('url', 'name')
|
|
||||||
|
|
||||||
And our `urls.py` setup:
|
|
||||||
|
|
||||||
from django.conf.urls.defaults import url, patterns, include
|
|
||||||
from myapp import views
|
|
||||||
from rest_framework import routers
|
|
||||||
|
|
||||||
|
|
||||||
|
# Routers provide an easy way of automatically determining the URL conf
|
||||||
router = routers.DefaultRouter()
|
router = routers.DefaultRouter()
|
||||||
router.register(r'users', views.UserViewSet, name='user')
|
router.register(r'users', views.UserViewSet, name='user')
|
||||||
router.register(r'groups', views.GroupViewSet, name='group')
|
router.register(r'groups', views.GroupViewSet, name='group')
|
||||||
|
|
||||||
|
|
||||||
# Wire up our API using automatic URL routing.
|
# Wire up our API using automatic URL routing.
|
||||||
# Additionally, we include login URLs for the browseable API.
|
# Additionally, we include login URLs for the browseable API.
|
||||||
urlpatterns = patterns('',
|
urlpatterns = patterns('',
|
||||||
|
|
|
@ -4,7 +4,6 @@ REST framework 2.3 is geared towards making it easier and quicker to build your
|
||||||
|
|
||||||
## ViewSets & Routers
|
## ViewSets & Routers
|
||||||
|
|
||||||
**TODO**
|
|
||||||
|
|
||||||
## Easier Serializers
|
## Easier Serializers
|
||||||
|
|
||||||
|
@ -132,13 +131,21 @@ If you've been customizing this behavior, for example perhaps to use `rst` marku
|
||||||
|
|
||||||
Note that the relevant methods have always been private APIs, and the docstrings called them out as intended to be deprecated.
|
Note that the relevant methods have always been private APIs, and the docstrings called them out as intended to be deprecated.
|
||||||
|
|
||||||
|
## ModelSerializers and reverse relationships
|
||||||
|
|
||||||
|
The support for adding reverse relationships to the `fields` option on a `ModelSerializer` class means that the `get_related_field` and `get_nested_field` method signatures have now changed.
|
||||||
|
|
||||||
|
In the unlikely event that you're providing a custom serializer class, and implementing these methods you should note the new call signature for both methods is now `(self, model_field, related_model, to_many)`. For revese relationships `model_field` will be `None`.
|
||||||
|
|
||||||
|
The old-style signature will continue to function but will raise a `PendingDeprecationWarning`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# Other notes
|
# Other notes
|
||||||
|
|
||||||
## Explict view attributes
|
## More explicit style
|
||||||
|
|
||||||
The usage of `model` attribute in generic Views is still supported, but it's usage is being discouraged in favour of the more explict `queryset` attribute.
|
The usage of `model` attribute in generic Views is still supported, but it's usage is being discouraged in favour of the setting the mode explict `queryset` and `serializer_class` attributes.
|
||||||
|
|
||||||
For example, the following is now the recommended style for using generic views:
|
For example, the following is now the recommended style for using generic views:
|
||||||
|
|
||||||
|
@ -146,9 +153,9 @@ For example, the following is now the recommended style for using generic views:
|
||||||
queryset = MyModel.objects.all()
|
queryset = MyModel.objects.all()
|
||||||
serializer_class = MyModelSerializer
|
serializer_class = MyModelSerializer
|
||||||
|
|
||||||
Using an explict `queryset` attribute makes the functioning of the view more clear than using the shortcut `model` attribute.
|
Using an explict `queryset` and `serializer_class` attributes makes the functioning of the view more clear than using the shortcut `model` attribute.
|
||||||
|
|
||||||
It also makes the usage of an overridden `get_queryset()` method more obvious.
|
It also makes the usage of the `get_queryset()` or `get_serializer_class()` methods more obvious.
|
||||||
|
|
||||||
class AccountListView(generics.RetrieveAPIView):
|
class AccountListView(generics.RetrieveAPIView):
|
||||||
serializer_class = MyModelSerializer
|
serializer_class = MyModelSerializer
|
||||||
|
@ -167,6 +174,10 @@ It also makes the usage of an overridden `get_queryset()` method more obvious.
|
||||||
|
|
||||||
The 2.3 release series will be the last series to provide compatiblity with Django 1.3.
|
The 2.3 release series will be the last series to provide compatiblity with Django 1.3.
|
||||||
|
|
||||||
|
## Version 2.2 API changes
|
||||||
|
|
||||||
|
All API changes in 2.2 that previously raised `PendingDeprecationWarning` will now raise a `DeprecationWarning`, which is loud by default.
|
||||||
|
|
||||||
## What comes next?
|
## What comes next?
|
||||||
|
|
||||||
The plan for the next few months is to concentrate on addressing outstanding tickets. 2.4 is likely to deal with relatively small refinements to the existing API.
|
The plan for the next few months is to concentrate on addressing outstanding tickets. 2.4 is likely to deal with relatively small refinements to the existing API.
|
||||||
|
|
|
@ -20,11 +20,17 @@ class GenericAPIView(views.APIView):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# You'll need to either set these attributes,
|
# You'll need to either set these attributes,
|
||||||
# or override `get_queryset`/`get_serializer_class`.
|
# or override `get_queryset()`/`get_serializer_class()`.
|
||||||
queryset = None
|
queryset = None
|
||||||
serializer_class = None
|
serializer_class = None
|
||||||
|
|
||||||
|
# This shortcut may be used instead of setting either or both
|
||||||
|
# of the `queryset`/`serializer_class` attributes, although using
|
||||||
|
# the explicit style is generally preferred.
|
||||||
|
model = None
|
||||||
|
|
||||||
# If you want to use object lookups other than pk, set this attribute.
|
# If you want to use object lookups other than pk, set this attribute.
|
||||||
|
# For more complex lookup requirements override `get_object()`.
|
||||||
lookup_field = 'pk'
|
lookup_field = 'pk'
|
||||||
|
|
||||||
# Pagination settings
|
# Pagination settings
|
||||||
|
@ -39,15 +45,6 @@ class GenericAPIView(views.APIView):
|
||||||
# Determines if the view will return 200 or 404 responses for empty lists.
|
# Determines if the view will return 200 or 404 responses for empty lists.
|
||||||
allow_empty = True
|
allow_empty = True
|
||||||
|
|
||||||
# This shortcut may be used instead of setting either (or both)
|
|
||||||
# of the `queryset`/`serializer_class` attributes, although using
|
|
||||||
# the explicit style is generally preferred.
|
|
||||||
model = None
|
|
||||||
|
|
||||||
# This shortcut may be used instead of setting the `serializer_class`
|
|
||||||
# attribute, although using the explicit style is generally preferred.
|
|
||||||
fields = None
|
|
||||||
|
|
||||||
# The following attributes may be subject to change,
|
# The following attributes may be subject to change,
|
||||||
# and should be considered private API.
|
# and should be considered private API.
|
||||||
model_serializer_class = api_settings.DEFAULT_MODEL_SERIALIZER_CLASS
|
model_serializer_class = api_settings.DEFAULT_MODEL_SERIALIZER_CLASS
|
||||||
|
@ -193,16 +190,15 @@ class GenericAPIView(views.APIView):
|
||||||
if serializer_class is not None:
|
if serializer_class is not None:
|
||||||
return serializer_class
|
return serializer_class
|
||||||
|
|
||||||
assert self.model is not None or self.queryset is not None, \
|
assert self.model is not None, \
|
||||||
"'%s' should either include a 'serializer_class' attribute, " \
|
"'%s' should either include a 'serializer_class' attribute, " \
|
||||||
"or use the 'queryset' or 'model' attribute as a shortcut for " \
|
"or use the 'model' attribute as a shortcut for " \
|
||||||
"automatically generating a serializer class." \
|
"automatically generating a serializer class." \
|
||||||
% self.__class__.__name__
|
% self.__class__.__name__
|
||||||
|
|
||||||
class DefaultSerializer(self.model_serializer_class):
|
class DefaultSerializer(self.model_serializer_class):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = self.model or self.queryset.model
|
model = self.model
|
||||||
fields = self.fields
|
|
||||||
return DefaultSerializer
|
return DefaultSerializer
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
|
|
|
@ -677,6 +677,8 @@ class ModelSerializer(Serializer):
|
||||||
def get_nested_field(self, model_field, related_model, to_many):
|
def get_nested_field(self, model_field, related_model, to_many):
|
||||||
"""
|
"""
|
||||||
Creates a default instance of a nested relational field.
|
Creates a default instance of a nested relational field.
|
||||||
|
|
||||||
|
Note that model_field will be `None` for reverse relationships.
|
||||||
"""
|
"""
|
||||||
class NestedModelSerializer(ModelSerializer):
|
class NestedModelSerializer(ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -686,6 +688,8 @@ class ModelSerializer(Serializer):
|
||||||
def get_related_field(self, model_field, related_model, to_many):
|
def get_related_field(self, model_field, related_model, to_many):
|
||||||
"""
|
"""
|
||||||
Creates a default instance of a flat relational field.
|
Creates a default instance of a flat relational field.
|
||||||
|
|
||||||
|
Note that model_field will be `None` for reverse relationships.
|
||||||
"""
|
"""
|
||||||
# TODO: filter queryset using:
|
# TODO: filter queryset using:
|
||||||
# .using(db).complex_filter(self.rel.limit_choices_to)
|
# .using(db).complex_filter(self.rel.limit_choices_to)
|
||||||
|
|
|
@ -344,32 +344,6 @@ class TestOverriddenGetObject(TestCase):
|
||||||
self.assertEqual(response.data, self.data[0])
|
self.assertEqual(response.data, self.data[0])
|
||||||
|
|
||||||
|
|
||||||
class TestFieldsShortcut(TestCase):
|
|
||||||
"""
|
|
||||||
Test cases for setting the `fields` attribute on a view.
|
|
||||||
"""
|
|
||||||
def setUp(self):
|
|
||||||
class OverriddenFieldsView(generics.RetrieveUpdateDestroyAPIView):
|
|
||||||
queryset = BasicModel.objects.all()
|
|
||||||
fields = ('text',)
|
|
||||||
|
|
||||||
class RegularView(generics.RetrieveUpdateDestroyAPIView):
|
|
||||||
queryset = BasicModel.objects.all()
|
|
||||||
|
|
||||||
self.overridden_fields_view = OverriddenFieldsView()
|
|
||||||
self.regular_view = RegularView()
|
|
||||||
|
|
||||||
def test_overridden_fields_view(self):
|
|
||||||
Serializer = self.overridden_fields_view.get_serializer_class()
|
|
||||||
self.assertEqual(Serializer().fields.keys(), ['text'])
|
|
||||||
self.assertEqual(Serializer().opts.model, BasicModel)
|
|
||||||
|
|
||||||
def test_not_overridden_fields_view(self):
|
|
||||||
Serializer = self.regular_view.get_serializer_class()
|
|
||||||
self.assertEqual(Serializer().fields.keys(), ['id', 'text'])
|
|
||||||
self.assertEqual(Serializer().opts.model, BasicModel)
|
|
||||||
|
|
||||||
|
|
||||||
# Regression test for #285
|
# Regression test for #285
|
||||||
|
|
||||||
class CommentSerializer(serializers.ModelSerializer):
|
class CommentSerializer(serializers.ModelSerializer):
|
||||||
|
|
Loading…
Reference in New Issue
Block a user