Created
March 8, 2017 17:40
-
-
Save melvyn-sopacua/dbf3c8f71023d6fc261131cb0a851f58 to your computer and use it in GitHub Desktop.
Case for pre_init form hook
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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