简体   繁体   中英

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.

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.

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)

You could just remove the self from self.kwargs['company_id'] in your get_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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM