pip install djkit
from djkit.utils import Obfuscator
Obfuscator.email("[email protected]") # abcdq****@test.com'
Obfuscator.obfuscate('my_super_confidential_secret') # 'my_super_confidential_s*****'
# 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',
]
# 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
# wherever.py
from example.core.serializers import HumanSerializer
data = {
"level": "BEGINNER",
"MILITARY_STATUS": "EXEMPTED",
}
instance = HumanSerializer(data=data)
instance.is_valid()
instance.save()
- 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
- 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
iswrite_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"""
can_parse_csv = "csv" in field.allowed_upload_formats
can_parse_csv = field.is_allowed_format('obj') # False
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
onTableUploadField
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
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": []
}
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 .