Skip to main content

Overview

The E-commerce API provides powerful filtering, searching, and pagination capabilities to help you retrieve exactly the data you need. These features are built on Django REST Framework and django-filters.

Pagination

All list endpoints use Limit-Offset pagination by default.

Configuration

Pagination settings are defined in config/settings.py:167-182:
REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
    'PAGE_SIZE': 10,
}

Parameters

limit
integer
default:"10"
Number of results to return per page
offset
integer
default:"0"
Starting position in the result set

Example Requests

GET /api/v1/products/
# Returns first 10 products

Response Format

Paginated responses include metadata:
{
  "count": 157,
  "next": "http://api.example.com/api/v1/products/?limit=10&offset=20",
  "previous": "http://api.example.com/api/v1/products/?limit=10&offset=0",
  "results": [
    {
      "id": 11,
      "name": "Product Name",
      // ... product fields
    },
    // ... more products
  ]
}
count
integer
Total number of items across all pages
next
string
URL for the next page (null if no more pages)
previous
string
URL for the previous page (null if on first page)
results
array
Array of items for the current page

Calculating Pages

# Formula for offset
offset = (page_number - 1) * limit

# Example: Get page 5 with 20 items per page
# offset = (5 - 1) * 20 = 80
GET /api/v1/products/?limit=20&offset=80

Filtering

Filter results by specific field values using query parameters.

Global Configuration

REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': [
        'django_filters.rest_framework.DjangoFilterBackend',
        'rest_framework.filters.SearchFilter'
    ]
}

Product Filtering

The Product list endpoint supports filtering by multiple fields. Location: catalogue/views.py:80
class ProductListView(GenericAPIView):
    filterset_fields = ["category", "is_available", "store"]

Available Filters

category
integer
Filter by category ID
is_available
boolean
Filter by availability (true or false)
store
integer
Filter by store/vendor ID

Example Requests

GET /api/v1/products/?category=5
# Returns products in category 5

Category Filtering

Products can also be filtered by category slug through the URL path: Location: catalogue/urls.py:17
path("products/categories/<slug:slug>/", ProductListView.as_view())

Example

GET /api/v1/products/categories/electronics/
# Returns all products in the "electronics" category
This approach uses the category slug instead of numeric ID, making URLs more readable.
Perform text-based searches across multiple fields. The Product list endpoint searches across multiple fields: Location: catalogue/views.py:81
class ProductListView(GenericAPIView):
    search_fields = ["name", "category__name", "label", "store__brand_name"]

Search Fields

  • name - Product name
  • category__name - Category name (related field)
  • label - Product label
  • store__brand_name - Store brand name (related field)
Double underscores (__) indicate searches across related models (Django’s lookup syntax).

Example Requests

GET /api/v1/products/?search=laptop
# Returns products matching "laptop" in any search field
Search categories by name: Location: catalogue/views.py:35
class CategoryListView(ListAPIView):
    search_fields = ["name"]
GET /api/v1/categories/?search=electronics
# Returns categories matching "electronics"

Combining Features

You can combine filtering, searching, and pagination in a single request.

Complex Query Example

GET /api/v1/products/?search=wireless&category=5&is_available=true&store=3&limit=20&offset=40
This query:
  1. Searches for “wireless” across name, category name, label, and brand
  2. Filters to category 5
  3. Filters to available products only
  4. Filters to store 3
  5. Returns 20 results (page 3)

Response Example

{
  "count": 87,
  "next": "http://api.example.com/api/v1/products/?search=wireless&category=5&is_available=true&store=3&limit=20&offset=60",
  "previous": "http://api.example.com/api/v1/products/?search=wireless&category=5&is_available=true&store=3&limit=20&offset=20",
  "results": [
    {
      "id": 41,
      "name": "Wireless Headphones Pro",
      "category": {
        "id": 5,
        "name": "Audio",
        "slug": "audio"
      },
      "store": {
        "id": 3,
        "brand_name": "TechStore"
      },
      "base_price": "149.99",
      "is_available": true,
      "rating": 4.5,
      "total_stock_level": 250
    }
    // ... 19 more products
  ]
}

Ordering

Products are ordered by default ordering specified in the model.

Default Product Ordering

Location: catalogue/models.py:56-57
class Product(BaseModel):
    class Meta:
        ordering = ["-total_sold", "-rating"]
Products are ordered by:
  1. total_sold (descending) - Most popular first
  2. rating (descending) - Highest rated first

Default Order Ordering

Location: orders/models.py:55
class Order(BaseModel):
    class Meta:
        ordering = ["-created"]
Orders are ordered by creation date (newest first).
Custom ordering via query parameters is not currently supported. Contact your API administrator if you need this feature.

Advanced Filtering Patterns

Building Dynamic Queries

Here are common patterns for building queries:
GET /api/v1/products/?is_available=true&limit=50
Returns first 50 available products from all stores.
GET /api/v1/products/?store=7&is_available=true
Returns all available products from store 7.
GET /api/v1/products/categories/electronics/?is_available=true&limit=24
Returns first 24 available electronics (e.g., for a category page).
GET /api/v1/products/?store=5&category=3&is_available=true
Returns available products in category 3 from store 5.
GET /api/v1/products/?search=laptop&is_available=true&limit=30
Returns first 30 available products matching “laptop”.
GET /api/v1/products/?store=12&is_available=false
Returns out-of-stock products for store 12.

Performance Tips

Use Appropriate Limits

Set limit based on your UI needs. Smaller pages load faster and reduce bandwidth.

Specific Filters

Add filters like is_available=true or store=X to reduce result sets.

Index-Friendly Queries

Filters on indexed fields (category, is_available, store) are optimized.

Avoid Deep Pagination

Large offset values (e.g., offset=10000) can be slow. Consider alternative approaches for deep pagination.

Error Handling

Invalid Filter Values

// Request: GET /api/v1/products/?category=invalid
{
  "category": [
    "Enter a valid integer."
  ]
}

Invalid Boolean

// Request: GET /api/v1/products/?is_available=yes
{
  "is_available": [
    "Must be a valid boolean."
  ]
}
Use true/false, 1/0, or True/False for boolean parameters.

Implementation Reference

View Configuration

Here’s how filtering and search are configured in the ProductListView: Location: catalogue/views.py:73-86
class ProductListView(GenericAPIView, LimitOffsetPagination):
    permission_classes = [AllowAny]
    serializer_class = ProductListSerializer
    filterset_fields = ["category", "is_available", "store"]
    search_fields = ["name", "category__name", "label", "store__brand_name"]

    def get_queryset(self):
        queryset = Product.objects.all()
        queryset = self.filter_queryset(queryset)
        return queryset
The filter_queryset() method automatically applies:
  • DjangoFilterBackend (for filterset_fields)
  • SearchFilter (for search_fields)

Next Steps

Product Endpoints

Explore the Product API endpoints

Data Models

Learn more about the data models

Build docs developers (and LLMs) love