Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Limit choices to foreignkey in django rest framework

How to limit images of request.user to be linked with node. I wish I could do something like:

photo = models.ForeignKey(
    Image,
    limit_choices_to={'owner': username},
)

but request.user rather than username and I don't want to use local threads.

models.py

class Node(models.Model):
    owner = models.ForeignKey(User)
    content = models.TextField()
    photo = models.ForeignKey(Image)

class Image(models.Model):
    owner = models.ForeignKey(User)
    file = models.ImageField(upload_to=get_upload_file_name)

serializers.py

class ImageSerializer(serializers.ModelSerializer):
    owner = serializers.Field('owner.username')

    class Meta:
        model = Image
        fields = ('file', 'owner')

class NodeSerializer(serializers.HyperlinkedModelSerializer):

    class Meta:
        model = Node
        fields = ('content', 'photo', 'owner')
like image 580
eneepo Avatar asked Mar 04 '14 13:03

eneepo


4 Answers

from rest_framework import serializers

class CustomForeignKey(serializers.PrimaryKeyRelatedField):
    def get_queryset(self):
        return Table.objects.filter(user=self.context['request'].user)
        # or: ...objects.filter(user=serializers.CurrentUserDefault()(self))

class Serializer(serializers.ModelSerializer):
   table = CustomForeignKey()
like image 93
mirek Avatar answered Nov 10 '22 00:11

mirek


You can create a custom foreign key field and define get_queryset() method there to filter related objects to only those of your user. The current user can be retrieved from the request in the context:

class UserPhotoForeignKey(serializers.PrimaryKeyRelatedField):
    def get_queryset(self):
        return Image.objects.filter(owner=self.context['request'].user)

class NodeSerializer(serializers.HyperlinkedModelSerializer):
    photo = UserPhotoForeignKey()
    class Meta:
        model = Node
        fields = ('content', 'photo', 'owner')

This example is using Django REST Framework version 3.

like image 33
Aidas Bendoraitis Avatar answered Nov 10 '22 08:11

Aidas Bendoraitis


I would deal with this by overriding get_serializer_class to dynamically return a serializer class at runtime, setting the choices option on the field there:

def get_serializer_class(self, ...):
    user = self.request.user
    owner_choices = ...  # However you want to restrict the choices

    class ImageSerializer(serializers.ModelSerializer):
        owner = serializers.Field('owner.username', choices=owner_choices)

        class Meta:
            model = Image
            fields = ('file', 'owner')

    return ImageSerializer
like image 10
Tom Christie Avatar answered Nov 10 '22 08:11

Tom Christie


class CustomForeignKey(serializers.PrimaryKeyRelatedField):
    def get_queryset(self):
        return Table.objects.filter(is_active=True)

class Serializer(serializers.ModelSerializer):
    (...)
   table= CustomForeignKey()
   class Meta:
   (...)

even more easy is :

class Serializer(serializers.ModelSerializer):
    (...)
    table = serializers.PrimaryKeyRelatedField(queryset=Table.objects.filter(is_active=True)) 
    class Meta:
    (...)
like image 4
Sérgio Avatar answered Nov 10 '22 06:11

Sérgio