Package: django-sweet-utils
Django sweet utils.A little django code sugar.If you find this package useful, please star it onGitHub.QuickstartAdddjango_sweet_utilsto yourINSTALLED_APPSsetting like this:INSTALLED_APPS = [
    ...
    'django_sweet_utils',
    ...
]Inherit your models fromdjango_sweet_utils.db.models.Model:from django_sweet_utils.db.models import Model


class MyModel(Model):
   ...From now your models has the following fields:uuid4as object id;created_atas object creation time;updated_atas object last update time;is_deletedas indicator that object is deleted or not;Models that inherited fromdjango_sweet_utils.db.models.Modelcan be filtered with simpleexisting()property:from django_sweet_utils.db.models import Model


class MyModel(Model):
   ...


queryset = MyModel.objects.existing()This returns queryset filtered byis_deleted=FalseAlso, now you don't need to catchDoesNotExisterror when attempting to get some object while it does not exist.
Just useget_or_none()instead ofget()and query returnsNoneif there is no object.FeaturesModelsFake deletionYou can delete your objects without actual database deletion.
Just usedelete()method on your model instance and it will be marked as deleted withis_deleted=True:To perform actual deletion usehard_delete()method instead.UUID4 as object idEvery model instance hasuuid4field as object id.Created and updated timeEvery model instance hascreated_atandupdated_atfields as object creation and last update time.Existing objectsYou can get only existing objects withexisting()property on your model manager.queryset=MyModel.objects.existing()Get or noneYou can get object orNoneif it does not exist withget_or_none()method on your model manager.obj=MyModel.objects.get_or_none(pk=1)APIViewsInherit your DRF API views fromdjango_sweet_utils.api.views:from django_sweet_utils.api.views import UpdateAPIView, DestroyAPIView


class MyUpdateView(UpdateAPIView):
   ...


class MyDestroyView(DestroyAPIView):
   ...PaginationThere isPageNumberPaginationclass that addspage_sizequery parameter toPageNumberPaginationclass.REST_FRAMEWORK={...'DEFAULT_PAGINATION_CLASS':'django_sweet_utils.api.pagination.PageNumberPagination','PAGE_SIZE':10,...}From now your views supportsPOSTrequest method instead ofPATCHandDELETEDestroyAPIView does not perform actual database deletion, but only marks file as deleted withis_deleted=TruePermissionsThere isDjangoModelPermissionsclass that addsviewpermission toDjangoModelPermissionsclass onGETrequest method.AdminHard deletion action for admin panel.fromdjango_sweet_utils.adminimporthard_delete_selectedclassMyModelAdmin(admin.ModelAdmin):actions=[hard_delete_selected]SeriliazersPrettier choice fieldYou can use customChoiceFieldinstead ofChoiceFieldfromrest_frameworkto get prettier choices representation in API.fromdjango_sweet_utils.api.serializersimportChoiceFieldclassMySerializer(serializers.ModelSerializer):my_field=ChoiceField(choices=MY_CHOICES)Prettier multiple choice fieldYou can use customMultipleChoiceFieldinstead ofMultipleChoiceFieldfromrest_frameworkto get prettier choices representation in API.fromdjango_sweet_utils.api.serializersimportMultipleChoiceFieldclassMySerializer(serializers.ModelSerializer):my_field=MultipleChoiceField(choices=MY_CHOICES)Template tagsformat_stringtemplate tagYou can useformat_stringtemplate tag to format string with arguments.{% load django_sweet_utils %}

{{ "Hello, {0}!".format_string("World") }}set_query_string_paramtemplate tagYou can useset_query_string_paramtemplate tag to set query string parameter.{% load django_sweet_utils %}

{% set_query_string_param "page" 1 %}More info about this tag you can findhere.LoggingCustomised JSON formatterThere isCustomisedJSONFormatterclass that formats log records as JSON.fromdjango_sweet_utils.loggingimportCustomisedJSONFormatterAPP_LABEL="my_app"ENVIRONMENT="production"formatter=CustomisedJSONFormatter()Customised JSON handlerThere isCustomHandlerclass that handles log records as JSON.fromdjango_sweet_utils.loggingimportCustomHandlerhandler=CustomHandler()MiscCustom JSON encoderYou can useLazyEncoderto serialize lazy objects to JSON.fromdjango_sweet_utils.miscimportLazyEncoderjson.dumps({"lazy":lazy_object},cls=LazyEncoder)