31👍
I’m faced with the same scenario. The best solution that I’ve found is to use a SerializerMethodField
and have that method query and return the desired values. You can have access to request.user
in that method through self.context['request'].user
.
Still, this seems like a bit of a hack. I’m fairly new to DRF, so maybe someone with more experience can chime in.
10👍
You have to use filter instead of get, otherwise if multiple record return you will get Exception.
current_user_zone_permission = serializers.SerializerMethodField('get_user_zone_permission')
def get_user_zone_permission(self, obj):
user = self.context['request'].user
zone_permission = ZonePermission.objects.filter(zone=obj, user=user)
serializer = ZonePermissionSerializer(zone_permission,many=True)
return serializer.data
- [Django]-How do I access the child classes of an object in django without knowing the name of the child class?
- [Django]-How to upgrade django?
- [Django]-How to query abstract-class-based objects in Django?
5👍
Now you can subclass the ListSerializer, using the method I described here: https://stackoverflow.com/a/28354281/3246023
You can subclass the ListSerializer and overwrite the to_representation method.
By default the to_representation method calls data.all() on the nested queryset. So you effectively need to make data = data.filter(**your_filters) before the method is called. Then you need to add your subclassed ListSerializer as the list_serializer_class on the meta of the nested serializer.
- subclass ListSerializer, overwriting to_representation and then calling super
- add subclassed ListSerializer as the meta list_serializer_class on the nested Serializer
- [Django]-How to reload modules in django shell?
- [Django]-How to make a PATCH request using DJANGO REST framework
- [Django]-Error: No module named staticfiles
4👍
If you’re using the QuerySet / filter in multiple places, you could use a getter function on your model, and then even drop the ‘source’ kwarg for the Serializer / Field. DRF automatically calls functions/callables if it finds them when using it’s get_attribute function.
class Zone(models.Model):
name = models.SlugField()
def current_user_zone_permission(self):
return ZonePermission.objects.get(zone=self, user=user)
I like this method because it keeps your API consistent under the hood with the api over HTTP.
class ZoneSerializer(serializers.HyperlinkedModelSerializer):
current_user_zone_permission = ZonePermissionSerializer()
class Meta:
model = Zone
fields = ('name', 'current_user_zone_permission')
Hopefully this helps some people!
Note: The names don’t need to match, you can still use the source kwarg if you need/want to.
Edit: I just realised that the function on the model doesn’t have access to the user or the request. So perhaps a custom model field / ListSerializer would be more suited to this task.
- [Django]-Django Admin – Disable the 'Add' action for a specific model
- [Django]-How to pass multiple values for a single URL parameter?
- [Django]-Django templates: verbose version of a choice
2👍
I would do it in one of two ways.
1) Either do it through prefetch in your view:
serializer = ZoneSerializer(Zone.objects.prefetch_related(
Prefetch('zone_permission_set',
queryset=ZonePermission.objects.filter(user=request.user),
to_attr='current_user_zone_permission'))
.get(id=pk))
2) Or do it though the .to_representation:
class ZoneSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Zone
fields = ('name',)
def to_representation(self, obj):
data = super(ZoneSerializer, self).to_representation(obj)
data['current_user_zone_permission'] = ZonePermissionSerializer(ZonePermission.objects.filter(zone=obj, user=self.context['request'].user)).data
return data
- [Django]-Django FileField: How to return filename only (in template)
- [Django]-Django: change the value of a field for all objects in a queryset
- [Django]-How to implement FirebaseDB with a Django Web Application