Package: django-rest-base
Django REST baseCustomized features and environment for building a Django REST framework app.RequirementsPython 3.8Django 3.0djangorestframework (Django REST framework)Optional packages required for additional features.PyJWTTokenAuthenticationchannelsNullURLRouter,NullConsumersentry-sdksentry_report(whenSentryreports enabled)numpyrest_base.utils.randomInstallationpipinstalldjango-rest-basesettings.pyINSTALLED_APPS=[...,'rest_base',]FeaturesErrorsettings.pyREST_FRAMEWORK={'EXCEPTION_HANDLER':'rest_base.errors.exception_handler',}errors.pyfromrest_base.errorsimportErrorMyAppError=Error('my_app')# classMyError=MyAppError('My','Error')# classMyErrorInstance=MyError(detail='caution: this is instance!')# instance (when *args and code not provided)views.pyfrommy_app.errorsimportMyError,MyErrorInstancedefmy_view(request):raiseMyError(detail='Something went wrong :(')defanother_view1(request):raiseMyError# raise without parameters is also permitteddefanother_view2(request):raiseMyErrorInstance()# __call__ should be used to raise instancerest_base.errors.exception_handleris similar with REST framework's default handler, but provides advanced error format.In Django REST base environment, every exception from views inheritsrest_base.errors.Error. Even original REST framework's exceptions and unhandled exceptions will be converted toError.ThoseErrors will generateResponsewhich has following error format.{"error":{"code":"My::Error","detail":"Something went wrong :(","traceback":"(traceback)"}}detailandtracebackare optional, andtracebackwill be included automatically when Django's DEBUG mode is enabled.Viewurls.pyfromdjango.urlsimportre_pathfromrest_base.urlsimportmethod_branchfrom.importviewsurlpatterns=[re_path(r'^my_endpoint/?$',method_branch(GET=views.my_view,POST=views.another_view)),]rest_base.urls.method_branchbranch the requests by it's method—GET,POST,PUT,DELETE.
It also supports@rest_framework.decorators.authentication_classesand@rest_framework.decorators.permission_classesfor each view.Modelmodels.pyfromrest_base.modelsimportBaseModel,BaseUser,BaseToken,semaphore@semaphore(block=True)classMyModel(BaseModel):field=...classMyUser(BaseUser):field=...classMyToken(BaseToken):field=...By replacing the original Djangomodels.Modelwithrest_base.models.BaseModel, several customized features can be used.created,last_modifiedfieldsobjects.update_or_createupdates instance only if original attributes anddefaultsare not same.bulk_managerSupports deadlock free following methods. (PostgreSQL ONLY)update,bulk_update,deletePredefinedDefault(SeeFieldsfor more)related_namemust be provided when field's type isForeignKey,OneToOneFieldorManyToManyField.You can use customizedBaseUserand JWT basedBaseTokenby inherit it.
SeeAuthenticationfor more information about JWT authentication.Fieldsmodels.pyfromdjango.dbimportmodelsfromrest_base.fieldsimportUniqueRandomPositiveInt32fromrest_base.modelsimportBaseModelclassMyModel(BaseModel):unique_field=models.IntegerField(unique=True,default=UniqueRandomPositiveInt32)If your model inheritsrest_base.models.BaseModel, you can set the default value asUniqueRandomPositiveInt32UniqueRandomPositiveInt52UniqueRandomPositiveInt64UniqueRandomChar(unique random url-safe characters)Then default value will be replaced with unique random value in the run-time.Adminadmin.pyfromdjango.contribimportadminfromrest_base.adminimportmodel_adminfrom.modelsimport*admin.site.register(*model_admin(MyModel))You can easily register you models to Django admin page by usingrest_base.admin.model_admin.
It registers all of the model's fields and supports link toForeignKey,OneToOneFieldandManyToManyFieldon Django admin.Authenticationpipinstalldjango-rest-base[jwt]models.pyfromrest_base.modelsimportBaseTokenclassToken(BaseToken):passsettings.pyREST_FRAMEWORK={'DEFAULT_AUTHENTICATION_CLASSES':('rest_base.authentication.CsrfExemptSessionAuthentication','rest_base.authentication.TokenAuthentication',),}REST_BASE={'AUTHENTICATION_MODEL':'my_app.models.Token',}views.pyfromrest_framework.decoratorsimportpermission_classesfromrest_framework.permissionsimportIsAuthenticated@permission_classes((IsAuthenticated,))defmy_view(request):...EachTokenwhich inheritsBaseTokenhaspublic_keyandsecret_key.
You can make bearer using following format.// Header{"alg":"HS256","typ":"JWT","public_key":"public_key","nonce":31}// Payload{"query":{"key":"value"}}Then set the HTTP Authorization header toAuthorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsInB1YmxpY19rZXkiOiJwdWJsaWNfa2V5Iiwibm9uY2UiOjMxfQ.eyJxdWVyeSI6eyJrZXkiOiJ2YWx1ZSJ9fQ.q1849tjsSspbtyBYHxsmS98FLUIG2W97aj_gaCxWGlgRemember that nonce must be a positive int32 value which increases for each request.Sentrypipinstalldjango-rest-base[sentry]settings.pyREST_BASE={'SENTRY_HOST':'https://<key>@sentry.io/<project>','SENTRY_VERBOSE':False,# report handled exceptions, default False}Ifsentry-sdkinstalled,SENTRY_HOSTdefined andrest_base.errors.exception_handlerconfigured correctly,
every unhandled exception from view will be reported to the Sentry.Handled exceptions also reported if you setSENTRY_VERBOSEtoTrue.Channelspipinstalldjango-rest-base[channels]routing.pyfromdjango.urlsimportpathfromrest_base.channels.routingimportNullURLRouterwebsocket_urlpatterns=[path('app/',NullURLRouter(my_app.routing.websocket_urlpatterns)),]EtcBy default, startapp command will use template inrest_base/conf/app_templatewhich contains additional code for Django REST base.env can be loaded byfromrest_base.utilsimportdotenvdotenv.load('path/to/.env')You can dump/load predefined model instances by usingpythonmanage.pydumpmy_app.Model
pythonmanage.pyloadmy_app.ModelLicenseMIT