django-rest-framework-tricks 0.2.14
pip install django-rest-framework-tricks
Released:
Collection of various tricks for Django REST framework.
Navigation
Unverified details
These details havenot been verified by PyPIProject links
Meta
- License: GNU General Public License v2 (GPLv2), GNU Lesser General Public License v2 or later (LGPLv2+) (GPL-2.0-only OR LGPL-2.1-or-later)
- Author:Artur Barseghyan
- Tags django, django rest framework, tricks
Classifiers
- Development Status
- Environment
- Framework
- Intended Audience
- License
- Operating System
- Programming Language
Project description
Collection of various tricks forDjango REST framework.
Prerequisites
Django 2.2, 3.0, 3.1, 3.2, 4.0 and 4.1.
Python 3.7, 3.8, 3.9, 3.10 and 3.11.
Dependencies
djangorestframework: Initially written with 3.6.3, but nowadays testedwith >=3.10,<3.14. May (still) work on earlier- or (even) supportlater- versions, although not guaranteed.
Installation
Install latest stable version from PyPI:
pipinstalldjango-rest-framework-tricksor latest development version from GitHub:
pipinstallhttps://github.com/barseghyanartur/django-rest-framework-tricks/archive/master.tar.gzAddrest_framework andrest_framework_tricks toINSTALLED_APPS:
INSTALLED_APPS=(# ...# REST framework'rest_framework',# REST framework tricks (this package)'rest_framework_tricks',# ...)
Documentation
Documentation is available onRead the Docs.
Main features and highlights
Nested serializers: Nested (writable) serializers for non-relational fields.
Ordering filter: Developer friendly names for ordering options (forinstance, for related field names).
File field with restrictions: Restrict the file field (in size).
Usage examples
Nested serializers
Nested serializers for non-relational fields.
Our imaginaryBook model consists of the following (non-relational) Djangomodel fields:
title:CharField
description:TextField
summary:TextField
publication_date:DateTimeField
state:CharField (with choices)
isbn:CharField
price:DecimalField
pages:IntegerField
stock_count:IntegerField
In our REST API, we want to split the Book serializer into parts using nestedserializers to have the following structure:
{"id":"","title":"","description":"","summary":"","publishing_information":{"publication_date":"","isbn":"","pages":""},"stock_information":{"stock_count":"","price":"","state":""}}Sample model
The only variation from standard implementation here is that we declare twoNestedProxyField fields on theBook model level for to be used inBookSerializer serializer.
Note, that the change does not cause model change (no migrations orwhatsoever).
Required imports
fromdjango.dbimportmodelsfromrest_framework_tricks.models.fieldsimportNestedProxyFieldModel definition
BOOK_PUBLISHING_STATUS_PUBLISHED='published'BOOK_PUBLISHING_STATUS_NOT_PUBLISHED='not_published'BOOK_PUBLISHING_STATUS_IN_PROGRESS='in_progress'BOOK_PUBLISHING_STATUS_CHOICES=((BOOK_PUBLISHING_STATUS_PUBLISHED,"Published"),(BOOK_PUBLISHING_STATUS_NOT_PUBLISHED,"Not published"),(BOOK_PUBLISHING_STATUS_IN_PROGRESS,"In progress"),)BOOK_PUBLISHING_STATUS_DEFAULT=BOOK_PUBLISHING_STATUS_PUBLISHEDclassBook(models.Model):"""Book."""title=models.CharField(max_length=100)description=models.TextField(null=True,blank=True)summary=models.TextField(null=True,blank=True)publication_date=models.DateField()state=models.CharField(max_length=100,choices=BOOK_PUBLISHING_STATUS_CHOICES,default=BOOK_PUBLISHING_STATUS_DEFAULT)isbn=models.CharField(max_length=100,unique=True)price=models.DecimalField(max_digits=10,decimal_places=2)pages=models.PositiveIntegerField(default=200)stock_count=models.PositiveIntegerField(default=30)# List the fields for `PublishingInformationSerializer` nested# serializer. This does not cause a model change.publishing_information=NestedProxyField('publication_date','isbn','pages',)# List the fields for `StockInformationSerializer` nested serializer.# This does not cause a model change.stock_information=NestedProxyField('stock_count','price','state',)classMeta:"""Meta options."""ordering=["isbn"]def__str__(self):returnself.titleSample serializers
At first, we addnested_proxy_field property to theMeta classdefinitions ofPublishingInformationSerializer andStockInformationSerializer nested serializers.
Then we define our (main)BookSerializer class, which is going to beused as aserializer_class of theBookViewSet. We inherit theBookSerializer fromrest_framework_tricks.serializers.HyperlinkedModelSerializerinstead of the one of the Django REST framework. There’s also arest_framework_tricks.serializers.ModelSerializer available.
Required imports
fromrest_frameworkimportserializersfromrest_framework_tricks.serializersimport(HyperlinkedModelSerializer,)from.modelsimportBookDefining the serializers
Note
If you get validation errors about null-values, addallow_null=Truenext to therequired=False for serializer field definitions.
Nested serializer
classPublishingInformationSerializer(serializers.ModelSerializer):"""Publishing information serializer."""publication_date=serializers.DateField(required=False)isbn=serializers.CharField(required=False)pages=serializers.IntegerField(required=False)classMeta:"""Meta options."""model=Bookfields=('publication_date','isbn','pages',)# Note, that this should be set to True to identify that# this serializer is going to be used as `NestedProxyField`.nested_proxy_field=TrueNested serializer
classStockInformationSerializer(serializers.ModelSerializer):"""Stock information serializer."""classMeta:"""Meta options."""model=Bookfields=('stock_count','price','state',)# Note, that this should be set to True to identify that# this serializer is going to be used as `NestedProxyField`.nested_proxy_field=TrueMain serializer to be used in the ViewSet
# Note, that we are importing the ``HyperlinkedModelSerializer`` from# the `rest_framework_tricks.serializers`. Names of the serializers# should match the names of model properties set with ``NestedProxyField``# fields.classBookSerializer(HyperlinkedModelSerializer):"""Book serializer."""publishing_information=PublishingInformationSerializer(required=False)stock_information=StockInformationSerializer(required=False)classMeta:"""Meta options."""model=Bookfields=('url','id','title','description','summary','publishing_information','stock_information',)Sample ViewSet
Absolutely no variations from standard implementation here.
Required imports
fromrest_framework.viewsetsimportModelViewSetfromrest_framework.permissionsimportAllowAnyfrom.modelsimportBookfrom.serializersimportBookSerializerViewSet definition
classBookViewSet(ModelViewSet):"""Book ViewSet."""queryset=Book.objects.all()serializer_class=BookSerializerpermission_classes=[AllowAny]Sample OPTIONS call
OPTIONS /books/api/books/HTTP 200 OKAllow: GET, POST, HEAD, OPTIONSContent-Type: application/jsonVary: Accept{"name":"Book List","description":"Book ViewSet.","renders":["application/json","text/html"],"parses":["application/json","application/x-www-form-urlencoded","multipart/form-data"],"actions":{"POST":{"id":{"type":"integer","required":false,"read_only":true,"label":"ID"},"title":{"type":"string","required":true,"read_only":false,"label":"Title","max_length":100},"description":{"type":"string","required":false,"read_only":false,"label":"Description"},"summary":{"type":"string","required":false,"read_only":false,"label":"Summary"},"publishing_information":{"type":"nested object","required":false,"read_only":false,"label":"Publishing information","children":{"publication_date":{"type":"date","required":false,"read_only":false,"label":"Publication date"},"isbn":{"type":"string","required":false,"read_only":false,"label":"Isbn"},"pages":{"type":"integer","required":false,"read_only":false,"label":"Pages"}}},"stock_information":{"type":"nested object","required":false,"read_only":false,"label":"Stock information","children":{"stock_count":{"type":"integer","required":false,"read_only":false,"label":"Stock count"},"price":{"type":"decimal","required":true,"read_only":false,"label":"Price"},"state":{"type":"choice","required":false,"read_only":false,"label":"State","choices":[{"value":"published","display_name":"Published"},{"value":"not_published","display_name":"Not published"},{"value":"in_progress","display_name":"In progress"}]}}}}}}Unlimited nesting depth
Unlimited nesting depth is supported.
Our imaginaryAuthor model could consist of the following (non-relational)Django model fields:
salutation:CharField
name:CharField
email:EmailField
birth_date:DateField
biography:TextField
phone_number:CharField
website:URLField
company:CharField
company_phone_number:CharField
company_email:EmailField
company_website:URLField
In our REST API, we could split the Author serializer into parts usingnested serializers to have the following structure:
{"id":"","salutation":"","name":"","birth_date":"","biography":"","contact_information":{"personal_contact_information":{"email":"","phone_number":"","website":""},"business_contact_information":{"company":"","company_email":"","company_phone_number":"","company_website":""}}}Our model would have to be defined as follows (seeAdvanced usage examplesfor complete model definition):
classAuthor(models.Model):"""Author."""# ...# List the fields for `PersonalContactInformationSerializer` nested# serializer. This does not cause a model change.personal_contact_information=NestedProxyField('email','phone_number','website',)# List the fields for `BusinessContactInformationSerializer` nested# serializer. This does not cause a model change.business_contact_information=NestedProxyField('company','company_email','company_phone_number','company_website',)# List the fields for `ContactInformationSerializer` nested# serializer. This does not cause a model change.contact_information=NestedProxyField('personal_contact_information','business_contact_information',)# ...See theAdvanced usage examplesfor complete example.
Ordering filter
Developer friendly names for ordering options (for instance, for related fieldnames) for making better APIs.
Sample model
Absolutely no variations from standard implementation here.
Required imports
fromdjango.dbimportmodelsModel definition
classProfile(models.Model):"""Profile."""user=models.ForeignKey('auth.User')biography=models.TextField()hobbies=models.TextField()Sample serializer
Absolutely no variations from standard implementation here.
Required imports
fromrest_frameworkimportserializersfrom.modelsimportProfileDefining the serializers
classProfileSerializer(serializers.ModelSerializer):"""Profile serializer."""username=serializers.CharField(source='user.username',read_only=True)full_name=serializers.SerializerMethodField()email=serializers.CharField(source='user.email',read_only=True)classMeta(object):model=Profilefields=('id','username','full_name','email','biography','hobbies',)defget_full_name(self,obj):returnobj.user.get_full_name()Sample ViewSet
The only variation from standard implementation here is that weuserest_frameworks_tricks.filters.OrderingFilter insteadofrest_framework.filters.OrderingFilter.
Required imports
fromrest_framework.viewsetsimportModelViewSetfromrest_framework.permissionsimportAllowAnyfromrest_framework_tricks.filtersimportOrderingFilterfrom.modelsimportProfilefrom.serializersimportProfileSerializerViewSet definition
classProfileViewSet(ModelViewSet):"""Profile ViewSet."""queryset=Profile.objects.all()serializer_class=ProfileSerializerpermission_classes=[AllowAny]filter_backends=(OrderingFilter,)ordering_fields={'id':'id','username':'user__username','email':'user__email','full_name':['user__first_name','user__last_name']}ordering=('id',)Sample GET calls
Note, that our ordering options are now equal to the field names in theserializer (JSON response). API becomes easier to use/understand that way.
GET /api/profile/?ordering=emailGET /api/profile/?ordering=-usernameGET /api/profile/?ordering=full_nameGET /api/profile/?ordering=-full_nameFile field with restrictions
Sample model
Absolutely no variations from standard implementation here.
Required imports
fromdjango.dbimportmodelsModel definition
classProfile(models.Model):"""Upload."""username=models.CharField(max_length=255)resume=models.FileField()Sample serializer
Required imports
fromrest_frameworkimportserializersfromrest_framework_tricks.fieldsimportConstrainedFileFieldfrom.modelsimportUploadDefining the serializers
classProfileSerializer(serializers.ModelSerializer):"""Profile serializer."""username=serializers.CharField()# Restrict resume to 5Mbresume=ConstrainedFileField(max_upload_size=5_242_880)classMeta(object):model=Profilefields=('id','username','resume',)Demo
Run demo locally
In order to be able to quickly evaluate thedjango-rest-framework-tricks,a demo app (with a quick installer) has been created (works on Ubuntu/Debian,may work on other Linux systems as well, although not guaranteed). Follow theinstructions below to have the demo running within a minute.
Grab and run the latestrest_framework_tricks_demo_installer.sh demoinstaller:
wget-O-https://raw.github.com/barseghyanartur/django-rest-framework-tricks/master/examples/rest_framework_tricks_demo_installer.sh|bashOpen your browser and test the app.
http://127.0.0.1:8001/books/api/Testing
Project is covered with tests.
To test with all supported Python/Django versions type:
toxTo test against specific environment, type:
tox-epy39-django32To test just your working environment type:
pytest-vvvTo run a single test in your working environment type:
pytest-vvvsrc/rest_framework_tricks/tests/test_nested_proxy_field.pypipinstall-rexamples/requirements/test.txtWriting documentation
Keep the following hierarchy.
=====title=====header======sub-header----------sub-sub-header~~~~~~~~~~~~~~sub-sub-sub-header^^^^^^^^^^^^^^^^^^sub-sub-sub-sub-header++++++++++++++++++++++sub-sub-sub-sub-sub-header**************************License
GPL-2.0-only OR LGPL-2.1-or-later
Support
For any issues contact me at the e-mail given in theAuthor section.
Project details
Unverified details
These details havenot been verified by PyPIProject links
Meta
- License: GNU General Public License v2 (GPLv2), GNU Lesser General Public License v2 or later (LGPLv2+) (GPL-2.0-only OR LGPL-2.1-or-later)
- Author:Artur Barseghyan
- Tags django, django rest framework, tricks
Classifiers
- Development Status
- Environment
- Framework
- Intended Audience
- License
- Operating System
- Programming Language
Release historyRelease notifications |RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more aboutinstalling packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more aboutwheel file names.
Copy a direct link to the current filters
UploadedPython 2Python 3
File details
Details for the filedjango-rest-framework-tricks-0.2.14.tar.gz.
File metadata
- Download URL:django-rest-framework-tricks-0.2.14.tar.gz
- Upload date:
- Size: 288.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.1 CPython/3.10.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 | 672316c3d37b93cdabf0b67b36a98e37738b5eae4535aeca1072411842ea9b51 | |
| MD5 | eb7077a576df149890fd4d08315cb7cf | |
| BLAKE2b-256 | c7f3a63537ea603f5e2f2bdb85e050992cd0e5b031f62b93ff7e7c430b3b4143 |
File details
Details for the filedjango_rest_framework_tricks-0.2.14-py2.py3-none-any.whl.
File metadata
- Download URL:django_rest_framework_tricks-0.2.14-py2.py3-none-any.whl
- Upload date:
- Size: 39.0 kB
- Tags: Python 2, Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.1 CPython/3.10.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 | 9eccf2a81487c22d368a8ffd06ba88dd928071cb8ae5145f9bdeb98e80f985de | |
| MD5 | 120ae09337514d8df2d98c2f2b20a870 | |
| BLAKE2b-256 | a259f5f02c7c15c62907f021184e2cc9865a511f06104fd9b7c061d59fba3d3f |