{"id":35240883,"url":"https://github.com/gaspect/dauto","last_synced_at":"2026-04-02T02:17:43.742Z","repository":{"id":184571275,"uuid":"652378415","full_name":"gaspect/dauto","owner":"gaspect","description":"Solutions for commons issues on django and drf projects","archived":false,"fork":false,"pushed_at":"2025-06-24T04:49:18.000Z","size":808,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2026-01-02T10:33:12.839Z","etag":null,"topics":["django","drf","python"],"latest_commit_sha":null,"homepage":"https://gaspect.github.io/dauto/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gaspect.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-06-12T00:16:52.000Z","updated_at":"2025-07-12T02:59:42.000Z","dependencies_parsed_at":"2024-06-20T13:24:15.863Z","dependency_job_id":"21c95937-a346-481e-8cf0-300f75b56308","html_url":"https://github.com/gaspect/dauto","commit_stats":null,"previous_names":["gaspect/dauto"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/gaspect/dauto","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gaspect%2Fdauto","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gaspect%2Fdauto/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gaspect%2Fdauto/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gaspect%2Fdauto/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gaspect","download_url":"https://codeload.github.com/gaspect/dauto/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gaspect%2Fdauto/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31294503,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-02T01:43:37.129Z","status":"online","status_checked_at":"2026-04-02T02:00:08.535Z","response_time":89,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["django","drf","python"],"created_at":"2025-12-30T05:01:08.353Z","updated_at":"2026-04-02T02:17:43.732Z","avatar_url":"https://github.com/gaspect.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Dauto\n\nSolutions for commons issues on Django and drf projects\n\n## Description\n\nThis project is a collection of common solutions for Django projects. It aims to assist developers who are working with\nDjango by providing tried-and-tested solutions to recurring issues and challenges. The strategies covered in this\nproject span from basic to advanced topics, making it a versatile resource for both beginners and experienced Django\ndevelopers. It facilitates quick problem-solving in Django projects and significantly reduces development time and\neffort. With these solutions at hand, developers can focus more on other crucial aspects of their projects. To learn more\nread the [documentation](https://gaspect.github.io/dauto/).\n\n## Use Cases\n\nWe think that cover from simple to complex can be useful in the module learning curve so... let's go 🚀!!!\n\n### Configure django databases based on urls\n\n```python\nfrom dauto.database import  database\nimport os\nDATABASES = {\n    \"default\": database(os.getenv(\"DATABASE_URL\"), conn_max_age=None, conn_health_checks=True),\n    \"test\": {\n        \"NAME\": \"test.sqlite3\",\n        \"ENGINE\": \"django.db.backends.sqlite3\",\n    },\n}\n```\n### Embed admin definitions in models\n\nWe can do it this way \n\n```python\n# app/model.py\nfrom django.db import  models\nfrom django.contrib import admin\n\n\nclass Poll(models.Model):\n    title = models.CharField(max_length=256)\n    description = models.TextField(null=True, blank=True)\n    active = models.BooleanField(default=False)\n    \n    def __str__(self):\n        return self.title\n\n    class Admin(admin.ModelAdmin):\n        list_display = [\"title\", \"active\"]\n        search_fields = [\"title\"]\n```\n\nthen on application config do\n\n```python\nfrom django.apps import AppConfig as BaseConfig\n\n\nclass AppConfig(BaseConfig):\n    default_auto_field = \"django.db.models.BigAutoField\"\n    name = \"apps\"\n\n    def ready(self) -\u003e None:\n        from dauto.admin import register # 👈\n        from app import  models # 👈\n        \n        register(models) # 👈\n```\n\n\n### Avoid circular signal call\n\nThis happens when two signals call each other, how break the cicle can be tricky we do it for you\n\n```python\nfrom django.db import models\nfrom django.db.models import signals\nfrom django.dispatch import receiver\n\nfrom dauto.signals import OutSignal\n\nclass A(models.Model):\n    ...\n\nclass B(models.Model):\n    a = models.ManyToManyField(A)\n\n@receiver(signals.post_save, sender=A)\ndef on_a_change(sender, instance, **kwargs):\n    for b in  instance.b_set.all():\n        b.update(**{})\n    \n@receiver(signals.post_save, sender=B)\ndef on_b_change(sender, instance, **kwargs):\n    with OutSignal(signals.post_save, on_a_change, A ): # 👈 disconnect on_a_change for this code block\n        for a in  instance.a.all():\n            a.update(**{})\n```\n\n### Model permission for DRF function base views\n\n```python\nfrom rest_framework import decorators\nfrom app.models import  SomeModel # 👈 Asume this exist\nfrom dauto.drf.permission import permissions_for\n\n@decorators.api_view([\"GET\", \"POST\"])\n@decorators.permission_classes(permissions_for(SomeModel))\ndef some_model_view(request):\n    ...\n```\n\n### Custom namespace versioning\n\n```python\n# common/versioning.py\n\nfrom dauto.drf.versioning import CustomNamespaceVersioning\n\nclass SharpNamespaceVersioning(CustomNamespaceVersioning):\n    separator = \"#\"\n```\n\n```python\n# settings.py\nREST_FRAMEWORK = {\n    \"DEFAULT_VERSIONING_CLASS\": \"common.versioning.SharpNamespaceVersioning\",\n}\n```\n\nNow your views can be reversed using `someview-details#v1`\n\n### Custom serializers getters for generic viewsets\n\nCan be used to retrieve serializers based on operations\n\n```python\nfrom dauto.drf.viewsets.mixin import ByOperationSerializerMixin\nfrom rest_framework.viewsets import ModelViewSet\nfrom rest_framework import decorators\nfrom app.serializers import AReadSerializer, AWriteSerializer, CustomOppSerializer\n\nclass AViewSet(ByOperationSerializerMixin, ModelViewSet):\n    \n    @decorators.action([\"POST\"], detail=True)\n    def custom_opp(self, request): # will user serialize with key `custom_app` and fallback to 'write' key serializer \n        # if not found because is a 'POST' an operation that write on the DB\n        ...\n    \n    serializer_class = {\n        \"read\": AReadSerializer,\n        \"write\": AWriteSerializer,\n        \"custom_opp\": CustomOppSerializer\n    }\n```\nor retrieve serializers based on versions\n\n```python\nfrom dauto.drf.viewsets.mixin import ByVersionSerializerMixin\nfrom rest_framework.viewsets import ModelViewSet\nfrom app.serializers import AReadSerializerV1, AWriteSerializerV2\n\nclass AViewSet(ByVersionSerializerMixin, ModelViewSet):\n    \n    serializer_class = {\n        \"v1\": AReadSerializerV1,\n        \"v2\": AWriteSerializerV2,\n    }\n```\n\nThen the `AViewSet` class can be used in two separated versions (namespace, url, whatever) and use different serializers for any of these version\nkeeping the logic without change.\n\nWe can use combinations of both for different effects\n\n\n```python\nfrom dauto.drf.viewsets.mixin import ByVersionSerializerMixin, ByOperationSerializerMixin\nfrom rest_framework.viewsets import ModelViewSet\nfrom app import serializers\n\nclass AViewSet(ByOperationSerializerMixin, ByVersionSerializerMixin, ModelViewSet):\n    \n    serializer_class = {\n        \"v1\": {\n            \"read\": serializers.v1.AReadSerializer,\n            \"write\": serializers.v1.AWriteSerializer\n        },\n        \"v2\": {\n            \"read\": serializers.v2.AReadSerializer,\n            \"write\": serializers.v2.AWriteSerializer\n        },\n    }\n```\n### Verbose creation and update methods\n\nWhen we say verbose we refer to use a read serializer like to process the instance created. This make\ngood combination with serializer getters\n\n```python\n\nfrom dauto.drf.viewsets.mixin import ByVersionSerializerMixin, ByOperationSerializerMixin\nfrom dauto.drf.viewsets.mixin import CreateVerboseModelMixin, UpdateVerboseModelMixin\n\nfrom rest_framework.viewsets import  GenericViewSet\nfrom rest_framework import mixins\nfrom app import serializers\n\nclass AViewSet(\n    CreateVerboseModelMixin, # 👈\n    mixins.RetrieveModelMixin,\n    UpdateVerboseModelMixin, # 👈\n    mixins.DestroyModelMixin,\n    mixins.ListModelMixin,\n    ByOperationSerializerMixin, # 👈\n    ByVersionSerializerMixin, # 👈\n    GenericViewSet\n):\n    \n    serializer_class = {\n        \"v1\": {\n            \"read\": serializers.v1.AReadSerializer,\n            \"write\": serializers.v1.AWriteSerializer\n        },\n        \"v2\": {\n            \"read\": serializers.v2.AReadSerializer,\n            \"write\": serializers.v2.AWriteSerializer\n        },\n    }\n```\n\nEven if you use your own serializer system to get a writer and read serializer it will work, and\nuse the serializer defined to be obtained in a read method as the verbose one.\n\n### Polymorphic useful methods\n\nIf you've never read about django polymorphic start [here](https://django-polymorphic.readthedocs.io/en/stable/). Is a \nmore (debated) way to handle model inheritance. That method have its own caveats and drawbacks that\nwe try to fix. One of then is incompatibility with some django  core admin functions making\nthe django administration site useless, can be fixed using the `dauto.polymorphic.collector` function.\n\nIn this example the user model is, and it's related with polymorphic models,\nso we need to monkey patch some django inners methods to solve incompatibility (do not ask\nhow many hours or debug took give with the answer).\n\n\n```python\n\nfrom django.contrib.auth.admin import UserAdmin\n\nfrom django.contrib.admin import utils #👈\nfrom django.db.models import deletion #👈\n\n\nfrom dauto.polymorphic import collector\n\nclass CustomUserModelAdmin(UserAdmin):\n\n    def get_deleted_objects(self, objs, request):\n        with collector(utils.NestedObjects): #👈\n            return super().get_deleted_objects(objs, request) # now this method use the monkey patched object\n        # and here the object back to normality\n\n    def delete_queryset(self, request, queryset):\n        with collector(deletion.Collector): #👈\n            return super().delete_queryset(request, queryset) # now this method use the monkey patched object\n        # and here the object back to normality\n\n```\nWe also build a method to build polymorphic serializers using already existing serializers.\nCan be found as the `dauto.polymorphic.polymorphic` function.\n\n\u003e I think this cover all the project, happy coding ️ ☺️👋","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgaspect%2Fdauto","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgaspect%2Fdauto","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgaspect%2Fdauto/lists"}