Queryset based on Django REST filter based on url
When a user visits "baseurl / companies / 6 / request /", I know that company_id is 6.
The user is then able to create a request with specific products, but should only see products belonging to 6 company.
Here's my viewet:
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 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 should be an easy way to access the company_id that is already in the InquirySerializer init method , and just pass that on, but I'm stumped.
source to share
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 attribute self.root
in the CompanyProductField class will refer to the InquirySerializer instance in this case.
source to share
I am currently going to use this "hacky" way to do it.
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 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)
source to share
You can just remove the method self
from self.kwargs['company_id'] in your
get_serializer () `,
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)
source to share