queryset argument is now optional on writable model fields.

This commit is contained in:
Tom Christie 2012-11-05 12:51:04 +00:00
parent ccd5f29510
commit 33be4b43b9
6 changed files with 33 additions and 14 deletions

View File

@ -64,6 +64,7 @@ To run the tests.
**Warning**: Please read [this thread][2.1.0-notes] regarding the `instance` and `data` keyword args before updating to 2.1.0. **Warning**: Please read [this thread][2.1.0-notes] regarding the `instance` and `data` keyword args before updating to 2.1.0.
* **Serializer `instance` and `data` keyword args have their position swapped.** * **Serializer `instance` and `data` keyword args have their position swapped.**
* `queryset` argument is now optional on writable model fields.
* Support Django's cache framework. * Support Django's cache framework.
* Minor field improvements. (Don't stringify dicts, more robust many-pk fields.) * Minor field improvements. (Don't stringify dicts, more robust many-pk fields.)
* Bugfixes (Support choice field in Browseable API) * Bugfixes (Support choice field in Browseable API)

View File

@ -11,9 +11,11 @@
**Warning**: Please read [this thread][2.1.0-notes] regarding the `instance` and `data` keyword args before updating to 2.1.0. **Warning**: Please read [this thread][2.1.0-notes] regarding the `instance` and `data` keyword args before updating to 2.1.0.
* **Serializer `instance` and `data` keyword args have their position swapped.** * **Serializer `instance` and `data` keyword args have their position swapped.**
* `queryset` argument is now optional on writable model fields.
* Support Django's cache framework. * Support Django's cache framework.
* Minor field improvements. (Don't stringify dicts, more robust many-pk fields.) * Minor field improvements. (Don't stringify dicts, more robust many-pk fields.)
* Bugfixes (Support choice field in Browseable API) * Bugfix: Support choice field in Browseable API.
* Bugfix: Related fields with `read_only=True` do not require a `queryset` argument.
## 2.0.2 ## 2.0.2

View File

@ -40,7 +40,7 @@ class Field(object):
self.source = source self.source = source
def initialize(self, parent): def initialize(self, parent, field_name):
""" """
Called to set up a field prior to field_to_native or field_from_native. Called to set up a field prior to field_to_native or field_from_native.
@ -248,7 +248,22 @@ class RelatedField(WritableField):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.queryset = kwargs.pop('queryset', None) self.queryset = kwargs.pop('queryset', None)
super(RelatedField, self).__init__(*args, **kwargs) super(RelatedField, self).__init__(*args, **kwargs)
self.read_only = self.default_read_only self.read_only = kwargs.pop('read_only', self.default_read_only)
def initialize(self, parent, field_name):
super(RelatedField, self).initialize(parent, field_name)
if self.queryset is None and not self.read_only:
try:
manager = getattr(self.parent.opts.model, self.source or field_name)
if hasattr(manager, 'related'): # Forward
self.queryset = manager.related.model._default_manager.all()
else: # Reverse
self.queryset = manager.field.rel.to._default_manager.all()
except:
raise
msg = ('Serializer related fields must include a `queryset`' +
' argument or set `read_only=True')
raise Exception(msg)
### We need this stuff to make form choices work... ### We need this stuff to make form choices work...

View File

@ -93,8 +93,8 @@ class BaseSerializer(Field):
def __init__(self, instance=None, data=None, context=None, **kwargs): def __init__(self, instance=None, data=None, context=None, **kwargs):
super(BaseSerializer, self).__init__(**kwargs) super(BaseSerializer, self).__init__(**kwargs)
self.fields = copy.deepcopy(self.base_fields)
self.opts = self._options_class(self.Meta) self.opts = self._options_class(self.Meta)
self.fields = copy.deepcopy(self.base_fields)
self.parent = None self.parent = None
self.root = None self.root = None
@ -128,7 +128,7 @@ class BaseSerializer(Field):
for key, field in self.fields.items(): for key, field in self.fields.items():
ret[key] = field ret[key] = field
# Set up the field # Set up the field
field.initialize(parent=self) field.initialize(parent=self, field_name=key)
# Add in the default fields # Add in the default fields
fields = self.default_fields(nested) fields = self.default_fields(nested)
@ -153,12 +153,12 @@ class BaseSerializer(Field):
##### #####
# Field methods - used when the serializer class is itself used as a field. # Field methods - used when the serializer class is itself used as a field.
def initialize(self, parent): def initialize(self, parent, field_name):
""" """
Same behaviour as usual Field, except that we need to keep track Same behaviour as usual Field, except that we need to keep track
of state so that we can deal with handling maximum depth. of state so that we can deal with handling maximum depth.
""" """
super(BaseSerializer, self).initialize(parent) super(BaseSerializer, self).initialize(parent, field_name)
if parent.opts.depth: if parent.opts.depth:
self.opts.depth = parent.opts.depth - 1 self.opts.depth = parent.opts.depth - 1
@ -369,7 +369,7 @@ class ModelSerializer(Serializer):
field = self.get_field(model_field) field = self.get_field(model_field)
if field: if field:
field.initialize(parent=self) field.initialize(parent=self, field_name=model_field.name)
ret[model_field.name] = field ret[model_field.name] = field
return ret return ret

View File

@ -7,12 +7,13 @@ from rest_framework.tests.models import Anchor, BasicModel, ManyToManyModel, Blo
factory = RequestFactory() factory = RequestFactory()
class BlogPostCommentSerializer(serializers.Serializer): class BlogPostCommentSerializer(serializers.ModelSerializer):
text = serializers.CharField() text = serializers.CharField()
blog_post_url = serializers.HyperlinkedRelatedField(source='blog_post', view_name='blogpost-detail', queryset=BlogPost.objects.all()) blog_post_url = serializers.HyperlinkedRelatedField(source='blog_post', view_name='blogpost-detail')
def restore_object(self, attrs, instance=None): class Meta:
return BlogPostComment(**attrs) model = BlogPostComment
fields = ('text', 'blog_post_url')
class BasicList(generics.ListCreateAPIView): class BasicList(generics.ListCreateAPIView):
@ -42,7 +43,7 @@ class ManyToManyDetail(generics.RetrieveAPIView):
class BlogPostCommentListCreate(generics.ListCreateAPIView): class BlogPostCommentListCreate(generics.ListCreateAPIView):
model = BlogPostComment model = BlogPostComment
model_serializer_class = BlogPostCommentSerializer serializer_class = BlogPostCommentSerializer
class BlogPostDetail(generics.RetrieveAPIView): class BlogPostDetail(generics.RetrieveAPIView):

View File

@ -15,7 +15,7 @@ class ManyToManySource(models.Model):
class ManyToManyTargetSerializer(serializers.ModelSerializer): class ManyToManyTargetSerializer(serializers.ModelSerializer):
sources = serializers.ManyPrimaryKeyRelatedField(queryset=ManyToManySource.objects.all()) sources = serializers.ManyPrimaryKeyRelatedField()
class Meta: class Meta:
model = ManyToManyTarget model = ManyToManyTarget