3

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.

3 Answers 3

2
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.

Sign up to request clarification or add additional context in comments.

1 Comment

self.root.company_id is what I was looking for!
1

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)

1 Comment

Why don't you simply set a company_id attribute in product_rows field, the same way you set a queryset in company field ?
0

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)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.