Skip to content

Commit

Permalink
fix ModelPermissionsField representation
Browse files Browse the repository at this point in the history
  • Loading branch information
agrausem committed Jan 15, 2015
1 parent 10c5327 commit b48069e
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 60 deletions.
47 changes: 22 additions & 25 deletions rest_framework_fine_permissions/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@

import logging
import six
import collections

from django.db import models
from rest_framework import serializers
from rest_framework.fields import is_simple_callable
from rest_framework.fields import Field
from rest_framework.fields import Field, empty


logger = logging.getLogger(__name__)
Expand All @@ -16,7 +18,7 @@


def get_application(app_label):
""" Get application. """
""" Get an application. """
try:
# django >= 1.7
from django.apps import apps as django_apps
Expand All @@ -29,7 +31,6 @@ def get_application(app_label):
APP_NAMES = {
app.rsplit('.', 1)[-1]: app for app in settings.INSTALLED_APPS
}

return APP_NAMES[app_label]


Expand All @@ -49,34 +50,30 @@ def get_serializer(serializer):
return serializer




class ModelPermissionsField(Field):
"""
"""

def __init__(self, serializer, field='', **kwargs):
""" Field that acts as a ModelPermissionsSerializer for relations. """

def __init__(self, serializer, read_only=False, write_only=False,
required=None, default=empty, initial=empty, source=None,
label=None, help_text=None, style=None,
error_messages=None, validators=None, allow_null=False):
self.serializer = get_serializer(serializer)
assert self.serializer is not None \
and issubclass(self.serializer, serializers.ModelSerializer), (
"Bad serializer defined %s" % serializer
)
self.field = field
super(ModelPermissionsField, self).__init__(**kwargs)

def _get_serializer(self, attr):
many = hasattr(attr, '__iter__') and not isinstance(attr, dict)
return self.serializer(attr, context=self.context, many=many)
super(ModelPermissionsField, self).__init__(read_only, write_only,
required, default, initial,
source, label, help_text,
style, error_messages,
validators, allow_null)

def to_representation(self, obj):
attr = getattr(obj, self.field or self.field_name, None)

assert attr is not None, (
"Bad configuration for field %s, "
"model %s doesn't have a field with this name" %
(self.field_name, self.parent.Meta.model.__name__))

if is_simple_callable(getattr(attr, 'all', None)):
attr = attr.all()
""" Represent data for the field. """
many = isinstance(obj, collections.Iterable) \
or isinstance(obj, models.Manager) \
and not isinstance(obj, dict)

return self._get_serializer(attr).data
ser = self.serializer(obj, context=self.context, many=many)
return ser.data
4 changes: 0 additions & 4 deletions rest_framework_fine_permissions/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
from rest_framework.utils.field_mapping import get_relation_kwargs

from .models import FieldPermission
from .fields import ModelPermissionsField


class ModelPermissionsSerializer(serializers.ModelSerializer):
Expand Down Expand Up @@ -76,9 +75,6 @@ def get_fields(self):
kwargs.pop('view_name', None)
field = field_cls(**kwargs)

if isinstance(field, ModelPermissionsField):
field.bind(allowed_field.name, self)

ret[allowed_field.name] = field
return ret

Expand Down
4 changes: 2 additions & 2 deletions tests/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ class Meta:
class CardSerializer(serializers.ModelPermissionsSerializer):

account = fields.ModelPermissionsField(AccountSerializer)
service_names = fields.ModelPermissionsField(ServiceSerializer, field='services')
service_names = fields.ModelPermissionsField(ServiceSerializer, source='services')

class Meta:
model = Card

class AnotherCardSerializer(serializers.ModelPermissionsSerializer):

account = fields.ModelPermissionsField(AccountSerializer)
service_names = fields.ModelPermissionsField('tests.ServiceSerializer', field='services')
service_names = fields.ModelPermissionsField('tests.ServiceSerializer', source='services')

class Meta:
model = Card
Expand Down
43 changes: 14 additions & 29 deletions tests/test_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,27 +37,28 @@ def _add_field_perms(self, app, model, *field_names):
def _auth_user(self):
self.request.user = self.user

def _get_serializer_instance(self, anonymous=False):
def _get_serializer_instance(self, instance=None, anonymous=False):
if anonymous:
self.Serializer(context={})
self.Serializer(instance=instance, context={})
self._auth_user()
return self.Serializer(context={'request': self.request})
return self.Serializer(instance=instance,
context={'request': self.request})

def test_simple_data_in_permissions_field(self):
""" Test with a many to one field. """
self._add_field_perms('tests', 'account', 'id', 'user')
self._add_field_perms('tests', 'card', 'account')

ser = self._get_serializer_instance()
mpf = ser.get_fields()['account']
ser = self._get_serializer_instance(instance=self.card)

representation = mpf.to_representation(self.card)
data = ser.data

self.assertEqual(sorted(representation), ['id', 'user'])
self.assertEqual(representation['id'], self.account.id)
self.assertEqual(sorted(data['account']), ['id', 'user'])
self.assertEqual(data['account']['id'], self.account.id)

def test_list_data_in_permissions_field(self):
""" Test with a many to one field. """
self._add_field_perms('tests', 'account', 'id', 'user')
self._add_field_perms('tests', 'card', 'id', 'service_names')
self._add_field_perms('tests', 'service', 'name', 'id')

Expand All @@ -66,28 +67,12 @@ def test_list_data_in_permissions_field(self):
self.card.services.add(service)
self.card.services.add(service2)

ser = self._get_serializer_instance()
mpf = ser.get_fields()['service_names']

representation = mpf.to_representation(self.card)

self.assertEqual(sorted(representation[0]), ['id', 'name'])
self.assertEqual(len(representation), 2)
self.assertEqual(representation[0]['name'], 'chronos')

def test_bad_configuration(self):
""" Test bad instantiation of a model permissions field. """
self._add_field_perms('tests', 'card', 'account_name')
self.Serializer = serializers.BadCardSerializer

ser = self._get_serializer_instance()
mpf = ser.get_fields()['account_name']
ser = self._get_serializer_instance(instance=self.card)
data = ser.data

self.assertRaisesRegexp(
AssertionError,
"for field account_name, model Card doesn't have a field",
mpf.to_representation,
self.card)
self.assertEqual(sorted(data['service_names'][0]), ['id', 'name'])
self.assertEqual(len(data['service_names']), 2)
self.assertEqual(data['service_names'][0]['name'], 'chronos')

def test_defined_with_no_dependency(self):
""" Test with serializer passed as a string. """
Expand Down

0 comments on commit b48069e

Please sign in to comment.