Skip to content

Instantly share code, notes, and snippets.

@melvyn-sopacua
Created March 8, 2017 17:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save melvyn-sopacua/dbf3c8f71023d6fc261131cb0a851f58 to your computer and use it in GitHub Desktop.
Save melvyn-sopacua/dbf3c8f71023d6fc261131cb0a851f58 to your computer and use it in GitHub Desktop.
Case for pre_init form hook
from uuid import uuid4
from django.db.models import Model
from django.forms import BaseForm
__all__ = (
'WrappedForm',
)
class WrappedForm(object):
def __init__(self, form_class: BaseForm, action_url: str,
is_multipart: bool = False, model_instance: Model = None,
initial: dict = None, prefix: str = 'auto', **kwargs):
"""
Wrapper for a Django Form
The wrapper holds additional information for the <form> tag that
Django doesn't include in it's BaseForm class.
It also provides a way to inject initial data, using either
model_instance or initial or both.
Form Prefix
-----------
A prefix is always given to the form, as the primary use case for
this object is to provide additional forms to a view. A single form
or even the primary form of the view can be handled easy enough using
the generic views.
:param form_class: The Django form
:param action_url: url the form should be submitted to
:param is_multipart: if the form should be capable of uploading files
:param model_instance: if the form is a model form used for update,
it will update this instance.
:param initial: dictionary with initial values for the form. Use this to
set foreign key values.
:param prefix: form prefix to use. If none is given, uuid4() is used
to generate the prefix.
"""
self.form_class = form_class
self.is_multipart = bool(is_multipart)
self.model_instance = model_instance
self.action_url = action_url
self.initial = initial
if prefix == 'auto':
self.prefix = uuid4().hex
else:
self.prefix = prefix
self.form = None
self._set_query_prefix()
def _set_query_prefix(self):
from urllib.parse import urlparse, urlunparse
from django.http import QueryDict
final_url = urlparse(self.action_url)
query = QueryDict(query_string=final_url.query, mutable=True)
query['prefix'] = self.prefix
# Work around parse results being immutable.
parts = (final_url.scheme, final_url.netloc, final_url.path,
final_url.params, query.urlencode(), final_url.fragment)
self.action_url = urlunparse(parts)
def get_form(self):
if self.form is None:
form_kwargs = {
'initial': self.initial,
'prefix': self.prefix,
}
if self.model_instance:
form_kwargs['instance'] = self.model_instance
# noinspection PyCallingNonCallable
self.form = self.form_class(**form_kwargs)
return self.form
# If we had pre_init signal
def pre_init(self, sender, **kwargs):
if sender == self:
return
sender.prefix = self.prefix
from django.views import generic
# Can be dumped with pre_init
class PrefixedFormView(generic.FormView):
def post(self, request, *args, **kwargs):
self.prefix = request.GET.get('prefix', None)
return super().post(request, *args, **kwargs)
# Simplified use
class ProjectTaskCreateView(PrefixedFormView, generic.CreateView):
model = models.Task
template_name = 'create/project-task.html'
form_class = forms.NewProjectTaskForm
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment