Commit e7e47073 by Mjumbe Wawatu Ukweli

Use parent's primary key when model is derived via multitable inheritance

parent 20880232
...@@ -456,8 +456,11 @@ class ModelSerializer(Serializer): ...@@ -456,8 +456,11 @@ class ModelSerializer(Serializer):
"Serializer class '%s' is missing 'model' Meta option" % self.__class__.__name__ "Serializer class '%s' is missing 'model' Meta option" % self.__class__.__name__
opts = get_concrete_model(cls)._meta opts = get_concrete_model(cls)._meta
pk_field = opts.pk pk_field = opts.pk
# while pk_field.rel:
# pk_field = pk_field.rel.to._meta.pk # If model is a child via multitable inheritance, use parent's pk
while isinstance(pk_field, models.OneToOneField) and pk_field.rel.parent_link:
pk_field = pk_field.rel.to._meta.pk
fields = [pk_field] fields = [pk_field]
fields += [field for field in opts.fields if field.serialize] fields += [field for field in opts.fields if field.serialize]
fields += [field for field in opts.many_to_many if field.serialize] fields += [field for field in opts.many_to_many if field.serialize]
......
...@@ -166,3 +166,17 @@ class NullableOneToOneSource(RESTFrameworkModel): ...@@ -166,3 +166,17 @@ class NullableOneToOneSource(RESTFrameworkModel):
name = models.CharField(max_length=100) name = models.CharField(max_length=100)
target = models.OneToOneField(OneToOneTarget, null=True, blank=True, target = models.OneToOneField(OneToOneTarget, null=True, blank=True,
related_name='nullable_source') related_name='nullable_source')
# Inherited
class ParentModel(RESTFrameworkModel):
name1 = models.CharField(max_length=100)
class ChildModel(ParentModel):
name2 = models.CharField(max_length=100)
class AssociatedModel(RESTFrameworkModel):
ref = models.OneToOneField(ParentModel, primary_key=True)
name = models.CharField(max_length=100)
...@@ -4,7 +4,8 @@ from django.test import TestCase ...@@ -4,7 +4,8 @@ from django.test import TestCase
from rest_framework import serializers from rest_framework import serializers
from rest_framework.tests.models import (HasPositiveIntegerAsChoice, Album, ActionItem, Anchor, BasicModel, from rest_framework.tests.models import (HasPositiveIntegerAsChoice, Album, ActionItem, Anchor, BasicModel,
BlankFieldModel, BlogPost, Book, CallableDefaultValueModel, DefaultValueModel, BlankFieldModel, BlogPost, Book, CallableDefaultValueModel, DefaultValueModel,
ManyToManyModel, Person, ReadOnlyManyToManyModel, Photo) ManyToManyModel, Person, ReadOnlyManyToManyModel, Photo, ParentModel, ChildModel,
AssociatedModel)
import datetime import datetime
import pickle import pickle
...@@ -96,6 +97,16 @@ class BrokenModelSerializer(serializers.ModelSerializer): ...@@ -96,6 +97,16 @@ class BrokenModelSerializer(serializers.ModelSerializer):
fields = ['some_field'] fields = ['some_field']
class DerivedModelSerializer(serializers.ModelSerializer):
class Meta:
model = ChildModel
class AssociatedModelSerializer(serializers.ModelSerializer):
class Meta:
model = AssociatedModel
class BasicTests(TestCase): class BasicTests(TestCase):
def setUp(self): def setUp(self):
self.comment = Comment( self.comment = Comment(
...@@ -170,6 +181,27 @@ class BasicTests(TestCase): ...@@ -170,6 +181,27 @@ class BasicTests(TestCase):
self.assertEqual(set(serializer.data.keys()), self.assertEqual(set(serializer.data.keys()),
set(['name', 'age', 'info'])) set(['name', 'age', 'info']))
def test_multitable_inherited_model_fields_as_expected(self):
"""
Assert that the parent pointer field is not included in the fields
serialized fields
"""
child = ChildModel(name1='parent name', name2='child name')
serializer = DerivedModelSerializer(child)
self.assertEqual(set(serializer.data.keys()),
set(['name1', 'name2', 'id']))
def test_onetoone_primary_key_model_fields_as_expected(self):
"""
Assert that a model with a onetoone field that is the primary key is
not treated like a derived model
"""
parent = ParentModel(name1='parent name')
associate = AssociatedModel(name='hello', ref=parent)
serializer = AssociatedModelSerializer(associate)
self.assertEqual(set(serializer.data.keys()),
set(['name', 'ref']))
def test_field_with_dictionary(self): def test_field_with_dictionary(self):
""" """
Make sure that dictionaries from fields are left intact Make sure that dictionaries from fields are left intact
...@@ -250,6 +282,14 @@ class ValidationTests(TestCase): ...@@ -250,6 +282,14 @@ class ValidationTests(TestCase):
self.assertEqual(serializer.is_valid(), False) self.assertEqual(serializer.is_valid(), False)
self.assertEqual(serializer.errors, {'email': ['This field is required.']}) self.assertEqual(serializer.errors, {'email': ['This field is required.']})
def test_multitable_inherited_model(self):
data = {
'name1': 'parent name',
'name2': 'child name',
}
serializer = DerivedModelSerializer(data=data)
self.assertEqual(serializer.is_valid(), True)
def test_missing_bool_with_default(self): def test_missing_bool_with_default(self):
"""Make sure that a boolean value with a 'False' value is not """Make sure that a boolean value with a 'False' value is not
mistaken for not having a default.""" mistaken for not having a default."""
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment