diff options
| -rw-r--r-- | docs/api-guide/pagination.md | 2 | ||||
| -rw-r--r-- | rest_framework/relations.py | 4 | ||||
| -rw-r--r-- | tests/test_relations_pk.py | 20 |
3 files changed, 25 insertions, 1 deletions
diff --git a/docs/api-guide/pagination.md b/docs/api-guide/pagination.md index c264ea8c..3518fb34 100644 --- a/docs/api-guide/pagination.md +++ b/docs/api-guide/pagination.md @@ -164,7 +164,7 @@ Cursor based pagination is more complex than other schemes. It also requires tha #### Details and limitations -Proper use of cursor based pagination a little attention to detail. You'll need to think about what ordering you want the scheme to be applied against. The default is to order by `"-created"`. This assumes that **there must be a 'created' timestamp field** on the model instances, and will present a "timeline" style paginated view, with the most recently added items first. +Proper use of cursor based pagination requires a little attention to detail. You'll need to think about what ordering you want the scheme to be applied against. The default is to order by `"-created"`. This assumes that **there must be a 'created' timestamp field** on the model instances, and will present a "timeline" style paginated view, with the most recently added items first. You can modify the ordering by overriding the `'ordering'` attribute on the pagination class, or by using the `OrderingFilter` filter class together with `CursorPagination`. When used with `OrderingFilter` you should strongly consider restricting the fields that the user may order by. diff --git a/rest_framework/relations.py b/rest_framework/relations.py index 0b7c9d86..3a966c5b 100644 --- a/rest_framework/relations.py +++ b/rest_framework/relations.py @@ -360,6 +360,10 @@ class ManyRelatedField(Field): ] def get_attribute(self, instance): + # Can't have any relationships if not created + if not instance.pk: + return [] + relationship = get_attribute(instance, self.source_attrs) return relationship.all() if (hasattr(relationship, 'all')) else relationship diff --git a/tests/test_relations_pk.py b/tests/test_relations_pk.py index f872a8dc..ca43272b 100644 --- a/tests/test_relations_pk.py +++ b/tests/test_relations_pk.py @@ -143,6 +143,16 @@ class PKManyToManyTests(TestCase): ] self.assertEqual(serializer.data, expected) + def test_many_to_many_unsaved(self): + source = ManyToManySource(name='source-unsaved') + + serializer = ManyToManySourceSerializer(source) + + expected = {'id': None, 'name': 'source-unsaved', 'targets': []} + # no query if source hasn't been created yet + with self.assertNumQueries(0): + self.assertEqual(serializer.data, expected) + def test_reverse_many_to_many_create(self): data = {'id': 4, 'name': 'target-4', 'sources': [1, 3]} serializer = ManyToManyTargetSerializer(data=data) @@ -296,6 +306,16 @@ class PKForeignKeyTests(TestCase): self.assertFalse(serializer.is_valid()) self.assertEqual(serializer.errors, {'target': ['This field may not be null.']}) + def test_foreign_key_with_unsaved(self): + source = ForeignKeySource(name='source-unsaved') + expected = {'id': None, 'name': 'source-unsaved', 'target': None} + + serializer = ForeignKeySourceSerializer(source) + + # no query if source hasn't been created yet + with self.assertNumQueries(0): + self.assertEqual(serializer.data, expected) + def test_foreign_key_with_empty(self): """ Regression test for #1072 |
