Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mezzanine.forms add user field (optional) #600

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions mezzanine/forms/defaults.py
Expand Up @@ -64,3 +64,10 @@
editable=False,
default=(),
)

register_setting(
name="FORMS_VISIBLE_USER_COLOMN",
description=_("Display users column in admin view entries list"),
editable=False,
default=False
)
69 changes: 49 additions & 20 deletions mezzanine/forms/forms.py
@@ -1,4 +1,3 @@

from datetime import date, datetime
from os.path import join, split
from uuid import uuid4
Expand All @@ -13,7 +12,8 @@

from mezzanine.conf import settings
from mezzanine.forms import fields
from mezzanine.forms.models import FormEntry, FieldEntry
from mezzanine.forms.fields import HIDDEN
from mezzanine.forms.models import FormEntry, FieldEntry, Field
from mezzanine.utils.timezone import now


Expand Down Expand Up @@ -57,12 +57,12 @@
lambda val_from, val_to, field: val_from <= field <= val_to
}

text_filter_field = forms.ChoiceField(label=" ", required=False,
choices=TEXT_FILTER_CHOICES)
choice_filter_field = forms.ChoiceField(label=" ", required=False,
choices=CHOICE_FILTER_CHOICES)
date_filter_field = forms.ChoiceField(label=" ", required=False,
choices=DATE_FILTER_CHOICES)
text_filter_field = forms.ChoiceField(
label=" ", required=False, choices=TEXT_FILTER_CHOICES)
choice_filter_field = forms.ChoiceField(
label=" ", required=False, choices=CHOICE_FILTER_CHOICES)
date_filter_field = forms.ChoiceField(
label=" ", required=False, choices=DATE_FILTER_CHOICES)


class FormForForm(forms.ModelForm):
Expand All @@ -73,7 +73,7 @@ class FormForForm(forms.ModelForm):

class Meta:
model = FormEntry
exclude = ("form", "entry_time")
exclude = ("form", "entry_time", "user")

def __init__(self, form, *args, **kwargs):
"""
Expand Down Expand Up @@ -139,20 +139,21 @@ def __init__(self, form, *args, **kwargs):
setattr(self.fields[field_key], "type",
field_class.__name__.lower())
if (field.required and settings.FORMS_USE_HTML5 and
field.field_type != fields.CHECKBOX_MULTIPLE):
field.field_type != fields.CHECKBOX_MULTIPLE):
self.fields[field_key].widget.attrs["required"] = ""
if field.placeholder_text and not field.default:
text = field.placeholder_text
self.fields[field_key].widget.attrs["placeholder"] = text

def save(self, **kwargs):
def save(self, user=None, **kwargs):
"""
Create a ``FormEntry`` instance and related ``FieldEntry``
instances for each form field.
"""
entry = super(FormForForm, self).save(commit=False)
entry.form = self.form
entry.entry_time = now()
entry.user = user
entry.save()
entry_fields = entry.fields.values_list("field_id", flat=True)
new_entry_fields = []
Expand Down Expand Up @@ -206,7 +207,19 @@ def __init__(self, form, request, *args, **kwargs):
"""
self.form = form
self.request = request
self.form_fields = form.fields.all()
self.form_fields = list(form.fields.all())

# Add ``FormEntry.user`` as a field.
if settings.FORMS_VISIBLE_USER_COLOMN:
self.user_field = user_field = Field()
user_field.id = -1
user_field.choices = ""
user_field.field_type = HIDDEN
user_field.label = FormEntry._meta.get_field("user").verbose_name
self.form_fields.append(user_field)
else:
self.user_field = None

self.entry_time_name = unicode(FormEntry._meta.get_field(
"entry_time").verbose_name).encode("utf-8")
super(EntriesForm, self).__init__(*args, **kwargs)
Expand All @@ -221,9 +234,9 @@ def __init__(self, form, request, *args, **kwargs):
choices = ((True, _("Checked")), (False, _("Not checked")))
else:
choices = field.get_choices()
contains_field = forms.MultipleChoiceField(label=" ",
choices=choices, widget=forms.CheckboxSelectMultiple(),
required=False)
contains_field = forms.MultipleChoiceField(
label=" ", choices=choices,
widget=forms.CheckboxSelectMultiple(), required=False)
self.fields["%s_filter" % field_key] = choice_filter_field
self.fields["%s_contains" % field_key] = contains_field
elif field.is_a(*fields.DATES):
Expand All @@ -240,9 +253,8 @@ def __init__(self, form, request, *args, **kwargs):
self.fields["%s_contains" % field_key] = contains_field
# Add ``FormEntry.entry_time`` as a field.
field_key = "field_0"
self.fields["%s_export" % field_key] = forms.BooleanField(initial=True,
label=FormEntry._meta.get_field("entry_time").verbose_name,
required=False)
self.fields["%s_export" % field_key] = forms.BooleanField(
initial=True, label=self.entry_time_name, required=False)
self.fields["%s_filter" % field_key] = date_filter_field
self.fields["%s_from" % field_key] = forms.DateField(
label=" ", widget=SelectDateWidget(), required=False)
Expand Down Expand Up @@ -295,8 +307,8 @@ def rows(self, csv=False):

# Get the field entries for the given form and filter by entry_time
# if specified.
field_entries = FieldEntry.objects.filter(entry__form=self.form
).order_by("-entry__id").select_related(depth=1)
field_entries = FieldEntry.objects.filter(entry__form=self.form)\
.order_by("-entry__id").select_related('entry', 'entry__user')
if self.cleaned_data["field_0_filter"] == FILTER_CHOICE_BETWEEN:
time_from = self.cleaned_data["field_0_from"]
time_to = self.cleaned_data["field_0_to"]
Expand All @@ -322,6 +334,23 @@ def rows(self, csv=False):
valid_row = True
if include_entry_time:
current_row[-1] = field_entry.entry.entry_time
if self.user_field is not None:
field_id = self.user_field.id
filter_type = self.cleaned_data.get(
"field_%s_filter" % field_id)
if filter_type:
filter_arg = self.cleaned_data[
"field_%s_contains" % field_id]
filter_func = FILTER_FUNCS[filter_type]
if not filter_func(
filter_arg, unicode(field_entry.entry.user)):
valid_row = False
try:
current_row[field_indexes[field_id]] = \
field_entry.entry.user
except KeyError:
pass

field_value = field_entry.value or ""
# Check for filter.
field_id = field_entry.field_id
Expand Down
145 changes: 145 additions & 0 deletions mezzanine/forms/migrations/0006_auto__add_field_formentry_user.py
@@ -0,0 +1,145 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models


class Migration(SchemaMigration):

def forwards(self, orm):
# Adding field 'FormEntry.user'
db.add_column(u'forms_formentry', 'user',
self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True, blank=True),
keep_default=False)


def backwards(self, orm):
# Deleting field 'FormEntry.user'
db.delete_column(u'forms_formentry', 'user_id')


models = {
u'auth.group': {
'Meta': {'object_name': 'Group'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
u'auth.permission': {
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
u'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
u'forms.field': {
'Meta': {'ordering': "('_order',)", 'object_name': 'Field'},
'_order': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
'choices': ('django.db.models.fields.CharField', [], {'max_length': '1000', 'blank': 'True'}),
'default': ('django.db.models.fields.CharField', [], {'max_length': '2000', 'blank': 'True'}),
'field_type': ('django.db.models.fields.IntegerField', [], {}),
'form': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'fields'", 'to': u"orm['forms.Form']"}),
'help_text': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'label': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
'placeholder_text': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
'required': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'visible': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
u'forms.fieldentry': {
'Meta': {'object_name': 'FieldEntry'},
'entry': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'fields'", 'to': u"orm['forms.FormEntry']"}),
'field_id': ('django.db.models.fields.IntegerField', [], {}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'value': ('django.db.models.fields.CharField', [], {'max_length': '2000', 'null': 'True'})
},
u'forms.form': {
'Meta': {'ordering': "('_order',)", 'object_name': 'Form', '_ormbases': [u'pages.Page']},
'button_text': ('django.db.models.fields.CharField', [], {'default': "u'Submit'", 'max_length': '50'}),
'content': ('mezzanine.core.fields.RichTextField', [], {}),
'email_copies': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
'email_from': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'email_message': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'email_subject': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
u'page_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['pages.Page']", 'unique': 'True', 'primary_key': 'True'}),
'response': ('mezzanine.core.fields.RichTextField', [], {}),
'send_email': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
u'forms.formentry': {
'Meta': {'object_name': 'FormEntry'},
'entry_time': ('django.db.models.fields.DateTimeField', [], {}),
'form': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'entries'", 'to': u"orm['forms.Form']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'})
},
u'generic.assignedkeyword': {
'Meta': {'ordering': "('_order',)", 'object_name': 'AssignedKeyword'},
'_order': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'keyword': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'assignments'", 'to': u"orm['generic.Keyword']"}),
'object_pk': ('django.db.models.fields.IntegerField', [], {})
},
u'generic.keyword': {
'Meta': {'object_name': 'Keyword'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'site': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['sites.Site']"}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '2000', 'null': 'True', 'blank': 'True'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '500'})
},
u'pages.page': {
'Meta': {'ordering': "('titles',)", 'object_name': 'Page'},
'_meta_title': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True', 'blank': 'True'}),
'_order': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
'content_model': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'expiry_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'gen_description': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'in_menus': ('mezzanine.pages.fields.MenusField', [], {'default': '(1, 2, 3)', 'max_length': '100', 'null': 'True', 'blank': 'True'}),
'in_sitemap': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'keywords': ('mezzanine.generic.fields.KeywordsField', [], {'object_id_field': "'object_pk'", 'to': u"orm['generic.AssignedKeyword']", 'frozen_by_south': 'True'}),
'keywords_string': ('django.db.models.fields.CharField', [], {'max_length': '500', 'blank': 'True'}),
'login_required': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': u"orm['pages.Page']"}),
'publish_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'short_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
'site': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['sites.Site']"}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '2000', 'null': 'True', 'blank': 'True'}),
'status': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
'titles': ('django.db.models.fields.CharField', [], {'max_length': '1000', 'null': 'True'})
},
u'sites.site': {
'Meta': {'ordering': "('domain',)", 'object_name': 'Site', 'db_table': "'django_site'"},
'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
}
}

complete_apps = ['forms']
4 changes: 4 additions & 0 deletions mezzanine/forms/models.py
@@ -1,6 +1,7 @@

from django.db import models
from django.utils.translation import ugettext_lazy as _
from mezzanine.utils.models import get_user_model_name

from mezzanine.conf import settings
from mezzanine.core.fields import RichTextField
Expand Down Expand Up @@ -114,6 +115,9 @@ class FormEntry(models.Model):

form = models.ForeignKey("Form", related_name="entries")
entry_time = models.DateTimeField(_("Date/time"))
user = models.ForeignKey(get_user_model_name(),
verbose_name=_("Entry poster"),
null=True, blank=True)

class Meta:
verbose_name = _("Form entry")
Expand Down
2 changes: 1 addition & 1 deletion mezzanine/forms/page_processors.py
Expand Up @@ -30,7 +30,7 @@ def form_processor(request, page):
url = page.get_absolute_url() + "?sent=1"
if is_spam(request, form, url):
return redirect(url)
entry = form.save()
entry = form.save(user=request.user)
subject = page.form.email_subject
if not subject:
subject = "%s - %s" % (page.form.title, entry.entry_time)
Expand Down