Implementing API query parameters and joining HNG 11
Published: 2024-06-29 14:42:06

#### Introduction

A while ago, a friend challenged me to build a simple CRUD REST API. One of the requirements was to implement filtering through query parameters. At the time, this seemed daunting because I had no idea how to do that with Django REST Framework (DRF). In this article, I’ll explain how I tackled this challenge.

#### Project Overview

The project was a basic CRUD REST API—a student API where students can input data like `name`, `matric_number`, and `course`, which gets stored in the database. The API includes a query parameter for `matric_number`, allowing users to retrieve a student by their matric number, like this: `https://api.com/v1/students?matric_number=2252ha123`.

#### Understanding Query Parameters

Before diving into the solution, let’s understand what a query parameter is. It’s the part of a URL that comes after the `?` symbol. For example, in `https://www.google.com/search?q=hng11`, the query parameter is `q=hng11`. The parameter is a key-value pair, and multiple query parameters are separated by the `&` symbol.

#### Finding the Solution

To find a solution, I first checked the [Django REST Framework documentation](https://www.django-rest-framework.org/api-guide/filtering/#filtering-against-query-parameters), which perfectly described how to implement filtering with query parameters.

#### Step-by-Step Implementation

2.  **Creating a Model** 
Let's create a `Student` model with a few fields:
```python
from django.db import models


class Student(models.Model):
    firstname = models.CharField(max_length=100, blank=False)
    lastname = models.CharField(max_length=100, blank=False)
    matric_number = models.CharField(max_length=10, blank=False)
    course = models.CharField(max_length=255, blank=False)
    created = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return "{} {}".format(self.firstname, self.lastname)
```
2. **Creating a Serializer** Next, create a model serializer to handle serialization:
```python
from rest_framework import serializers

from api.models import Student


class StudentSerialzer(serializers.ModelSerializer):

    class Meta:
        model = Student
        fields = ["id", "firstname", "lastname", "matric_number", "course"]
```
3. **Creating a View** For this, I'll use a viewset. Here’s what your `views.py` should look like:
    ``` python
    from rest_framework import viewsets

    from api.models import Student
    from api.serializers import StudentSerialzer


    class StudentViewSet(viewsets.ModelViewSet):
        queryset = Student.objects.all()
        serializer_class = StudentSerialzer

    ```
    at this point, it's just a basic CRUD view

4. **Overriding the Default Queryset** By default, this view operates on all `Student` objects. To filter with query parameters, we override the `get_queryset()` function:
    ```python
    class StudentViewSet(viewsets.ModelViewSet):
    queryset = Student.objects.all()
    serializer_class = StudentSerialzer

    def get_queryset(self):
        matric_number = self.request.query_params.get('matric_number')
        if matric_number is not None:
            return Student.objects.filter(matric_number=matric_number)
        else:
            return self.queryset
    ```

  
    **Line-by-line Analysis:**
    ```python
    matric_number = self.request.query_params.get('matric_number')
    ```
    Here we want to get the value from the query parameter, remember it's a key-value pair

    ```python
    if matric_number is not None:
    ```
    now, we're checking if the query parameter is not empty, we only want to override the default queryset if a filter is provided
    ```python
        return Student.objects.filter(matric_number=matric_number)
    ```
    if the query parameter is not empty then filter the objects with the provided `matric_number`
    ```python
    else:
        return self.queryset
    ```
    return the default queryset if there is no query parameter


### Conclusion

Now, you can run your API like any other DRF project using `python manage.py runserver`. Create a few students with the browsable API and test the query parameters. That’s how I implemented them using DRF—it just took some documentation reading.

----------

### Joining HNG 11

My name is Franklin, and I'm a Backend Software Engineer in training. I love Python and have been learning backend development with Django and DRF. While learning from articles, tutorials, and videos is great, I feel I need hands-on experience to become the kind of engineer I aspire to be. I hope to gain this experience at the HNG 11 internship.

This internship will provide real-world experience, challenges, and interactions with fellow developers on the same journey. If you feel you need that level up, join me at the HNG 11 internship! [Visit the webpage](https://hng.tech/internship) to learn more. You can also register for a premium membership for more perks and benefits. [Register for premium](https://hng.tech/premium).

Thank you for reading my first article on DEV.to. I hope to write many more and improve my technical writing skills.