Skip to content

Instantly share code, notes, and snippets.

Created July 3, 2014 03:06
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 anonymous/953e569362f2936ec9a4 to your computer and use it in GitHub Desktop.
Save anonymous/953e569362f2936ec9a4 to your computer and use it in GitHub Desktop.
Bind an object (through a hidden field) to a form
class FormHiddenObjectMixin(object):
"""
In forms in various create and update views, some of the form values
are populated and hiddedn when the form is created. The user does not
have to fill in this field. For example, when creating a shipment, we
know that is for a particular purchase order. The purchase_order
parameter of the form is set during form initialization.
This mixin provides support for finding this related object either from
URL query parameters (in the case of a CreateView) or from the object
itself (in the case of an UpdateView).
"""
hidden_object_model = None
hidden_object_context_name = ''
hidden_object_pk_query_param = ''
hidden_object_field_name = ''
hidden_object = None
def get_hidden_object(self):
if not self.hidden_object:
self.hidden_object = self.get_hidden_object_from_object() or self.get_hidden_object_from_url()
return self.hidden_object
def get_hidden_object_from_object(self):
if not self.object:
return None
if not self.hidden_object_field_name:
raise ImproperlyConfigured(
"FormHiddenObjectMixin requires the definition of 'hidden_object_field_name'")
return getattr(self.object, self.hidden_object_field_name)
def get_hidden_object_from_url(self):
if not (self.hidden_object_pk_query_param and self.hidden_object_model):
raise ImproperlyConfigured(
"FormHiddenObjectMixin requires the definition of 'hidden_object_pk_query_param'"
" and 'hidden_object_model'")
pk = self.request.GET.get(self.hidden_object_pk_query_param, None)
obj = get_object_or_404(self.hidden_object_model, pk=pk)
return obj
def get_hidden_initial_form_data(self):
if not self.hidden_object_field_name:
raise ImproperlyConfigured(
"FormHiddenObjectMixin requires the definition of 'hidden_object_field_name'")
return {
self.hidden_object_field_name: self.get_hidden_object(),
}
def get_hidden_context_data(self):
if not self.hidden_object_context_name:
raise ImproperlyConfigured(
"FormHiddenObjectMixin requires the definition of 'hidden_object_context_name'")
return {
self.hidden_object_context_name: self.get_hidden_object(),
}
class PictureFormHiddenObjectMixin(FormHiddenObjectMixin):
hidden_object_context_name = 'client'
hidden_object_field_name = 'client'
hidden_object_pk_query_param = 'client_pk'
hidden_object_model = Client
class PictureCreate(PictureFormHiddenObjectMixin, CreateView):
model = Picture
form_class = modelform_factory(Picture,
widgets={ 'client': forms.HiddenInput() },
fields=('pic', 'client', ))
def get_initial(self):
initial = super(PictureCreate, self).get_initial()
initial.update(self.get_hidden_initial_form_data())
return initial
def get_context_data(self, **kwargs):
context = super(PictureCreate, self).get_context_data(**kwargs)
context.update(self.get_hidden_context_data())
return context
# My URL looks like example.com/upload?client_pk=3
# You could change the URL to example.com/client/3/upload/ as well. You'd have to slightly
# change the logic in get_hidden_object_from_url() to get it from self.kwargs
# rather than from the query parameter
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment