I needed to be able to filter which items of a ManyRelatedField
were returned, based on some attributes of the request user. Normally, all items in the relationship are returned, however I was able to override the ManyRelatedField.to_attribute()
function to enable additional filtering of the relationship.
Created
October 5, 2015 15:44
-
-
Save lsowen/99dedd98227f518336a2 to your computer and use it in GitHub Desktop.
django-rest-framework-json-api dynamic filter relationship
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from rest_framework.relations import MANY_RELATION_KWARGS, ManyRelatedField | |
from rest_framework import serializers | |
from rest_framework_json_api.relations import ResourceRelatedField | |
class CustomManyRelatedField(ManyRelatedField): | |
def get_attribute(self, instance): | |
# Override the default implementation of get_attribute | |
# Can't have any relationships if not created | |
if hasattr(instance, 'pk') and instance.pk is None: | |
return [] | |
relationship = get_attribute(instance, self.source_attrs) | |
queryset = self.filter_relationship(instance, relationship) | |
return queryset.all() if (hasattr(queryset, 'all')) else queryset | |
def filter_relationship(self, instance, relationship): | |
user = self.context['request'].user | |
return relationship.filter("some additional logic here") | |
class CustomResourceRelatedField(ResourceRelatedField): | |
@classmethod | |
def many_init(cls, *args, **kwargs): | |
list_kwargs = {'child_relation': cls(*args, **kwargs) } | |
for key in kwargs.keys(): | |
if key in MANY_RELATION_KWARGS: | |
list_kwargs[key] = kwargs[key] | |
return CustomManyRelatedField(**list_kwargs) | |
class BuildSerializer(serializers.ModelSerializer): | |
artifacts = CustomResourceRelatedField(queryset=BuildArtifact.objects, many=True) | |
class Meta: | |
model = Build |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks a million, this worked great! I modified slightly to filter out objects that have an "is_deleted" flag set to true (and changed super call to work with Python 2.x):