Skip to main content

A package providing a multi-ModelForm solution for django

Project description

django-stapler

Build Status

Provides a simple way to combine multiple ModelForm classes

Description

Django's ModelForm class lets you create a Form class for a model. This lets you conveniently create and update model instances. In some specific cases it would be desiarble to combine multiple ModelForms so that you can create and update multiple model instances in one view with one form. django-stapler provides this functionality

Dependencies

Python 3.6 Python 3.7 Python 3.8

  • Django 2.2+

Installing

pip install django-stapler

Basic usage

Add app to settings.py

INSTALLED_APPS = [ ...
                   'stapler',
                 ]

Define Model classes as usual

models.py

from django.db import models

# Create your models here.
class Bike(models.Model):

    name = models.CharField(max_length=10)
    frame_type = models.CharField(max_length=10, blank=True, null=True)

class Manufacturer(models.Model):

    name = models.CharField(max_length=10)
    chief = models.CharField(max_length=10)

Also declare the ModelForm classes as usual, and in addition staple the ModelForms together by creating a new StapleForm class. In the inner Meta class set the modelforms attribute to a tuple of to staple ModelForms.

forms.py

from django.forms import ModelForm
from stapler.forms import StaplerForm
from .models import Bike, Manufacturer


class BikeModelForm(ModelForm):

    class Meta:
        model = Bike
        fields = ['name', 'price']


class ManufacturerModelForm(ModelForm):

    class Meta:
        model = Manufacturer
        fields = ['name', 'revenue']

class StapledForm(StaplerForm):

    class Meta:
        modelforms = (BikeModelForm, ManufacturerModelForm)
        #auto_prefix = False, defaults is True

The StapledForm yields a form with four fields: bike__name, bike__price, manufacturer__name, manufacturer__revenue. If you want to keep the original field names, you can set the auto_prefix attribute in the Meta class to False. This may lead to unexpected behaviour when fieldnames between models clash.

You can use the StapledForm in views.py to create a new Bike and Manufacturer instance in one go by calling form.save(). This wil return a dictionary with keys resembling the Model class names in lowercase with the _instance suffix. The keys map to the newly created instances:

views.py

from django.views.generic.edit import FormView
from .forms import StapledForm

class SomeView(FormView):
    template_name = 'example.html'
    form_class = StapledForm
    success_url = '/thanks/'

    def form_valid(self, form):
        # This method is called when valid form data has been POSTed.
        # It should return an HttpResponse.
        result = form.save()
        nw_bike = result['bike_instance']   # the saved bike instance
        nw_manufacturer = result['manufacturer_instance'] # the saved manufacturer instance
        return super().form_valid(form)

You can also use the form to update existing instances by providing a tuple of instances to the named instances argument:

from .models import Bike, Manufacturer
from .forms import StapledForm

...

# inside view function
bike = Bike.objects.first()
manufacturer = Manufacturer.objects.first()

form = StapledForm(data=request.POST, instances=(bike, manufacturer))
if form.is_valid():
    result = form.save()
    result # this is a dictionary with the updated instances

StapledForm provides the pre_save and post_save hooks. These methods are called before and after the instances are saved when the save() method is called:

class StapledForm(StaplerForm):

    ...

    def pre_save(self):
        print("did you get the memo?")


    def post_save(self):
        print("have you seen my stapler?")

Extra options

In addition to modelforms attribute, you can set a few options in Meta class that alter the behaviour of the StaplerForm

  • auto_prefix: defaults to True. This will append a prefix of the model class name to the appropriate fields
  • required: A tuple of the ModelForm classes that are required. By default, all ModelForm classes defined in modelforms are required. If a ModelForm is not in the required attribute, it's errors are ignored and is_valid() can still return True. Calling save() in this case will only save the instances of ModelForms that did validate. Instead of an instance, None is stored in the returned dictionary

License

This project is licensed under the MIT License - see the LICENSE.md file for details

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django-stapler-1.1.0.2.tar.gz (8.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

django_stapler-1.1.0.2-py3-none-any.whl (8.2 kB view details)

Uploaded Python 3

File details

Details for the file django-stapler-1.1.0.2.tar.gz.

File metadata

  • Download URL: django-stapler-1.1.0.2.tar.gz
  • Upload date:
  • Size: 8.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/49.2.0 requests-toolbelt/0.9.1 tqdm/4.48.0 CPython/3.6.7

File hashes

Hashes for django-stapler-1.1.0.2.tar.gz
Algorithm Hash digest
SHA256 205ae62b9e84fe709fb13678ef72db8b9f3be6ea379101bcfda68a38ee7d367e
MD5 e76a06b65c23a0c97ac252857bc2e1d3
BLAKE2b-256 beec5e92f387964d9bf4c13e357a1d59dfc08a1deff4b50b681cdb891ffeb531

See more details on using hashes here.

File details

Details for the file django_stapler-1.1.0.2-py3-none-any.whl.

File metadata

  • Download URL: django_stapler-1.1.0.2-py3-none-any.whl
  • Upload date:
  • Size: 8.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/49.2.0 requests-toolbelt/0.9.1 tqdm/4.48.0 CPython/3.6.7

File hashes

Hashes for django_stapler-1.1.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 c0ba5153b23023c4a3c1a71d63c945aa32afdc8ba47ecdad55905e3faa18edce
MD5 774fd1afc7a6a0684b9d32f4e248bd35
BLAKE2b-256 0cb89888e9f72e57fd598e0980ee3bfcba1cf3a816c470f4cfda4818e656a44c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page