Skip to content

Commit

Permalink
feat: add visibiility mixin for relationships
Browse files Browse the repository at this point in the history
  • Loading branch information
Yelinz committed Nov 17, 2023
1 parent 8caaaa7 commit 545c36a
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 3 deletions.
30 changes: 27 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,34 @@ For the visibilities, extend your DRF `ViewSet` classes with the
from rest_framework.viewsets import ModelViewSet
from generic_permissions.visibilities import VisibilityViewMixin
class MyModelViewset(VisibilityViewMixin, ModelViewSet):
serializer_class = ...
serializer_class = MyModelSerializers
queryset = ...
```

Make sure to use a subclassed `serializer_related_field` (such as the default `PrimariyKeyRelatedField`)
with the provided `VisibilityRelatedFieldMixin`. Otherwise relationships will leak hidden models.

```python
# serializers.py
from rest_framework.viewsets import ModelSerializer
from generic_permissions.visibilities import VisibilityPrimaryKeyRelatedField
class MyModelSerializers(ModelSerializer):
serializer_related_field = VisibilityPrimaryKeyRelatedField
```

A few subclassed fields are provided:
- `VisibilityPrimaryKeyRelatedField`
- `VisibilityResourceRelatedField`
- `VisibilitySerializerMethodResourceRelatedField`

If a different relation field variation is needed extend it with `VisibilityRelatedFieldMixin`:

```python
from generic_permissions.visibilities import VisibilityRelatedFieldMixin
class CustomRelationField(VisibilityRelatedFieldMixin):
pass
```

### Permission subsystem

Similarly, for the permissions system, add the `PermissionViewMixin` to your
Expand All @@ -94,13 +118,13 @@ You may use only one of the two mixins, or both, depending on your needs.
Last, for the validation system, you extend your **serializer** with a mixin:
```python
# serializers.py
from rest_framework import serializers
from rest_framework.serializers import ModelSerializer

from generic_permissions.serializers import PermissionSerializerMixin
from generic_permissions.validation import ValidatorMixin

from myapp import models
class MyModelSerializer(ValidatorMixin, serializers.ModelSerializer):
class MyModelSerializer(ValidatorMixin, ModelSerializer):
# my field definitions...
class Meta:
model = models.MyModel
Expand Down
34 changes: 34 additions & 0 deletions generic_permissions/visibilities.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
from functools import reduce
from warnings import warn

from rest_framework.serializers import PrimaryKeyRelatedField
from rest_framework_json_api.relations import (
ResourceRelatedField,
SerializerMethodResourceRelatedField,
)

from .config import DGAPConfigManager, VisibilitiesConfig

"""
Expand Down Expand Up @@ -44,6 +50,34 @@ def get_queryset(self):
return queryset


class VisibilityRelatedFieldMixin:
def get_queryset(self):
queryset = super().get_queryset()

for handler in VisibilitiesConfig.get_handlers(queryset.model):
queryset = handler(
queryset, self.get_parent_serializer()._context["request"]
)

return queryset


class VisibilityPrimaryKeyRelatedField(
PrimaryKeyRelatedField, VisibilityRelatedFieldMixin
):
pass


class VisibilityResourceRelatedField(ResourceRelatedField, VisibilityRelatedFieldMixin):
pass


class VisibilitySerializerMethodResourceRelatedField(
SerializerMethodResourceRelatedField, VisibilityRelatedFieldMixin
):
pass


class BaseVisibility: # pragma: no cover
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
Expand Down
5 changes: 5 additions & 0 deletions tests/serializers.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
from rest_framework import serializers

from generic_permissions.validation import ValidatorMixin
from generic_permissions.visibilities import VisibilityPrimaryKeyRelatedField

from . import models


class TestModel1Serializer(ValidatorMixin, serializers.ModelSerializer):
serializer_related_field = VisibilityPrimaryKeyRelatedField

class Meta:
model = models.Model1
fields = "__all__"


class TestModel2Serializer(ValidatorMixin, serializers.ModelSerializer):
serializer_related_field = VisibilityPrimaryKeyRelatedField

class Meta:
model = models.Model2
fields = "__all__"

0 comments on commit 545c36a

Please sign in to comment.