drf-axios-middleware

website·Indexed 29 days ago

https://singularit-de.github.io/drf-axios-middleware/

An Axios middleware for Django REST Framework (DRF) that provides TypeScript support and utilities for handling filter configurations. Includes features such as the FilterSetConfig type, convertFilterSetConfig function, and support for nested fields and custom filter handlers.

Tokens
5.4K
Snippets
40
Records
42
Agent score
72%

What's inside drf-axios-middleware

  1. Apply drf-axios-middleware to an Axios instance

    To use the DRF Axios middleware, import applyDrfMiddleware and wrap your Axios instance creation. This allows you to pass a configuration object to customize the middleware's behavior.
    import axios from 'axios';
    import applyDrfMiddleware from '@singularit/drf-axios-middleware';
    
    const api = applyDrfMiddleware(axios.create(), {
        // config
    });
  2. Filter API requests using drf-axios-middleware

    The @singularit/drf-axios-middleware package provides a middleware for axios that introduces a filterSet parameter to the request configuration. This parameter allows developers to define filters using a structured object that the middleware converts into valid query parameters accepted by the Django Rest Framework (DRF).

    The filterSet object follows this structure:

    • Key: The field name to filter on.
    • Value: An object where the key is the operator (e.g., gte) and the value is the filter value, or a nested object for further field specification.
    import axios from 'axios'
    import applyDrfMiddleware from '@singularit/drf-axios-middleware'
    
    // Initialize axios with the DRF middleware
    const api = applyDrfMiddleware(axios.create())
    
    // Example: Fetch all users with id >= 15
    api.get('/api/v1/users/', {
      filterSet: {
        id: { gte: 15 }
      }
    }).then((response) => {
        console.log(response.data)
    });
  3. Apply drf-axios-middleware to an Axios instance

    To integrate the DRF middleware, wrap an Axios instance (created via axios.create()) using the applyDrfMiddleware function. This allows you to pass a configuration object to customize the middleware's behavior.
    import axios from 'axios';
    import applyDrfMiddleware from '@singularit/drf-axios-middleware';
    
    const api = applyDrfMiddleware(axios.create(), {
        // config
    });
  4. Restrict allowed filters using Key-Configuration

    You can specify which filters are permitted for specific attributes by providing a second generic parameter to FilterSetConfig. Attributes not mentioned in the key configuration will continue to allow all default filters. Note that the value filter cannot be excluded.
    interface CategoryKeyConfig {
        name : 'exact' | 'startwith' | 'endswith'
    }
    
    // Only 'exact', 'startwith', and 'endswith' are allowed for the 'name' attribute
    const config: FilterSetConfig<Category, CategoryKeyConfig> = {
        name: {
            exact: 'Fantasy'
        }
    };
  5. Map a single filter operator to multiple query parameters

    You can use the filterHandler to expand a single filter operator into multiple parameters. For example, a between operator can be mapped to both gte (greater than or equal to) and lte (less than or equal to) parameters in the resulting URL.
    import axios from 'axios';
    import applyDrfMiddleware from '@singularit/drf-axios-middleware';
    
    const api = applyDrfMiddleware(axios.create(), {
        filterHanlder: {
            between: (key, value) => {
                return [
                    {key: 'gte', value: value[0]},
                    {key: 'lte', value: value[1]}
                ]
            }
        }
    });
    
    // get all users with id between 1 and 99
    api.get('/api/v1/users/', {filterSet: {id: {between: [1, 99]}}}).then((response) => {
        console.log(response.data);
    });
    
    // Resulting request: GET /api/v1/users/?id__gte=1&id__lte=99
  6. Use a custom 'between' filter to generate gte and lte parameters

    To implement a 'between' filter that generates both a 'greater than or equal to' (gte) and 'less than or equal to' (lte) query parameter, define a between handler in the filterHanlder configuration that returns an array of two parameter objects.
    import axios from 'axios';
    import applyDrfMiddleware from '@singularit/drf-axios-middleware';
    
    const api = applyDrfMiddleware(axios.create(), {
        filterHanlder: {
            between: (key, value) => {
                return [
                    {key: 'gte', value: value[0]},
                    {key: 'lte', value: value[1]}
                ]
            }
        }
    });
    
    // Request for users with id between 1 and 99
    // Resulting request: GET /api/v1/users/?id__gte=1&id__lte=99
    api.get('/api/v1/users/', {filterSet: {id: {between: [1, 99]}}}).then((response) => {
        console.log(response.data);
    });
  7. Implement a custom 'notIn' filter handler

    Since notin is not a default operator in Django Rest Framework, you must implement the filter logic on the server side and map it in the middleware using a custom handler. Note that the exact query parameter syntax (e.g., id__notin) depends on your server's Array Serializer configuration.
    import axios from 'axios';
    import applyDrfMiddleware from '@singularit/drf-axios-middleware';
    
    const api = applyDrfMiddleware(axios.create(), {
        filterHanlder: {
            notIn: (key, value) => {
                return [{key: 'notin', value: value}]
            }
        }
    });
    
    // Request for all users with id NOT IN [1, 2, 3]
    // Resulting request: GET /api/v1/users/?id__notin=1,2,3
    api.get('/api/v1/users/', {filterSet: {id: {notIn: [1, 2, 3]}}}).then((response) => {
        console.log(response.data);
    });
  8. Filter a nested field with multiple operators

    You can apply multiple filter operators (such as gte and lte) to a single nested field by providing multiple keys within the operator object. This allows for range filtering on related models.
    import axios from 'axios';
    import applyDrfMiddleware from '@singularit/drf-axios-middleware';
    
    const api = applyDrfMiddleware(axios.create());
    
    // Request users where profile id is between 15 and 99
    // Resulting request: GET /api/v1/users/?profile__id__gte=15&profile__id__lte=99
    api.get('/api/v1/users/', {
      filterSet: { 
        profile: { 
          id: { 
            gte: 15, 
            lte: 99 
          } 
        } 
      }
    }).then((response) => {
        console.log(response.data);
    });
  9. Filter a nested field using multiple operators

    To apply multiple constraints (such as a range) to a single nested field, provide multiple operator keys within the field's value object. For example, providing both gte and lte for a nested ID will generate multiple query parameters for that field.
    import axios from 'axios';
    import applyDrfMiddleware from '@singularit/drf-axios-middleware';
    
    const api = applyDrfMiddleware(axios.create());
    
    // get all users with profile id >= 15 and id <= 99
    api.get('/api/v1/users/', {
      filterSet: { profile: { id: { gte: 15, lte: 99 } } }
    }).then((response) => {
        console.log(response.data);
    });
    
    // Resulting request: GET /api/v1/users/?profile__id__gte=15&profile__id__lte=99
  10. Convert filter configurations using convertFilterSetConfig

    The convertFilterSetConfig function is used when writing custom middleware to transform a FilterSetConfig object into a flat object where keys are converted to the Django REST Framework (DRF) double-underscore format (e.g., converting { number: { gt: 123 } } to { number__gt: 123 }).
    import { convertFilterSetConfig, FilterSetConfig } from '@singularit/drf-axios-middleware'
    
    interface Data {
        number: number
        text?: string
        new?: boolean
    }
    
    const simpleConfig: FilterSetConfig<Data> = {
        number: { gt: 123 },
        text: { gt: 'string' },
    }
    
    console.log(convertFilterSetConfig(simpleConfig))
    // Output: { number__gt: 123, text__gt: 'string' }