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.
* **Serializer `instance` and `data` keyword args have their position swapped.**
* `queryset` argument is now optional on writable model fields.
* Support Django's cache framework.
* Minor field improvements. (Don't stringify dicts, more robust many-pk fields.)
* 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.
* **Serializer `instance` and `data` keyword args have their position swapped.**
* `queryset` argument is now optional on writable model fields.
* Support Django's cache framework.
* 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

View File

@ -40,7 +40,7 @@ class Field(object):
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.
@ -248,7 +248,22 @@ class RelatedField(WritableField):
def __init__(self, *args, **kwargs):
self.queryset = kwargs.pop('queryset', None)
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...

View File

@ -93,8 +93,8 @@ class BaseSerializer(Field):
def __init__(self, instance=None, data=None, context=None, **kwargs):
super(BaseSerializer, self).__init__(**kwargs)
self.fields = copy.deepcopy(self.base_fields)
self.opts = self._options_class(self.Meta)
self.fields = copy.deepcopy(self.base_fields)
self.parent = None
self.root = None
@ -128,7 +128,7 @@ class BaseSerializer(Field):
for key, field in self.fields.items():
ret[key] = field
# Set up the field
field.initialize(parent=self)
field.initialize(parent=self, field_name=key)
# Add in the default fields
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.
def initialize(self, parent):
def initialize(self, parent, field_name):
"""
Same behaviour as usual Field, except that we need to keep track
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:
self.opts.depth = parent.opts.depth - 1
@ -369,7 +369,7 @@ class ModelSerializer(Serializer):
field = self.get_field(model_field)
if field:
field.initialize(parent=self)
field.initialize(parent=self, field_name=model_field.name)
ret[model_field.name] = field
return ret

View File

@ -7,12 +7,13 @@ from rest_framework.tests.models import Anchor, BasicModel, ManyToManyModel, Blo
factory = RequestFactory()
class BlogPostCommentSerializer(serializers.Serializer):
class BlogPostCommentSerializer(serializers.ModelSerializer):
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):
return BlogPostComment(**attrs)
class Meta:
model = BlogPostComment
fields = ('text', 'blog_post_url')
class BasicList(generics.ListCreateAPIView):
@ -42,7 +43,7 @@ class ManyToManyDetail(generics.RetrieveAPIView):
class BlogPostCommentListCreate(generics.ListCreateAPIView):
model = BlogPostComment
model_serializer_class = BlogPostCommentSerializer
serializer_class = BlogPostCommentSerializer
class BlogPostDetail(generics.RetrieveAPIView):

View File

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