def send_emails(self, request, form_for_form, form, entry, attachments): subject = form.email_subject if not subject: subject = "%s - %s" % (form.title, entry.entry_time) fields = [] for (k, v) in form_for_form.fields.items(): value = form_for_form.cleaned_data[k] if isinstance(value, list): value = ", ".join([i.strip() for i in value]) fields.append((v.label, value)) context = { "fields": fields, "message": form.email_message, "request": request, } email_from = form.email_from or settings.DEFAULT_FROM_EMAIL email_to = form_for_form.email_to() if email_to and form.send_email: send_mail_template(subject, "form_response", email_from, email_to, context=context, fail_silently=EMAIL_FAIL_SILENTLY) headers = None if email_to: headers = {"Reply-To": email_to} email_copies = split_choices(form.email_copies) if email_copies: send_mail_template(subject, "form_response_copies", email_from, email_copies, context=context, attachments=attachments, fail_silently=EMAIL_FAIL_SILENTLY, headers=headers)
def form_detail(request, slug, template="forms/form_detail.html"): """ Display a built form and handle submission. """ published = Form.objects.published(for_user=request.user) form = get_object_or_404(published, slug=slug) if form.login_required and not request.user.is_authenticated(): return redirect("%s?%s=%s" % (settings.LOGIN_URL, REDIRECT_FIELD_NAME, urlquote(request.get_full_path()))) request_context = RequestContext(request) args = (form, request_context, request.POST or None, request.FILES or None) form_for_form = FormForForm(*args) if request.method == "POST": if not form_for_form.is_valid(): form_invalid.send(sender=request, form=form_for_form) else: entry = form_for_form.save() subject = form.email_subject if not subject: subject = "%s - %s" % (form.title, entry.entry_time) fields = [] for (k, v) in form_for_form.fields.items(): value = form_for_form.cleaned_data[k] if isinstance(value, list): value = ", ".join([i.strip() for i in value]) fields.append((v.label, value)) context = { "fields": fields, "message": form.email_message, "request": request, } email_from = form.email_from or settings.DEFAULT_FROM_EMAIL email_to = form_for_form.email_to() if email_to and form.send_email: send_mail_template(subject, "form_response", email_from, email_to, context=context, fail_silently=settings.DEBUG) email_copies = split_choices(form.email_copies) if email_copies: if email_to and SEND_FROM_SUBMITTER: # Send from the email entered. email_from = email_to attachments = [] for f in form_for_form.files.values(): f.seek(0) attachments.append((f.name, f.read())) send_mail_template(subject, "form_response", email_from, email_copies, context=context, attachments=attachments, fail_silently=settings.DEBUG) form_valid.send(sender=request, form=form_for_form, entry=entry) return redirect(reverse("form_sent", kwargs={"slug": form.slug})) context = {"form": form} return render_to_response(template, context, request_context)
def assemble_attachments(self, request, form_for_form, form): """ Prepaires the content of the email. Returns a list of assembled attachments. """ email_copies = split_choices(form.email_copies) attachments = [] if email_copies: for f in form_for_form.files.values(): f.seek(0) attachments.append((f.name, f.read())) return attachments
def __init__(self, form, context, *args, **kwargs): """ Dynamically add each of the form fields for the given form model instance and its related field model instances. """ self.form = form self.form_fields = form.fields.visible() initial = kwargs.pop("initial", {}) # If a FormEntry instance is given to edit, stores it's field # values for using as initial data. field_entries = {} if kwargs.get("instance"): for field_entry in kwargs["instance"].fields.all(): field_entries[field_entry.field_id] = field_entry.value super(FormForForm, self).__init__(*args, **kwargs) # Create the form fields. for field in self.form_fields: field_key = field.slug field_class = fields.CLASSES[field.field_type] field_widget = fields.WIDGETS.get(field.field_type) field_args = { "label": field.label, "required": field.required, "help_text": field.help_text } arg_names = field_class.__init__.__code__.co_varnames if "max_length" in arg_names: field_args["max_length"] = settings.FIELD_MAX_LENGTH if "choices" in arg_names: choices = list(field.get_choices()) if field.field_type == fields.SELECT and not ( field.required and field.default): # The first OPTION with attr. value="" display only if... # 1. ...the field is not required. # 2. ...the field is required and the default is not set. text = "" if field.placeholder_text is None else field.placeholder_text choices.insert(0, ("", text)) field_args["choices"] = choices if field_widget is not None: field_args["widget"] = field_widget # # Initial value for field, in order of preference: # # - If a form model instance is given (eg we're editing a # form response), then use the instance's value for the # field. # - If the developer has provided an explicit "initial" # dict, use it. # - The default value for the field instance as given in # the admin. # initial_val = None try: initial_val = field_entries[field.id] except KeyError: try: initial_val = initial[field_key] except KeyError: initial_val = Template(field.default).render(context) if initial_val: if field.is_a(*fields.MULTIPLE): initial_val = split_choices(initial_val) if field.field_type == fields.CHECKBOX: initial_val = initial_val != "False" self.initial[field_key] = initial_val self.fields[field_key] = field_class(**field_args) if field.field_type == fields.DOB: now = datetime.now() years = list(range(now.year, now.year - 120, -1)) self.fields[field_key].widget.years = years # Add identifying CSS classes to the field. css_class = field_class.__name__.lower() # Do not add the 'required' field to the CheckboxSelectMultiple because it will # mean that all checkboxes have to be checked instead of the usual use case of # "at least one". if field.required and (field_widget != forms.CheckboxSelectMultiple): css_class += " required" if settings.USE_HTML5: # Except Django version 1.10 this is necessary for all versions from 1.8 to 1.11. self.fields[field_key].widget.attrs[ "required"] = "required" self.fields[field_key].widget.attrs["class"] = css_class if field.placeholder_text and not field.default and field.field_type != fields.SELECT: # Attribute `placeholder` not allowed on element `select` at this point. # See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select # or check the code in https://validator.w3.org. text = field.placeholder_text self.fields[field_key].widget.attrs["placeholder"] = text
# The filter function for each filter type FILTER_FUNCS = { FILTER_CHOICE_CONTAINS: lambda val, field: val.lower() in field.lower(), FILTER_CHOICE_DOESNT_CONTAIN: lambda val, field: val.lower() not in field.lower(), FILTER_CHOICE_EQUALS: lambda val, field: val.lower() == field.lower(), FILTER_CHOICE_DOESNT_EQUAL: lambda val, field: val.lower() != field.lower(), FILTER_CHOICE_BETWEEN: lambda val_from, val_to, field: ((not val_from or val_from <= field) and (not val_to or val_to >= field)), FILTER_CHOICE_CONTAINS_ANY: lambda val, field: set(val) & set(split_choices(field)), FILTER_CHOICE_CONTAINS_ALL: lambda val, field: set(val) == set(split_choices(field)), FILTER_CHOICE_DOESNT_CONTAIN_ANY: lambda val, field: not set(val) & set(split_choices(field)), FILTER_CHOICE_DOESNT_CONTAIN_ALL: lambda val, field: set(val) != set(split_choices(field)), } # Export form fields for each filter type grouping text_filter_field = forms.ChoiceField(label=" ", required=False, choices=TEXT_FILTER_CHOICES) choice_filter_field = forms.ChoiceField(label=" ", required=False, choices=CHOICE_FILTER_CHOICES)
def __init__(self, form, context, *args, **kwargs): """ Dynamically add each of the form fields for the given form model instance and its related field model instances. """ self.form = form self.form_fields = form.fields.visible() initial = kwargs.pop("initial", {}) # If a FormEntry instance is given to edit, stores it's field # values for using as initial data. field_entries = {} if kwargs.get("instance"): for field_entry in kwargs["instance"].fields.all(): field_entries[field_entry.field_id] = field_entry.value super(FormForForm, self).__init__(*args, **kwargs) # Create the form fields. for field in self.form_fields: field_key = field.slug field_class = fields.CLASSES[field.field_type] field_widget = fields.WIDGETS.get(field.field_type) field_args = { "label": field.label, "required": field.required, "help_text": field.help_text } arg_names = field_class.__init__.__code__.co_varnames if "max_length" in arg_names: field_args["max_length"] = settings.FIELD_MAX_LENGTH if "choices" in arg_names: choices = list(field.get_choices()) if (field.field_type == fields.SELECT and field.default not in [c[0] for c in choices]): choices.insert(0, ("", field.placeholder_text)) field_args["choices"] = choices if field_widget is not None: field_args["widget"] = field_widget # # Initial value for field, in order of preference: # # - If a form model instance is given (eg we're editing a # form response), then use the instance's value for the # field. # - If the developer has provided an explicit "initial" # dict, use it. # - The default value for the field instance as given in # the admin. # initial_val = None try: initial_val = field_entries[field.id] except KeyError: try: initial_val = initial[field_key] except KeyError: initial_val = Template(field.default).render(context) if initial_val: if field.is_a(*fields.MULTIPLE): initial_val = split_choices(initial_val) if field.field_type == fields.CHECKBOX: initial_val = initial_val != "False" self.initial[field_key] = initial_val self.fields[field_key] = field_class(**field_args) if field.field_type == fields.DOB: now = datetime.now() years = list(range(now.year, now.year - 120, -1)) self.fields[field_key].widget.years = years # Add identifying CSS classes to the field. css_class = field_class.__name__.lower() if field.required: css_class += " required" if (settings.USE_HTML5 and field.field_type != fields.CHECKBOX_MULTIPLE): self.fields[field_key].widget.attrs["required"] = "" self.fields[field_key].widget.attrs["class"] = css_class if field.placeholder_text and not field.default: text = field.placeholder_text self.fields[field_key].widget.attrs["placeholder"] = text
def __init__(self, form, context, *args, **kwargs): """ Dynamically add each of the form fields for the given form model instance and its related field model instances. """ self.form = form self.form_fields = form.fields.visible() initial = kwargs.pop("initial", {}) # If a FormEntry instance is given to edit, stores it's field # values for using as initial data. field_entries = {} if kwargs.get("instance"): for field_entry in kwargs["instance"].fields.all(): field_entries[field_entry.field_id] = field_entry.value super(FormForForm, self).__init__(*args, **kwargs) # Create the form fields. for field in self.form_fields: if field.field_type == fields.DYNAMIC: maximum_instances = field.get_max() for count in range(maximum_instances): field_key = field.slug+str(count) field_class = fields.CLASSES[field.field_type] field_widget = fields.WIDGETS.get(field.field_type) field_args = {"label": field.label, "required": field.required, "help_text": field.help_text} arg_names = field_class.__init__.im_func.func_code.co_varnames if "max_length" in arg_names: field_args["max_length"] = settings.FIELD_MAX_LENGTH if "choices" in arg_names: field_args["choices"] = field.get_choices() if field_widget is not None: field_args["widget"] = field_widget # Initial value for field, in order of preference: # # - If a form model instance is given (eg we're editing a # form response), then use the instance's value for the # field. # - If the developer has provided an explicit "initial" # dict, use it. # - The default value for the field instance as given in # the admin. # initial_val = None try: initial_val = field_entries[field.id] except KeyError: try: initial_val = initial[field_key] except KeyError: initial_val = Template(field.default).render(context) if initial_val: if field.is_a(*fields.MULTIPLE): initial_val = split_choices(initial_val) if field.field_type == fields.CHECKBOX: initial_val = initial_val != "False" self.initial[field_key] = initial_val self.fields[field_key] = field_class(**field_args) # Add identifying CSS classes to the field. css_class = field_class.__name__.lower() if field.required: css_class += " required" if (settings.USE_HTML5 and field.field_type != fields.CHECKBOX_MULTIPLE): self.fields[field_key].widget.attrs["required"] = "" self.fields[field_key].widget.attrs["class"] = css_class if field.placeholder_text and not field.default: text = field.placeholder_text self.fields[field_key].widget.attrs["placeholder"] = text else: field_key = field.slug field_class = fields.CLASSES[field.field_type] field_widget = fields.WIDGETS.get(field.field_type) field_args = {"label": field.label, "required": field.required, "help_text": field.help_text} arg_names = field_class.__init__.im_func.func_code.co_varnames if "max_length" in arg_names: field_args["max_length"] = settings.FIELD_MAX_LENGTH if "choices" in arg_names: field_args["choices"] = field.get_choices() if field_widget is not None: field_args["widget"] = field_widget # # Initial value for field, in order of preference: # # - If a form model instance is given (eg we're editing a # form response), then use the instance's value for the # field. # - If the developer has provided an explicit "initial" # dict, use it. # - The default value for the field instance as given in # the admin. # initial_val = None try: initial_val = field_entries[field.id] except KeyError: try: initial_val = initial[field_key] except KeyError: initial_val = Template(field.default).render(context) if initial_val: if field.is_a(*fields.MULTIPLE): initial_val = split_choices(initial_val) if field.field_type == fields.CHECKBOX: initial_val = initial_val != "False" self.initial[field_key] = initial_val self.fields[field_key] = field_class(**field_args) if field.field_type == fields.DOB: now = datetime.now() years = range(now.year, now.year - 120, -1) self.fields[field_key].widget.years = years # Add identifying CSS classes to the field. css_class = field_class.__name__.lower() if field.required: css_class += " required" if (settings.USE_HTML5 and field.field_type != fields.CHECKBOX_MULTIPLE): self.fields[field_key].widget.attrs["required"] = "" self.fields[field_key].widget.attrs["class"] = css_class if field.placeholder_text and not field.default: text = field.placeholder_text self.fields[field_key].widget.attrs["placeholder"] = text
FILTER_FUNCS = { FILTER_CHOICE_CONTAINS: lambda val, field: val.lower() in field.lower(), FILTER_CHOICE_DOESNT_CONTAIN: lambda val, field: val.lower() not in field.lower(), FILTER_CHOICE_EQUALS: lambda val, field: val.lower() == field.lower(), FILTER_CHOICE_DOESNT_EQUAL: lambda val, field: val.lower() != field.lower(), FILTER_CHOICE_BETWEEN: lambda val_from, val_to, field: ( (not val_from or val_from <= field) and (not val_to or val_to >= field) ), FILTER_CHOICE_CONTAINS_ANY: lambda val, field: set(val) & set(split_choices(field)), FILTER_CHOICE_CONTAINS_ALL: lambda val, field: set(val) == set(split_choices(field)), FILTER_CHOICE_DOESNT_CONTAIN_ANY: lambda val, field: not set(val) & set(split_choices(field)), FILTER_CHOICE_DOESNT_CONTAIN_ALL: lambda val, field: set(val) != set(split_choices(field)), } # Export form fields for each filter type grouping text_filter_field = forms.ChoiceField(label=" ", required=False, choices=TEXT_FILTER_CHOICES) choice_filter_field = forms.ChoiceField(label=" ", required=False, choices=CHOICE_FILTER_CHOICES) multiple_filter_field = forms.ChoiceField(label=" ", required=False, choices=MULTIPLE_FILTER_CHOICES)
def __init__(self, form, context, *args, **kwargs): """ Dynamically add each of the form fields for the given form model instance and its related field model instances. """ self.form = form self.form_fields = form.fields.visible() initial = kwargs.pop("initial", {}) # If a FormEntry instance is given to edit, stores it's field # values for using as initial data. field_entries = {} if kwargs.get("instance"): for field_entry in kwargs["instance"].fields.all(): field_entries[field_entry.field_id] = field_entry.value super(FormForForm, self).__init__(*args, **kwargs) # Create the form fields. for field in self.form_fields: field_key = field.slug field_class = fields.CLASSES[field.field_type] field_widget = fields.WIDGETS.get(field.field_type) field_args = {"label": field.label, "required": field.required, "help_text": field.help_text} arg_names = field_class.__init__.__code__.co_varnames if "max_length" in arg_names: field_args["max_length"] = settings.FIELD_MAX_LENGTH if "choices" in arg_names: choices = list(field.get_choices()) if field.field_type == fields.SELECT and not (field.required and field.default): # The first OPTION with attr. value="" display only if... # 1. ...the field is not required. # 2. ...the field is required and the default is not set. text = "" if field.placeholder_text is None else field.placeholder_text choices.insert(0, ("", text)) field_args["choices"] = choices if field_widget is not None: field_args["widget"] = field_widget # # Initial value for field, in order of preference: # # - If a form model instance is given (eg we're editing a # form response), then use the instance's value for the # field. # - If the developer has provided an explicit "initial" # dict, use it. # - The default value for the field instance as given in # the admin. # initial_val = None try: initial_val = field_entries[field.id] except KeyError: try: initial_val = initial[field_key] except KeyError: initial_val = Template(field.default).render(context) if initial_val: if field.is_a(*fields.MULTIPLE): initial_val = split_choices(initial_val) if field.field_type == fields.CHECKBOX: initial_val = initial_val != "False" self.initial[field_key] = initial_val self.fields[field_key] = field_class(**field_args) if field.field_type == fields.DOB: now = datetime.now() years = list(range(now.year, now.year - 120, -1)) self.fields[field_key].widget.years = years # Add identifying CSS classes to the field. css_class = field_class.__name__.lower() # Do not add the 'required' field to the CheckboxSelectMultiple because it will # mean that all checkboxes have to be checked instead of the usual use case of # "at least one". if field.required and (field_widget != forms.CheckboxSelectMultiple): css_class += " required" if settings.USE_HTML5: # Except Django version 1.10 this is necessary for all versions from 1.8 to 1.11. self.fields[field_key].widget.attrs["required"] = "required" self.fields[field_key].widget.attrs["class"] = css_class if field.placeholder_text and not field.default and field.field_type != fields.SELECT: # Attribute `placeholder` not allowed on element `select` at this point. # See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select # or check the code in https://validator.w3.org. text = field.placeholder_text self.fields[field_key].widget.attrs["placeholder"] = text
def __init__(self, form, context, *args, **kwargs): """ Dynamically add each of the form fields for the given form model instance and its related field model instances. """ self.fieldsets = [] # supported by the fieldsetMixin self.form = form self.form_fields = form.fields.visible() initial = kwargs.pop("initial", {}) # If a FormEntry instance is given to edit, stores it's field # values for using as initial data. field_entries = {} if kwargs.get("instance"): for field_entry in kwargs["instance"].fields.all(): field_entries[field_entry.field_id] = field_entry.value super(FormForForm, self).__init__(*args, **kwargs) from pprint import pprint print "initial fieldsets:" pprint(self.fieldsets) #self._tmpl_p[0] = u'<div class="fieldset" >%(title)s%(description)s%(fields)s</div>' mutable = list(self._tmpl_p) mutable[ 0] = u'<div class="fieldset" >%(title)s%(description)s%(fields)s</div>' self._tmpl_p = tuple(mutable) # Create the form fields. for field in self.form_fields: #### if not field.page: print "Field", field, "has no page assignment" pass # our fieldset page name page description, field name #add_field_to_fieldsets( self.fieldsets, 'Questions', ' ', field.slug) #).replace(' ', '_') ) else: print "adding", field.slug, "to", field.page.name add_field_to_fieldsets( self.fieldsets, field.page.name, field.page.description, field.slug) #str(field).replace(' ', '_') ) #### field_key = field.slug field_class = fields.CLASSES[field.field_type] field_widget = fields.WIDGETS.get(field.field_type) field_args = { "label": field.label, "required": field.required, "help_text": field.help_text } arg_names = field_class.__init__.im_func.func_code.co_varnames if "max_length" in arg_names: field_args["max_length"] = settings.FIELD_MAX_LENGTH if "choices" in arg_names: field_args["choices"] = field.get_choices() if field_widget is not None: field_args["widget"] = field_widget # # Initial value for field, in order of preference: # # - If a form model instance is given (eg we're editing a # form response), then use the instance's value for the # field. # - If the developer has provided an explicit "initial" # dict, use it. # - The default value for the field instance as given in # the admin. # initial_val = None try: initial_val = field_entries[field.id] except KeyError: try: initial_val = initial[field_key] except KeyError: initial_val = Template(field.default).render(context) if initial_val: if field.is_a(*fields.MULTIPLE): initial_val = split_choices(initial_val) if field.field_type == fields.CHECKBOX: initial_val = initial_val != "False" self.initial[field_key] = initial_val self.fields[field_key] = field_class(**field_args) if field.field_type == fields.DOB: now = datetime.now() years = range(now.year, now.year - 120, -1) self.fields[field_key].widget.years = years # Add identifying CSS classes to the field. css_class = field_class.__name__.lower() if field.required: css_class += " required" if (settings.USE_HTML5 and field.field_type != fields.CHECKBOX_MULTIPLE): self.fields[field_key].widget.attrs["required"] = "" self.fields[field_key].widget.attrs["class"] = css_class if field.placeholder_text and not field.default: text = field.placeholder_text self.fields[field_key].widget.attrs["placeholder"] = text
def __init__(self, form, context, *args, **kwargs): """ Dynamically add each of the form fields for the given form model instance and its related field model instances. """ self.fieldsets = [] # supported by the fieldsetMixin self.form = form self.form_fields = form.fields.visible() initial = kwargs.pop("initial", {}) # If a FormEntry instance is given to edit, stores it's field # values for using as initial data. field_entries = {} if kwargs.get("instance"): for field_entry in kwargs["instance"].fields.all(): field_entries[field_entry.field_id] = field_entry.value super(FormForForm, self).__init__(*args, **kwargs) from pprint import pprint print "initial fieldsets:" pprint( self.fieldsets ) #self._tmpl_p[0] = u'<div class="fieldset" >%(title)s%(description)s%(fields)s</div>' mutable = list( self._tmpl_p ) mutable[0] = u'<div class="fieldset" >%(title)s%(description)s%(fields)s</div>' self._tmpl_p = tuple( mutable ) # Create the form fields. for field in self.form_fields: #### if not field.page: print "Field", field, "has no page assignment" pass # our fieldset page name page description, field name #add_field_to_fieldsets( self.fieldsets, 'Questions', ' ', field.slug) #).replace(' ', '_') ) else: print "adding", field.slug, "to", field.page.name add_field_to_fieldsets( self.fieldsets, field.page.name, field.page.description, field.slug )#str(field).replace(' ', '_') ) #### field_key = field.slug field_class = fields.CLASSES[field.field_type] field_widget = fields.WIDGETS.get(field.field_type) field_args = {"label": field.label, "required": field.required, "help_text": field.help_text} arg_names = field_class.__init__.im_func.func_code.co_varnames if "max_length" in arg_names: field_args["max_length"] = settings.FIELD_MAX_LENGTH if "choices" in arg_names: field_args["choices"] = field.get_choices() if field_widget is not None: field_args["widget"] = field_widget # # Initial value for field, in order of preference: # # - If a form model instance is given (eg we're editing a # form response), then use the instance's value for the # field. # - If the developer has provided an explicit "initial" # dict, use it. # - The default value for the field instance as given in # the admin. # initial_val = None try: initial_val = field_entries[field.id] except KeyError: try: initial_val = initial[field_key] except KeyError: initial_val = Template(field.default).render(context) if initial_val: if field.is_a(*fields.MULTIPLE): initial_val = split_choices(initial_val) if field.field_type == fields.CHECKBOX: initial_val = initial_val != "False" self.initial[field_key] = initial_val self.fields[field_key] = field_class(**field_args) if field.field_type == fields.DOB: now = datetime.now() years = range(now.year, now.year - 120, -1) self.fields[field_key].widget.years = years # Add identifying CSS classes to the field. css_class = field_class.__name__.lower() if field.required: css_class += " required" if (settings.USE_HTML5 and field.field_type != fields.CHECKBOX_MULTIPLE): self.fields[field_key].widget.attrs["required"] = "" self.fields[field_key].widget.attrs["class"] = css_class if field.placeholder_text and not field.default: text = field.placeholder_text self.fields[field_key].widget.attrs["placeholder"] = text