0

Hi I'm new to Django and the Django rest framework so my terminology may be off.

I'm trying to build an API that gives back a list of items from a model but filtered based on fields in another related model.

I'll provide my current view and serializer classes and models

class service(models.Model):
    name = models.CharField(max_length=50)
    vendor = models.CharField(max_length=50)
    version = models.CharField(max_length=10)
    registration_status = models.BooleanField(default=False)

class service_network(models.Model):

    service = models.OneToOneField(
        service,
        related_name='network',
        on_delete=models.CASCADE,
        primary_key=True,
    )
    forwarded_port = models.CharField(max_length=50)

class ServiceNetworkSerializer(serializers.ModelSerializer):
    class Meta:
        model = service_network
        fields = '__all__'

class ServiceSerializer(serializers.ModelSerializer):
    network = ServiceNetworkSerializer()

    class Meta:
        model = service
        fields = [
            'id',
            'name',
            'vendor',
            'version',
            'registration_status',
            'network',
        ]
class ServiceAPI(ModelViewSet):
    queryset = service.objects.all()
    serializer_class = ServiceSerializer
    filterset_fields = '__all__'

Currently I can get back lists using a URL query string

{{baseUrl}}/engine/service?registration_status=true

What I want to do is something like this

{{baseUrl}}/engine/service/network?forwarded_port=8080

Which I would expect to give back a list of services where the related network field "forwarded_port" is equal to 8080.

Is there another way to query this API? Maybe using a POST with a body containing the query? If there something in the DOCS that I can read, I've tried to look through filtering and querysets but I wasn't able to find anything that would do this out of the box

I'm also new to stackoverflow and I've tried to keep my question short with as much relevant information so if there anything missing I'd be happy to edit my question

2 Answers 2

1

I was able to solve this using the following queryset override

    def get_queryset(self):
    if len(self.request.GET) > 0:
        query_set = {}
        for query in self.request.GET:
            query_set[query] = self.request.GET.get(query)
        return service.objects.filter(**query_set)
    else:
        return service.objects.all()

What this does is lets you filter fields without explicitly specifying what they are, in cases when you have many fields that need filtering. I also have to say as I'm not experienced with Django, I'm not sure what kind of errors this may bring up but its a hack that's worked for me. If I find this is really bad I'll come back and remove this.

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

Comments

0

Try this:

{{baseUrl}}/engine/service?network__forwarded_port=8080

Probably it works.

Doc: https://docs.djangoproject.com/en/dev/topics/db/queries/#lookups-that-span-relationships-1

EDIT:

If the above answer doesn't work, you can change the ServiceApi class and filter by yourself:

class ServiceAPI(ModelViewSet):
    def get_queryset(self):
        if self.request.GET.get(network__forwarded_port)
            return service.objects.filter(network__forwarded_port = self.request.GET.get(network__forwarded_port))
        else:
            return service.objects.all()
    serializer_class = ServiceSerializer
    filterset_fields = '__all__'

4 Comments

Thanks for your swift response, the URL did not work, it gave back the full set of, ``` [ { "id": 1, "name": "InfluxDB", "vendor": "InfluxData", "version": "latest", "registration_status": true, "network": { "service": 1, "forwarded_port": "8086" } } ] ```
I have edited my answer. Try it.
is there a way to filter for all fields, There are many more fields and models I've just left them out of this question as I didn't feel it was needed, should I add them in the question to better reflect the problem? , I'll look through the docs, Thank you btw this worked
According to the doc: "you can use both an overridden .get_queryset() and generic filtering together, and everything will work as expected" django-rest-framework.org/api-guide/filtering/…

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.