Reputation: 11
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
Upvotes: 0
Views: 2584
Reputation: 11
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.
Upvotes: 1
Reputation: 1094
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__'
Upvotes: 0