Skip to content

About

Django DRF File Generation provides a safe way to generate Django basic files like url.py, serializers.py, admin.py, views.py, based on your models.py

Resources

Code of conduct

Contributing

Stars

6 stars

Watchers

2 watching

Forks

Repository files navigation

Django DRF File Generator

PyPI Python versions License CI

🇧🇷 Leia em português

Generate the Django REST Framework boilerplate you'd otherwise type by hand — admin.py, serializers.py, views.py and urls.py — from the models you already wrote.

It reads your models one of two ways:

  • Standalone, parsing models.py with Python's ast module. No Django install, no settings, no project needed — point it at any file.
  • As a management command, introspecting your live app registry. More accurate, because Django itself resolves inheritance and relations for you.

Both paths feed the same templates, so you get the same output either way.

Install

pip install django-drf-file-generator

Quick start

Standalone, against a file:

drf_gen -m myapp/models.py --all --out myapp/

Or from inside a Django project, against an installed app:

python manage.py drfgen myapp

Then wire the generated router into your project's URLs:

urlpatterns = [path("api/", include("myapp.urls"))]

What you get

Given this models.py:

from django.db import models


class Author(models.Model):
    name = models.CharField(max_length=255)
    email = models.EmailField(blank=True)


class Book(models.Model):
    title = models.CharField(max_length=255)
    author = models.ForeignKey(Author, on_delete=models.CASCADE)
    tags = models.ManyToManyField("Tag", blank=True)
    metadata = models.JSONField(default=dict)
    created = models.DateTimeField(auto_now_add=True)

you get serializers.py:

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = ["id", "title", "author", "tags", "metadata", "created"]
        read_only_fields = ["id", "created"]

views.py:

class BookViewSet(viewsets.ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    filter_backends = [
        DjangoFilterBackend,
        filters.SearchFilter,
        filters.OrderingFilter,
    ]
    filterset_fields = ["title", "author", "tags", "created"]
    search_fields = ["title"]
    ordering_fields = ["id", "title", "created"]
    ordering = ["id"]

admin.py:

@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
    list_display = ["id", "title", "author", "metadata", "created"]
    list_filter = ["author", "created"]
    search_fields = ["title"]
    ordering = ["id"]

and urls.py:

router = routers.DefaultRouter()
router.register(r"authors", AuthorViewSet, basename="authors")
router.register(r"books", BookViewSet, basename="books")

urlpatterns = [path("", include(router.urls))]

The output is meant to actually run

A few things the generator gets right that are easy to get wrong by hand:

  • tags is missing from list_display. A ManyToManyField there raises admin.E109 at system-check time, which stops the whole site from booting.
  • metadata is missing from filterset_fields. django-filter has no filter for JSONField and blows up on the first request to that endpoint. Same for BinaryField, FileField and ImageField.
  • created and id are read-only. Primary keys, auto_now/auto_now_add fields, and anything with editable=False should never be client-writable.
  • Fields inherited from abstract base classes are included, and abstract models themselves are never emitted.
  • An explicit primary_key=True field is respected — no phantom id.
  • A model called Tags routes at /tags/, not /tagss/.

The generated files pass ruff format --check unchanged, so regenerating won't churn your diff.

Options

Flag What it does
-m, --model PATH the models.py to read (standalone only)
-o, --out DIR where to write (default: drf_gen_build; the app's own directory for the management command)
-a, --admin generate admin.py
-s, --serializers generate serializers.py
-v, --views generate views.py (--views in the management command)
-u, --urls generate urls.py
-A, --all generate all four
-f, --force overwrite existing files
--dry-run report what would be written
--stdout print instead of writing
--template-dir DIR use your own templates

About overwriting

Re-running is safe and takes one step. Files still carrying the generated-by header are refreshed automatically; anything else is left alone and reported. Start editing a generated file (or just delete the header) and it becomes yours — the generator won't touch it again without --force.

The one time you need --force up front is on a freshly created app, because manage.py startapp leaves its own stub admin.py and views.py behind:

python manage.py drfgen myapp --all --force

Custom templates

The four built-in templates are Jinja2 files. Copy the one you want to change and point --template-dir at your copy — the rest still come from the package:

python -c "import drf_gen, pathlib; print(pathlib.Path(drf_gen.__file__).parent / 'templates')"
cp .../templates/serializers.py.jinja mytemplates/
drf_gen -m myapp/models.py --all --template-dir mytemplates/ --out myapp/

Each template receives models (a list of ModelSpec), plus model_names, serializer_names and viewset_names. A ModelSpec exposes name, route, pk_name, fields, and the ready-made selections used above: field_names, read_only_field_names, list_display, list_filter, filterset_fields, search_fields, ordering_fields. See drf_gen/ir.py.

Requirements

  • Python 3.9+
  • Jinja2 (installed automatically)
  • For the management command: Django 4.2+
  • For the generated code: Django 4.2+, Django REST Framework 3.14+, and django-filter if any model has filterable fields

Upgrading from 0.x

1.0 is a rewrite. The old version only ran on Python 2 and generated code for Django 1.8. What changed:

  • Python 3.9+ only; the generated code targets Django 4.2+ / DRF 3.14+.
  • Field types are found by parsing, not by matching the first letter of the type name — so JSONField, ManyToManyField, SlugField and others no longer disappear from the output.
  • The generated UserView, PasswordReset and ObtainAuthToken are gone. They depended on rest_auth and on a models.Perfil from one specific private project. Bring your own auth.
  • The tool no longer edits your models.py. 0.x appended a hack_models() monkeypatch to core/models.py on every run. If you have one, delete it.
  • config.ini is gone; use --out.
  • -D/--Delete, which rmtree'd the output directory, is gone. Existing files are now protected by default instead.
  • Viewsets are named <Model>ViewSet, not <Model>View.

Contributing

See CONTRIBUTING.md. Bug reports and pull requests welcome.

License

MIT — see LICENSE.rst.

Written by Alexandre Proença.

About

Django DRF File Generation provides a safe way to generate Django basic files like url.py, serializers.py, admin.py, views.py, based on your models.py

Resources

Code of conduct

Contributing

Stars

6 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages