Skip to main content

A library for handling common stuff in Django

Project description

DjKit

Installation

  • pip install djkit

Examples

Obfuscation

from djkit.utils import Obfuscator

Obfuscator.email("abcdqweqwe@test.com")  # abcdq****@test.com'
Obfuscator.obfuscate('my_super_confidential_secret')  # 'my_super_confidential_s*****'

Django rest framework related examples

# models.py
from django.db import models


class Human(models.Model):
    class Level(models.IntegerChoices):
        BEGINNER = 0
        INTERMEDIATE = 1
        ADVANCED = 2

    class MilitaryStatus(models.TextChoices):
        EXEMPTED = "exempted", "Exempted"
        SERVED = "served", "Served"
        POSTPONED = "postponed", "Postponed"

    name = models.CharField(max_length=128)
    level = models.IntegerField(choices=Level.choices)
    military_status = models.CharField(
        choices=MilitaryStatus.choices,
        max_length=128
    )
# serializers.py
from rest_framework import serializers
from djkit.rest_framework.serializers import EnumSerializer
from example.core import models


class HumanSerializer(serializers.ModelSerializer):
    level = EnumSerializer(enum=models.Human.Level)
    military_status = EnumSerializer(enum=models.Human.MilitaryStatus)

    class Meta:
        model = models.Human
        fields = [
            'id',
            'level',
            'military_status',
        ]

Example serialization

# wherever.py
from example.core.serializers import HumanSerializer
from example.core.models import Human

human = Human.objects.find(id=1)
serializer = HumanSerializer(human)  # level = BEGINNER, military_status = EXEMPTED

Example deserialization

# wherever.py
from example.core.serializers import HumanSerializer

data = {
    "level": "BEGINNER",
    "MILITARY_STATUS": "EXEMPTED",
}

instance = HumanSerializer(data=data)
instance.is_valid()
instance.save()

Got some endpoints that accept files in table formats? got you

  1. Assuming Pandas
import pandas as pd
from djkit.rest_framework.pandas import TableUploadField  # or PandasTableUploadField
from rest_framework import serializers


class MySerializer(serializers.ModelSerializer):
    file = TableUploadField()

    def create(self, validated_data):
        file: pd.DataFrame = validated_data['file']
        # do logic, don't do row based validation here
        return validated_data

    # optional method
    def validate_file_row(self, row, index, table_df):
        if row.iloc[0] == "X":
            row.iloc[0] = "Y"

        # return new row, or None and changes won't be reflected
        return row
  1. Assuming Pola.rs
import polars as pl
from djkit.rest_framework.polars import TableUploadField  # or PolarsTableUploadField
from rest_framework import serializers


class MySerializer(serializers.ModelSerializer):
    file = TableUploadField()

    def create(self, validated_data):
        file: pl.DataFrame = validated_data['file']
        # do logic, don't do row based validation here
        return validated_data

    # optional method
    def validate_file_row(self, row, index, table_df):
        # do polars logic, return new row or None
        return row
  • TableUploadField is write_only
  • TableUploadField is easily extended, use your own library if you want
from djkit.rest_framework.serializers import TableUploadField as BaseTableUploadField


def read_csv(source):
    return ...


def read_excel(source):
    return ...


class TableUploadField(BaseTableUploadField):
    handlers = {
        "csv": read_csv,
        "xlsx": read_excel,
        "xls": read_excel,
        "xlsm": read_excel,
        "xlsb": read_excel,
        "odf": read_excel,
        "ods": read_excel,
        "odt": read_excel,
    }

    def update_row(self, table_object: "YourLibraryDataFrame", index, new_row):
        """how your library updates the row"""

Supported formats are the keys in handlers

can_parse_csv = "csv" in field.allowed_upload_formats

Or

can_parse_csv = field.is_allowed_format('obj') # False

Custom kwargs for handlers in TableFieldUpload

from djkit.rest_framework.pandas import PandasTableUploadField
import pandas as pd


class Serializer(...):
    pandas_file = PandasTableUploadField(handler_kwargs={
        # by format
        "xlsx": {
            # args for read_excel would be here
            "engine": "openpyxl"
        },
        # or by reference
        pd.read_csv: {
            "delimiter": "\t"
        }
    })
  • The same logic applies to all TableUploadField subclasses.

  • djkit provides easily methods for overriding most of the logic.

  • If you want a field that does aggregation or something, override process_table on TableUploadField

Obfuscation

from djkit.rest_framework.serializers import ObfuscatedCharField, ObfuscatedEmailField, ObfuscatedFieldMixin


class MySerializer(...):
    email = ObfuscatedEmailField()  # in the API, it's obfuscated
    name = ObfuscatedCharField()  # same applies here


class MyCustomObfuscatedApiKeyField(ObfuscatedFieldMixin, MyApiKeyField):
    pass

Better error handling

REST_FRAMEWORK = {
    "DEFAULT_RENDERER_CLASSES": [
        "djkit.rest_framework.renderers.JSONRenderer"
    ]
}

This will change you response schema in case of errors to

response = {
    "field_errors": [],
    "non_field_errors": []
}

Contributions

To run the project locally

  • pip install poetry
  • poetry install
  • poetry shell
  • pre-commit install

To build the docs

  • make html

To run the tests

  • pytest .

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

djkit-1.0.9.tar.gz (13.5 kB view hashes)

Uploaded Source

Built Distribution

djkit-1.0.9-py3-none-any.whl (15.2 kB view hashes)

Uploaded Python 3

Supported by

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