Drop out attribute

This commit is contained in:
Tom Christie 2013-04-30 08:24:33 +01:00
parent 81c3b4f250
commit 21ae3a6691
6 changed files with 42 additions and 61 deletions

View File

@ -374,16 +374,20 @@ Returns the field instance that should be used to represent the pk 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.
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
**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.
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
**Signature**: `.get_field(self, model_field)`

View File

@ -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.
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.contrib.auth.models import User, Group
from rest_framework import viewsets, routers
# ViewSets define the view behavior.
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
fields = ('url', 'email', 'is_staff', 'groups')
model = User
class GroupViewSet(viewsets.ModelViewSet):
queryset = Group.objects.all()
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
model = Group
# Routers provide an easy way of automatically determining the URL conf
router = routers.DefaultRouter()
router.register(r'users', views.UserViewSet, name='user')
router.register(r'groups', views.GroupViewSet, name='group')
# Wire up our API using automatic URL routing.
# Additionally, we include login URLs for the browseable API.
urlpatterns = patterns('',

View File

@ -4,7 +4,6 @@ REST framework 2.3 is geared towards making it easier and quicker to build your
## ViewSets & Routers
**TODO**
## 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.
## 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
## 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:
@ -146,9 +153,9 @@ For example, the following is now the recommended style for using generic views:
queryset = MyModel.objects.all()
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):
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.
## 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?
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.

View File

@ -20,11 +20,17 @@ class GenericAPIView(views.APIView):
"""
# You'll need to either set these attributes,
# or override `get_queryset`/`get_serializer_class`.
# or override `get_queryset()`/`get_serializer_class()`.
queryset = 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.
# For more complex lookup requirements override `get_object()`.
lookup_field = 'pk'
# Pagination settings
@ -39,15 +45,6 @@ class GenericAPIView(views.APIView):
# Determines if the view will return 200 or 404 responses for empty lists.
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,
# and should be considered private API.
model_serializer_class = api_settings.DEFAULT_MODEL_SERIALIZER_CLASS
@ -193,16 +190,15 @@ class GenericAPIView(views.APIView):
if serializer_class is not None:
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, " \
"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." \
% self.__class__.__name__
class DefaultSerializer(self.model_serializer_class):
class Meta:
model = self.model or self.queryset.model
fields = self.fields
model = self.model
return DefaultSerializer
def get_queryset(self):

View File

@ -677,6 +677,8 @@ class ModelSerializer(Serializer):
def get_nested_field(self, model_field, related_model, to_many):
"""
Creates a default instance of a nested relational field.
Note that model_field will be `None` for reverse relationships.
"""
class NestedModelSerializer(ModelSerializer):
class Meta:
@ -686,6 +688,8 @@ class ModelSerializer(Serializer):
def get_related_field(self, model_field, related_model, to_many):
"""
Creates a default instance of a flat relational field.
Note that model_field will be `None` for reverse relationships.
"""
# TODO: filter queryset using:
# .using(db).complex_filter(self.rel.limit_choices_to)

View File

@ -344,32 +344,6 @@ class TestOverriddenGetObject(TestCase):
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
class CommentSerializer(serializers.ModelSerializer):