5dollarwhitebox.org - theboxownsyou

  • blog
  • projects
  • articles
  • tech wiki
  • about
  • login
Home › Python Reference

RSS Feed

Python: Unique Username, Groupname, Email Validators for TurboGears 2.0 Form Widgets

drks — Thu, 2009-12-31 00:34

Disclaimer: This is a rough brain dump. I plan on doing a proper hello world in the near future, but wanted to get this somewhere accessible so I didn't forget about it.

I came across a rather annoying issue of how to properly handle duplicate usernames, groupnames, and email addresses in turbogears 2. What I came up with was a set of validators that can be added to chained_validators on your form validation. I'm using the dMirr project as an example of how I'm using these validators:

dmirr/widgets/validators.py:

import re
import pylons
from pylons.i18n import ugettext as _
from formencode import Invalid
from formencode.schema import SimpleFormValidator
from tw.forms.validators import Email
 
from dmirr.model import DBSession as db
from dmirr import model
 
__all__ = ['UniqueEmail', 'UniqueUserName', 'UniqueGroupName']
 
def validate_unique_email(value_dict, state, validator):
    # first for edit forms
    if value_dict.has_key('user_id'):
        u1 = db.query(model.User).filter_by(user_id=value_dict['user_id'])\
             .first()
        if u1.email_address != value_dict['email_address']:
            u2 = db.query(model.User)\
                 .filter_by(email_address=value_dict['email_address']).first()
            if u2:
                return {'email_address':'The address already exists.'}
    # or new form                
    else:
        u1 = db.query(model.User)\
             .filter_by(email_address=value_dict['email_address']).first()
        if u1:
            return {'email_address':'The address already exists.'}
 
 
def validate_unique_user_name(value_dict, state, validator):
    # first for edit forms
    if value_dict.has_key('user_id'):
        u1 = db.query(model.User).filter_by(user_id=value_dict['user_id'])\
             .first()
        if u1 and u1.user_name != value_dict['user_name']:
            u2 = db.query(model.User)\
                 .filter_by(user_name=value_dict['user_name']).first()
            if u2:
                return {'user_name':'The user name already exists.'}
    # or new form        
    else:
        u1 = db.query(model.User)\
             .filter_by(user_name=value_dict['user_name']).first()
        if u1:
            return {'user_name':'The user name already exists.'}
 
def validate_unique_group_name(value_dict, state, validator):
    # first for edit forms
    if value_dict.has_key('group_id'):
        g1 = db.query(model.Group).filter_by(group_id=value_dict['group_id'])\
             .first()
        if g1 and g1.group_name != value_dict['group_name']:
            g2 = db.query(model.Group)\
                 .filter_by(group_name=value_dict['gropu_name']).first()
            if g2:
                return {'group_name':'The group name already exists.'}
    # or new form                
    else:
        g1 = db.query(model.Group)\
             .filter_by(group_name=value_dict['group_name']).first()
        if g1:
            return {'group_name':'The group name already exists.'}
 
UniqueEmail = SimpleFormValidator(validate_unique_email)
UniqueUserName = SimpleFormValidator(validate_unique_user_name)
UniqueGroupName = SimpleFormValidator(validate_unique_group_name)



The easiest way to use this is to add the validator to your chained_validators under your form widget.

dmirr/widgets/user_form.py:

"""User Form"""
 
import re
from pylons.i18n import ugettext as _
from tg import config, url
from tw.api import CSSLink
from tw.forms import TableForm, TextField, TextArea, CheckBox, Spacer, \
                     HiddenField, PasswordField, Label, SubmitButton, Button
from tw.forms.validators import Schema, Int, NotEmpty, UnicodeString, \
                                FieldsMatch, Email, URL        
 
from dmirr.widgets.validators import UniqueEmail, UniqueUserName
 
 
class DynamicLabel(Label):
    value = ''
    template = 'dmirr.widgets.templates.dynamic_label' 
 
class UserNewForm(TableForm):
    css = [CSSLink(link=url('/theme/%s/_css/user.css' % config['theme']))]
    validator = Schema(
        chained_validators=[
            FieldsMatch('email_address', 'confirm_email'),
            FieldsMatch('password', 'confirm_password'),
            UniqueEmail(),
            UniqueUserName(),
            ]
        )
    fields = [
        TextField('user_name', label_text='User Name', help_text="This can not be changed.", 
            validator=UnicodeString(not_empty=True)),
        TextField('display_name', label_text='Display Name',
            validator=UnicodeString(not_empty=True)),
        TextField('web_url', label_text='Web URL',
            validator=URL(not_empty=False)),    
        Spacer(),
        TextField('email_address', label_text='Email Address',
            validator=Email(not_empty=True)),
        TextField('confirm_email', label_text='Confirm Email'),
        Spacer(),
        PasswordField('password', label_text='Password',
            validator=UnicodeString(not_empty=True)),
        PasswordField('confirm_password', label_text='Confirm Password'),
        Spacer(),
        TextArea('about', label_text='About/Description'),
        Spacer(),
        TextArea('terms', label_text='Terms of Use'),
        CheckBox('agreed_to_terms', label_text='Agree to Terms', 
            help_text="Check if you agree to the terms of use.",
            validator=NotEmpty),
        ]
    submit_text = 'Register User'
 
class UserEditForm(TableForm):
    css = [CSSLink(link=url('/theme/%s/_css/user.css' % config['theme']))]
    validator = Schema(
        chained_validators=[
            FieldsMatch('password', 'confirm_password'),
            UniqueEmail(),
            UniqueUserName(),
            ]
        )
    fields = [
        HiddenField('user_id', validator=Int()),
        HiddenField('user_name'),
        HiddenField('_method'),
        #TextField('user_name', label_text='User Name',  
        #    validator=UnicodeString(not_empty=True)),
        DynamicLabel('user_name', label_text="User Name", suppress_label=False),
        TextField('display_name', label_text='Display Name',
            validator=UnicodeString(not_empty=True)),
        TextField('web_url', label_text='Web URL',
            validator=URL(not_empty=False)), 
        TextField('email_address', label_text='Email Address',
            validator=Email(not_empty=True)),
        Spacer(),
        PasswordField('password', label_text='Password',
            validator=UnicodeString(not_empty=False)),
        PasswordField('confirm_password', label_text='Confirm Password'),
        Spacer(),
        TextArea('about', label_text='About/Description'),
        SubmitButton('submit', attrs=dict(value="Save User")),
        Button('Cancel', attrs=dict(value="Cancel", onClick="history.back();"))
        ] 
 
create_user_form = UserNewForm("create_user_form", action=url('/user/'))
edit_user_form = UserEditForm("edit_user_form", action=url('/user/?_method=PUT'))



You can see that I use both the standard Email validator in the widget, and also the new UniqueEmail, UniqueUserName validators in the chained_validators. All that is required is a hidden 'user_id' field in your form so that the validator can look up the current values in the database to compare against.

‹ Python: Setting up a TurboGears Application Under Shared Namespace up Python: Getting Started with setuptools ›
  • Printer-friendly version

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Very interesting, i like this

odżywki (not verified) — Sun, 2010-01-31 21:13

Very interesting, i like this website.Look my website : Odżywki

  • reply

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Post new comment

The content of this field is kept private and will not be shown publicly.
Input format
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.
  • Lines and paragraphs break automatically.
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>, <bash>, <c>, <cpp>, <diff>, <drupal5>, <drupal6>, <java>, <javascript>, <mysql>, <perl>, <php>, <python>, <ruby>. Beside the tag style "<foo>" it is also possible to use "[foo]".

More information about formatting options



Who's online

There are currently 0 users and 1 guest online.
  • blog
  • projects
  • articles
  • tech wiki
  • about
  • login

5dollarwhitebox.org is not responsible in anyway for actions performed based on information found on this site.