Darren Alfonso
Darren Alfonso

Reputation: 1390

Django REST Framework Filter Queryset Based On URL

When user visits "baseurl/companies/6/inquiry/", I know that the company_id is 6.

Then user then has the option to create an inquiry with specific products, but should only see the products that belong to company 6.

Here's my viewset:

class InquiryViewSet(viewsets.ModelViewSet):
    queryset = Inquiry.objects.all()
    serializer_class = InquirySerializer

    def get_serializer(self, *args, **kwargs):
        serializer_class = self.get_serializer_class()
        context = self.get_serializer_context()
        return serializer_class(*args, company_id=self.kwargs['company_id'], context=context, **kwargs)

Here's my serializer:

class InquirySerializer(serializers.ModelSerializer):
    def __init__(self, *args, company_id=None, **kwargs):
        super(InquirySerializer, self).__init__(*args, **kwargs)
        company_set = Company.objects.filter(pk=company_id)
        self.fields['company'].queryset = company_set

    company = serializers.HyperlinkedRelatedField(many=False,
                                                  view_name='company-detail',
                                                  queryset=Company.objects.all())
    inquirer = UserPKField(many=False)
    is_anonymous = serializers.BooleanField
    product_rows = CompanyProductField(many=True, company_id= 'Want to access company_id in __init__')

    class Meta:
        model = Inquiry
        fields = ('pk', 'company', 'inquirer_email', 'inquirer', 'is_anonymous', 'inquiry_date', 'product_rows')
        read_only_fields = ('inquirer', 'inquiry_date')

And here's the CompanyProductField

class CompanyProductField(serializers.PrimaryKeyRelatedField):
    def __init__(self, *args, company_id=None, **kwargs):
        super(CompanyProductField, self).__init__(*args, **kwargs)
        self.company_id = company_id

    def get_queryset(self):
        product_query = Q(company__pk=self.company_id)
        return Product.objects.filter(product_query)

There has to be a simple way I can access the company_id that's already in InquirySerializer's init method and just pass that on, but I'm stumped.

Upvotes: 3

Views: 965

Answers (3)

A. J. Parr
A. J. Parr

Reputation: 8026

class InquirySerializer(serializers.ModelSerializer):
    def __init__(self, *args, **kwargs):
        company_id = kwargs.pop('company_id')
        self.company_id = company_id
        super().__init__(*args, **kwargs)

    product_rows = CompanyProductField(many=True)

class CompanyProductField(serializers.PrimaryKeyRelatedField):
    def get_queryset(self):
        return Product.objects.filter(company_id=self.root.company_id)

The self.root attribute on the CompanyProductField class will refer to the instance of InquirySerializer in this case.

Upvotes: 2

zaidfazil
zaidfazil

Reputation: 9245

You could just remove the self from self.kwargs['company_id'] in yourget_serializer()` method,

def get_serializer(self, *args, **kwargs):
    serializer_class = self.get_serializer_class()
    kwargs['context'] = self.get_serializer_context()
    return serializer_class(company_id=kwargs['company_id'], *args, **kwargs)

Upvotes: 0

Darren Alfonso
Darren Alfonso

Reputation: 1390

For now, I'm going to use this somewhat "hacky" way of doing this.

In my serializers.py file I added a global variable:

from rest_framework import serializers
from .models import *
from django.db.models import Q

global_company_id = 0

Then in the init method for my serializer I set the global_company_id:

class InquirySerializer(serializers.ModelSerializer):
def __init__(self, *args, company_id=None, **kwargs):
    super(InquirySerializer, self).__init__(*args, **kwargs)
    company_set = Company.objects.filter(pk=company_id)
    self.fields['company'].queryset = company_set
    global global_company_id
    global_company_id = company_id

company = serializers.HyperlinkedRelatedField(many=False,
                                              view_name='company-detail',
                                              queryset=Company.objects.all())
inquirer = UserPKField(many=False)
is_anonymous = serializers.BooleanField
product_rows = CompanyProductField(many=True)

And in the CompanyProductField I accessed the global_company_id:

class CompanyProductField(serializers.PrimaryKeyRelatedField):
def get_queryset(self):
    product_query = Q(company__pk=global_company_id)
    return Product.objects.filter(product_query)

Upvotes: 1

Related Questions