Question

I have a simple DRF application that is used to manage databases/users.

I have my normal Django users. Each User can 'own' as set of Schemas (databases) Each User can 'own' a set of DatabaseUsers (different to the Django users) There exists a many-many relationship between Schemas and DatabaseUsers (a Schema has many DatabaseUsers, and a DatabaseUser can access many schemas). But Schemas and DatabaseUsers are owned by a single Django User.

This all works absolutely fine in the JSON view - I have appropriate filters so that a user may only access their own Schemas or DatabaseUsers.

However, when using the Web API, when a User goes to create a new schema, DRF helpfully lists all the DatabaseUsers in the system for them to select from, rather than just their own users:

Too many users listed here In the above image, userA_dbUser1, 2, 3 are owned by userA and so shouldn't be visible by userB. I don't know how this information gets populated by DRF as it doesn't appear to go through the serializer. How do I prevent the DRF web API from listing the DatabaseUsers that belong to a different user.

models:

class DatabaseUser(models.Model):
    owner = models.ForeignKey('auth.User')
    name = models.CharField(max_length=128, primary_key=True)
    def __str__(self):
        return self.name

class Schema(models.Model):
    owner = models.ForeignKey('auth.User')
    title = models.CharField(max_length=100, primary_key=True)
    breed = models.ForeignKey('schema.Breed')
    users = models.ManyToManyField(DatabaseUser)
    def __str__(self):
        return "%s (%s)" % (self.title, self.breed)

views:

class SchemaMixin(object):
    queryset = Schema.objects.all()
    serializer_class = SchemaSerializer
    def get_queryset(self):
        # Only list the objects that are owned by the current user
        return Schema.objects.filter(owner = self.request.user)

    def pre_save(self, obj):
        obj.owner = self.request.user

class SchemaList(SchemaMixin, ListCreateAPIView):
    pass

class SchemaDetail(SchemaMixin, RetrieveUpdateDestroyAPIView):
    pass
Was it helpful?

Solution

Dear people of the future. schillingt1's link above lead me to the solution. Here's the code that you need to add to the serializer:

class SchemaSerializer(serializers.ModelSerializer):
    ...

    def get_fields(self, *args, **kwargs):
        # Override this method so that the list of DatabaseUsers presented in the browseable API
        # is restricted to the DatabaseUsers owned by the current user.
        fields = super(SchemaSerializer, self).get_fields(*args, **kwargs)
        view = self.context['view']
        owner = view.request.user
        fields['users'].queryset = fields['users'].queryset.filter(owner=owner)
        return fields
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top