chronox chronox - 3 years ago 68
Python Question

Django Rest Api filter field's select options based on request.user

I am currently working on a django rest framework api which involves displaying a list of campaigns and allowing user to create new campaign.

On the browsable api, I managed to display the list of campaigns that I wanted as well as have a form for the user to create new campaign.

This is a screenshot of the form that the user is using for creating new campaign.

A screenshot of the form on browsable API

While everything is working, I faced an issue that I do not have any idea how to solve even after reading the documentation.

As you can see on the screenshot, there is a clist field that allows user to select the contact list he/she want the campaign invitations to be sent to. However, I want to make sure only the contact lists created by the user's company are shown in that field (currently, all the contact lists from different companies can be selected).

Here is the codes in the api.py:

class EditCampaignViewSet(ModelViewSet):
queryset = Campaign.objects.all()
serializer_class = EditCampaignSerializer
parser_classes = (MultiPartParser, FormParser)

def get_serializer_context(self):
return {'request': self.request}

def list(self, request, p_uuid=None, type=None, *args, **kwargs):
company = request.user.profile.company
queryset = Campaign.objects.filter(company=company,
product__uuid=p_uuid,
deleted=False,
campaign_type=type)\
.order_by('-created')\
.prefetch_related('user__profile')
serializer = EditCampaignSerializer(queryset, many=True)
return Response(serializer.data)


This is the serializers.py

class EditCampaignSerializer(serializers.ModelSerializer):
class Meta:
model = Campaign
fields = ('id', 'campaign_id', 'campaign_type', 'name', 'product', 'description', 'status', 'actual_file_name',
'pdf_file', 'download', 'header', 'body', 'footer', 'company', 'created', 'updated', 'deleted',
'clist', 'user')
read_only_fields = ('id', 'campaign_id', 'campaign_type', 'product', 'status', 'actual_file_name', 'company', 'created',
'updated', 'deleted', 'user')

def __init__(self, *args, **kwargs):
super(EditCampaignSerializer, self).__init__(*args, **kwargs)
user = self.context['request'].user
self.fields['clist'] = ChoiceField(choices=CList.objects.filter(company=user.profile.company))


I am still pretty new to django rest framework, so please pardon me if the answer is obvious.

Answer Source

Not sure what your models look like, but something like this will work:

views.py:

class EditCampaignViewSet(ModelViewSet):
    ...

    def get_serializer_context(self):
        return {'request': self.request}

serializers.py:

class EditCampaignSerializer(serializers.ModelSerializer):

    class Meta:
        ...
        ...

    def __init__(self, *args, **kwargs):
        super(EditCampaignSerializer, self).__init__(*args, **kwargs)
        user = self.context['request'].user
        self.fields['clist'] = ChoiceField(choices=ContactList.objects.filter(company__user=user))
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download