Skip to content

Instantly share code, notes, and snippets.

@jsocol
Created September 21, 2011 03:50
Show Gist options
  • Select an option

  • Save jsocol/1231199 to your computer and use it in GitHub Desktop.

Select an option

Save jsocol/1231199 to your computer and use it in GitHub Desktop.
Form-based user settings
from django import forms
from tower import ugettext_lazy as _lazy
class SettingForm(forms.Form):
auto_watch_new_threads = forms.BooleanField(
default=True, required=False, initial=True,
help_text=_lazy('Automatically watch threads I create.'))
auto_watch_reply = forms.BooleanField(
default=True, required=False, initial=True,
help_text=_lazy('Automatically watch threads I reply to.'))
def save(self):
# Here we'd have to do some work to coerce the different field types
# into values we can pack into your Value class.
#def is_valid(self): # We wouldn't need to rehash any of this functionality.
{# In the settings template, we wouldn't need to recreate the form widgets. #}
{# I also left out field errors but we should definitely include those. #}
<form>
<fieldset>{# We can lay all this out however we want, and change/reorganize over time. #}
<div>
{{ form.fields['auto_watch_reply'].render() }}{# I forget exactly how you have to do this. #}
{{ form.fields['auto_watch_reply'].label() }}
</div>
<div>{# ... for each field ... #}</div>
</fieldset>
<div class="submit"><button type="submit" value="{{ _('Save settings') }}"></div>
</form>
"""There is one more hard bit: getting settings for users.
We'd want to be lazy here, but we also can't wait until a user has visited
the edit-settings page. What if they hit a view that needs one of those
settings? I think we need some sort of indirection, maybe a classmethod on
the Value class, to give us someway of asking for a value and defining
a default.
Here's one strawman API.
"""
class Value(ModelBase): # In models.py, mostly as-is, with this method:
@classmethod
def get_for_user(user, setting, default=None):
# Some implementation. It would be _awesome_ if this could coerce
# values according to the form, e.g. BooleanFields would come out
# of this as True/False, etc.
# Then in code that needs this, say in the forms:
if Value.get_for_user(request.user, 'auto_watch_reply', True):
# Do stuff if the setting is True, or the user has never changed
# the default. This isn't perfect, since the default might need to be
# set in multiple places. Maybe if we don't pass a default we can
# figure it out from the form?
# views.py gets a lot simpler, and safer, using the Django form validation.
# There might be a bit more to it than this but probably not a whole lot.
from users.forms import SettingForm
@login_required
@require_http_methods(['GET', 'POST'])
def edit_settings(request):
if request.method == 'POST':
form = SettingForm(request.POST)
if form.is_valid():
form.save() # Here there be magic.
messages.add_message(request, *a)
return HttpResponseRedirect() # Back to the form.
else:
form = SettingForm()
return jingo.render(request, 'users/settings.html', {'form': form})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment