Skip to content

Included field might not be set #172

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 14, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion example/factories/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import factory
from faker import Factory as FakerFactory
from example.models import Blog, Author, Entry, Comment
from example.models import Blog, Author, AuthorBio, Entry, Comment

faker = FakerFactory.create()
faker.seed(983843)
Expand All @@ -23,6 +23,14 @@ class Meta:
email = factory.LazyAttribute(lambda x: faker.email())


class AuthorBioFactory(factory.django.DjangoModelFactory):
class Meta:
model = AuthorBio

author = factory.SubFactory(AuthorFactory)
body = factory.LazyAttribute(lambda x: faker.text())


class EntryFactory(factory.django.DjangoModelFactory):
class Meta:
model = Entry
Expand Down
9 changes: 9 additions & 0 deletions example/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@ def __str__(self):
return self.name


@python_2_unicode_compatible
class AuthorBio(BaseModel):
author = models.OneToOneField(Author, related_name='bio')
body = models.TextField()

def __str__(self):
return self.author.name


@python_2_unicode_compatible
class Entry(BaseModel):
blog = models.ForeignKey(Blog)
Expand Down
14 changes: 12 additions & 2 deletions example/serializers.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from rest_framework_json_api import serializers, relations
from example.models import Blog, Entry, Author, Comment
from example.models import Blog, Entry, Author, AuthorBio, Comment


class BlogSerializer(serializers.ModelSerializer):
Expand Down Expand Up @@ -38,11 +38,21 @@ class Meta:
'authors', 'comments', 'suggested',)


class AuthorBioSerializer(serializers.ModelSerializer):

class Meta:
model = AuthorBio
fields = ('author', 'body',)


class AuthorSerializer(serializers.ModelSerializer):
included_serializers = {
'bio': AuthorBioSerializer
}

class Meta:
model = Author
fields = ('name', 'email',)
fields = ('name', 'email', 'bio')


class CommentSerializer(serializers.ModelSerializer):
Expand Down
3 changes: 2 additions & 1 deletion example/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import pytest
from pytest_factoryboy import register

from example.factories import BlogFactory, AuthorFactory, EntryFactory, CommentFactory
from example.factories import BlogFactory, AuthorFactory, AuthorBioFactory, EntryFactory, CommentFactory

register(BlogFactory)
register(AuthorFactory)
register(AuthorBioFactory)
register(EntryFactory)
register(CommentFactory)

Expand Down
14 changes: 14 additions & 0 deletions example/tests/integration/test_includes.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,17 @@ def test_dynamic_related_data_is_included(single_entry, entry_factory, client):
assert [x.get('type') for x in included] == ['entries'], 'Dynamic included types are incorrect'
assert len(included) == 1, 'The dynamically included blog entries are of an incorrect count'


def test_missing_field_not_included(author_bio_factory, author_factory, client):
# First author does not have a bio
author = author_factory()
response = client.get(reverse('author-detail', args=[author.pk])+'?include=bio')
data = load_json(response.content)
assert 'included' not in data
# Second author does
bio = author_bio_factory()
response = client.get(reverse('author-detail', args=[bio.author.pk])+'?include=bio')
data = load_json(response.content)
assert 'included' in data
assert len(data['included']) == 1
assert data['included'][0]['attributes']['body'] == bio.body
2 changes: 2 additions & 0 deletions rest_framework_json_api/renderers.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,8 @@ def extract_included(fields, resource, resource_instance, included_resources):
# For ManyRelatedFields if `related_name` is not set we need to access `foo_set` from `source`
relation_instance_or_manager = getattr(resource_instance, field.child_relation.source)
except AttributeError:
if not hasattr(current_serializer, field.source):
continue
serializer_method = getattr(current_serializer, field.source)
relation_instance_or_manager = serializer_method(resource_instance)

Expand Down