Skip to content
Go to file

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time


What is DynamicForms?

DynamicForms wants to eliminate HTML form boilerplate for generic tables & forms. Specifying a single DRF Serializer / ViewSet and possibly desired form layout instantly provides both HTML renders and JSON renders (and anything else DRF supports) giving you free choice of how to implement your project.

It performs all the visualisation & data entry of your DRF Serializers & ViewSets and adds some candy of its own: It is a django library that gives you the power of dynamically-shown form fields, auto-filled default values, dynamic record loading and similar candy with little effort. To put it differently: once defined, a particular ViewSet / Serializer can be rendered in multiple ways allowing you to perform viewing and authoring operations on the data in question.

It is based on django-rest-framework

Documentation on readthedocs

Why DynamicForms

  • Turn your rest-framework ViewSets into HTML forms

  • Powerful HTML based CRUD

    • Support for fetching "new" records, both in JSON or in HTML
    • Render to HTML, dialog html or from your own template
    • Render form (embedded or dialog) or table, depending on situation
    • Dynamically display & hide fields based on other fields' values
    • Easily add actions and place the buttons to execute them anywhere you like
  • Clear separation of list & dialog templates

  • Dynamic loading of additional records for table views

  • Easy implementation of simple filtering

  • Action items, declared globally, placed where you need them

  • Custom templates whenever & wherever you want them

  • Render to full html or work with dialogs within same page or both at the same time

  • Each form and field have a unique HTML id for easy finding & manipulation

  • Bootstrap 3 & 4 and jQuery UI templates, easy to make your own or enhance existing

  • Support for form validation, will show errors even if they are not tied to a field

  • Convenient JS functions for easier action scripting

  • Progress dialog for long lasting ajax operations

Quick start guide

pip install dynamicforms

Then you need to Activate DynamicForms in DRF.

Also make sure you specify a proper base page template DYNAMICFORMS_PAGE_TEMPLATE - see below for an example).

DynamicForms has been designed to cause minimal disruption to your existing code patterns.

So instead of DRF ModelViewSet just use DynamicForms ModelViewSet, instead of ModelSerializer - DynamicForms ModelSerializer.

Currently only the dynamicforms.viewsets.ModelViewSet is supported for ViewSets. We have others planned, but not implemented yet.


from dynamicforms import serializers, viewsets
from ..models import PageLoad

class PageLoadSerializer(serializers.ModelSerializer):
    form_titles = {
        'table': 'Dynamic page loader list',
        'new': 'New object',
        'edit': 'Editing object',

    class Meta:
        model = PageLoad
        exclude = ()

class PageLoadViewSet(viewsets.ModelViewSet):
    template_context = dict(url_reverse='page-load')
    pagination_class = viewsets.ModelViewSet.generate_paged_loader(30)  # enables pagination

    queryset = PageLoad.objects.all()
    serializer_class = PageLoadSerializer

examples/ (excerpt)

from django.db import models

class PageLoad(models.Model):
    Shows how DynamicForms handles dynamic loading of many records in ViewSet result
    description = models.CharField(max_length=20, help_text='Item description')

If you want filter in list view just set serializers property show_filter value to True. Filter will be applied if user press enter in filter field. If you want to have filter button in list header, call Actions with add_default_filter = True.


from dynamicforms import serializers, viewsets
from dynamicforms.action import Actions
from ..models import Filter

class FilterSerializer(serializers.ModelSerializer):
    form_titles = {
        'table': 'Dynamic filter list',
        'new': 'New object',
        'edit': 'Editing object',
    actions = Actions(add_default_crud=True, add_default_filter=True)
    show_filter = True

    class Meta:
        model = Filter
        exclude = ()

class FilterViewSet(viewsets.ModelViewSet):
    template_context = dict(url_reverse='filter')
    pagination_class = viewsets.ModelViewSet.generate_paged_loader(30)  # enables pagination

    queryset = Filter.objects.all()
    serializer_class = FilterSerializer

Following is an example page template to render straight router URLs. Lines 12, 17 & 20 show the lines that obtain and render the actual data, be it table or form. See DYNAMICFORMS_PAGE_TEMPLATE.

{% extends 'examples/base.html' %}
{% load dynamicforms %}
{% block title %}
  {{ serializer.page_title }}
{% endblock %}
{% block body %}
  {% get_data_template as data_template %}

<div class="{{ DYNAMICFORMS.bs_card_class }}">
  <div class="{{ DYNAMICFORMS.bs_card_header }}">
    {{ serializer.page_title }}
    {% if serializer.render_type == 'table' %}{% render_table_commands serializer 'header' %}{% endif %}
  <div class="{{ DYNAMICFORMS.bs_card_body }}">
    {% include data_template with serializer=serializer data=data %}
{% endblock %}

Done. Point your DRF router to the ViewSet you just created and your browser to its URL - make sure you add ".html" to the URL to specify the renderer. If you forget that, you will get DRF's API renderer.

You can’t perform that action at this time.