Skip to main content

A collection of useful mixins for Django REST Framework ViewSets and APIViews

Project description

django-api-mixins

A collection of useful mixins for Django REST Framework ViewSets and APIViews to simplify common API patterns.

Features

  • APIMixin: Dynamic serializer selection based on action (create, update, list, retrieve)
  • ModelMixin: Automatic filter field generation for Django models
  • RelationshipFilterMixin: Automatic filtering for reverse relationships and direct fields
  • RoleBasedFilterMixin: Role-based queryset filtering for multi-tenant applications

Installation

pip install django-api-mixins

Requirements

  • Python 3.8+
  • Django 3.2+
  • Django REST Framework 3.12+

Quick Start

APIMixin

Use different serializers for different actions (create, update, list, retrieve):

from rest_framework import viewsets
from django_api_mixins import APIMixin

class UserViewSet(APIMixin, viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer  # Default serializer
    create_serializer_class = UserCreateSerializer  # For POST requests
    update_serializer_class = UserUpdateSerializer  # For PUT/PATCH requests
    list_serializer_class = UserListSerializer  # For GET list requests
    retrieve_serializer_class = UserDetailSerializer  # For GET detail requests

The mixin also automatically handles list data in requests:

# POST /api/users/
# Body: [{"name": "User1"}, {"name": "User2"}]
# Automatically sets many=True for list data

ModelMixin

Automatically generate filter fields for all model fields:

from django.db import models
from django_api_mixins import ModelMixin

class Product(models.Model, ModelMixin):
    name = models.CharField(max_length=100)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    created_at = models.DateTimeField(auto_now_add=True)
    is_active = models.BooleanField(default=True)

# Automatically generates filter fields:
# - name: exact, in, isnull
# - price: exact, in, isnull, gte, lte
# - created_at: exact, in, isnull, gte, lte
# - is_active: exact, in, isnull

Use in your ViewSet with Django Filter Backend:

from rest_framework import viewsets
from django_filters.rest_framework import DjangoFilterBackend
from django_api_mixins import ModelMixin

class ProductViewSet(viewsets.ModelViewSet):
    queryset = Product.objects.all()
    filter_backends = [DjangoFilterBackend]
    filterset_fields = Product.get_filter_fields()  # Use auto-generated fields

Filter related models:

# Get filter fields for a related model
filter_fields = Product.get_filter_fields_for_related_model('category')
# Returns: {'category__name': [...], 'category__id': [...], ...}

# Get filter fields for a foreign key field
filter_fields = Order.get_filter_fields_for_foreign_fields('product')
# Returns: {'product__name': [...], 'product__price': [...], ...}

RelationshipFilterMixin

Automatically apply filters for reverse relationships and direct fields:

from rest_framework import viewsets
from django_api_mixins import RelationshipFilterMixin

class OrderViewSet(RelationshipFilterMixin, viewsets.ModelViewSet):
    queryset = Order.objects.all()
    
    # Define which reverse relationship filters to allow
    reverse_relation_filters = [
        'customer__name',
        'customer__email',
        'product__category__name',
    ]
    
    # Define which filters support list/array values
    listable_filters = ['customer__id', 'product__id']

Important: Place the mixin BEFORE the ViewSet class:

# ✅ Correct
class OrderViewSet(RelationshipFilterMixin, viewsets.ModelViewSet):
    pass

# ❌ Wrong
class OrderViewSet(viewsets.ModelViewSet, RelationshipFilterMixin):
    pass

Usage examples:

# Filter by customer name
GET /api/orders/?customer__name=John

# Filter by multiple customer IDs (listable filter)
GET /api/orders/?customer__id=1,2,3
# or
GET /api/orders/?customer__id=[1,2,3]

# Filter by product category
GET /api/orders/?product__category__name=Electronics

RoleBasedFilterMixin

Automatically filter querysets based on user roles:

from rest_framework import viewsets
from django_api_mixins import RoleBasedFilterMixin

class OrderViewSet(RoleBasedFilterMixin, viewsets.ModelViewSet):
    queryset = Order.objects.all()
    
    # Required: field name to filter on
    role_filter_field = 'operator_type'
    
    # Optional: roles that see all data
    admin_roles = ['admin', 'super_admin']
    
    # Optional: roles that see no data
    excluded_roles = ['guest']
    
    # Optional: custom role to field value mapping
    role_mapping = {
        'custom_role': 'custom_value',
        'manager': 'MGR',
    }

Important: Place the mixin BEFORE the ViewSet class:

# ✅ Correct
class OrderViewSet(RoleBasedFilterMixin, viewsets.ModelViewSet):
    pass

# ❌ Wrong
class OrderViewSet(viewsets.ModelViewSet, RoleBasedFilterMixin):
    pass

How it works:

  1. Extracts the user's role from user.role.name
  2. Admin roles see all data (no filtering)
  3. Excluded roles see no data (empty queryset)
  4. Other roles are filtered by role_filter_field = role_name (or mapped value)

Example:

# User with role.name = 'operator'
# Model has operator_type field
# Automatically filters: Order.objects.filter(operator_type='operator')

# User with role.name = 'admin'
# Sees all orders (no filtering)

# User with role.name = 'guest'
# Sees no orders (queryset.none())

FieldLookup Enum

The package includes a FieldLookup enum for consistent lookup naming:

from django_api_mixins import FieldLookup

FieldLookup.EXACT      # "exact"
FieldLookup.ICONTAINS  # "icontains"
FieldLookup.CONTAINS   # "contains"
FieldLookup.ISNULL     # "isnull"
FieldLookup.GTE        # "gte"
FieldLookup.LTE        # "lte"
FieldLookup.IN         # "in"

Combining Mixins

You can combine multiple mixins:

from rest_framework import viewsets
from django_api_mixins import (
    APIMixin,
    RelationshipFilterMixin,
    RoleBasedFilterMixin,
)

class OrderViewSet(
    RelationshipFilterMixin,
    RoleBasedFilterMixin,
    APIMixin,
    viewsets.ModelViewSet
):
    queryset = Order.objects.all()
    serializer_class = OrderSerializer
    create_serializer_class = OrderCreateSerializer
    
    role_filter_field = 'operator_type'
    reverse_relation_filters = ['customer__name', 'product__category__name']
    listable_filters = ['customer__id']

Note: The order of mixins matters! Place filtering mixins before the ViewSet class.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT License - see LICENSE file for details.

Support

For issues, questions, or contributions, please visit the GitHub repository.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django_api_mixins-0.1.1.tar.gz (8.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

django_api_mixins-0.1.1-py3-none-any.whl (8.7 kB view details)

Uploaded Python 3

File details

Details for the file django_api_mixins-0.1.1.tar.gz.

File metadata

  • Download URL: django_api_mixins-0.1.1.tar.gz
  • Upload date:
  • Size: 8.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.8

File hashes

Hashes for django_api_mixins-0.1.1.tar.gz
Algorithm Hash digest
SHA256 9dcf169d75bfadf4bb387d4c59a0116e6260060b6e939fce3b700d0ccb3521c4
MD5 2d264d87edca5878562ee110ca5c2d15
BLAKE2b-256 c0035987ccdb959e18a98c8e40e719041ba7e8d39a7be3e3b56b154ee6961b26

See more details on using hashes here.

File details

Details for the file django_api_mixins-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for django_api_mixins-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 230dbf9732e35088019954390ab04d21cdca3b99cbd83a8df944cce2d41f1544
MD5 dad5e436ff8cf17ba755676ac7fb8848
BLAKE2b-256 94da18dc40c46fcb880223b7f742b2d6aa9002593bf95f621a829f993f036ee3

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page