/ Published in: Python
This is based on FormEncode 1.2 + two patches you get here:
http://code.google.com/p/formalchemy/issues/detail?id=83
and here:
http://code.google.com/p/formalchemy/issues/detail?id=84
(at this point, they might be included in the official release).
http://code.google.com/p/formalchemy/issues/detail?id=83
and here:
http://code.google.com/p/formalchemy/issues/detail?id=84
(at this point, they might be included in the official release).
Expand |
Embed | Plain Text
Copy this code and paste it in your HTML
### My App name = Vigilia ## in vigilia/forms/__init__.py class FieldSet(forms.FieldSet): def _render(self, **kwargs): return render('/fieldset.mako', extra_vars=kwargs) def _render_readonly(self, **kwargs): return render('/fieldset_readonly.mako', extra_vars=kwargs) def insert_after(self, after_what, field): """Insert a field to be rendered after a given field""" idx = self._render_fields._list.index(after_what) if idx is not None: self.insert_at_index(idx + 1, field) else: raise ValueError('No such field in render_fields: %s' % after_what) def insert_at_index(self, idx, field): """Insert a field to be rendered before a given field""" if field.key in self._render_fields._list: self._render_fields._list.remove(field.key) self._render_fields._list.insert(idx, field.key) self._render_fields[field.key] = field class RadioSetRenderer(fields.RadioSet): widget = staticmethod(h.radio) def render(self, options, **kwargs): self.radios = [] self.options = opts = options for i, (choice_name, choice_value) in enumerate(opts): choice_id = '%s_%i' % (self.name, i) radio = self.widget(self.name, choice_name, id=choice_id, checked=self._is_checked(choice_value), **kwargs) label = h.make_tag('label', c=radio + ' %s' % choice_value) self.radios.append(label) return h.make_tag('div', c=h.make_tag("br").join(self.radios)) class CheckboxRenderer(RadioSetRenderer): widget = staticmethod(h.checkbox) class EmailSmsRenderer(fields.TextFieldRenderer): pass class PermissionField(fields.Field): is_collection = False is_composite_foreign_key = False class PermissionsRenderer(fields.SelectFieldRenderer): def render(self, **kwargs): return h.select(self.name, [p.permission for p in self.field.model.permissions], model.permissions_list, size=len(model.permissions_list), id=self.name, multiple=True) def deserialize(self): # This simple calculation makes sure we don't delete rows that # haven't changed. We only add rows that were actually added, # and remove the rows that were actually deleted from the last # saved records. u = self.field.model p1 = set([perm.permission for perm in u.permissions]) p2 = set(self._params.getall(self.name)) p_rem = list(p1.difference(p2)) p_add = list(p2.difference(p1)) # Remove unwanted permissions.. u.permissions = [perm for perm in u.permissions if perm.permission not in p_rem] # Add new permissions for x in p_add: u.permissions.append(model.Permission(x)) return None def password_validator(value, field): if field.parent.passwd1.value != value: raise validators.ValidationError('Les deux mots de passes ne concordent pas') ## in vigilia/model/___init___.py # Permissions definitions permissions_list = [ ('admin', u'Administration globale'), ('moderation', u'Modération des commentaires'), ('posts_admin', u'Administration des posts'), ('posts_post', u'Poster un événement'), ('events_admin', u'Gestion des Activités'), ('logs_view', u'Visionnement des logs'), ] # Users users_t = Table('users', metadata, Column('id', Integer, primary_key=True), Column('username', String(25)), Column('password', String(50)), Column('firstname', Unicode(80)), Column('lastname', Unicode(80)), Column('gender', String(5), default='M'), Column('email', Unicode(255)), Column('email_sms', Unicode(150)), Column('photo', Unicode(255)), # Lien relatif à une variable # de configuration, vers l'image Column('telephone', Unicode(100)), Column('dob', Date), # Date of birth - Sans garder l'année Column('pref_email_new_post', Boolean), Column('pref_email_updt_post', Boolean), Column('pref_email_sms_post', Boolean), # Only when asked for Column('pref_email_new_event', Boolean), Column('pref_email_updt_event', Boolean), ) class User(object): @property def fullname(self): """Create the full-name representation of the user.""" if not self.firstname: return unicode(self.username) return self.firstname + \ (' %s' % self.lastname if self.lastname else '') def __str__(self): return self.fullname def __repr__(self): return "<User: %s>" % self.username def __cmp__(self, other): if self.firstname is None or other.firstname is None: return 0 n1 = self.firstname + self.lastname n2 = other.firstname + other.lastname return cmp(n1, n2) def has_perm(self, *args): """Checks if user has certain permissions""" return has_perm(permissions=[p.permission for p in self.permissions], *args) mapper(User, users_t, { 'post_answers': relation(PostAnswer, lazy=True, backref='answer_user'), 'recipient_to': relation(Recipient, backref='user'), 'last_viewed': relation(LastViewed, backref='user'), 'permissions': relation(Permission), 'openids': relation(OpenID, backref='user'), }) ## in vigilia/controller/users.py from vigilia.lib.base import * log = logging.getLogger(__name__) def gen_fieldset(mdl): fs = forms.FieldSet(mdl) fs.add(forms.Field('passwd1')) fs.add(forms.Field('passwd2')) fs.add(forms.PermissionField(name='permissions')) fs.add(forms.Field('alert', value='').label(u'E-mail notification')\ .checkbox([('X', u'Envoyer un courriel avec ces informations '\ 'au nouvel usager')])\ .with_renderer(forms.CheckboxRenderer)) inc = [fs.username.label(u"Nom d'usager"), fs.passwd1.password().label(u'Mot de passe'), fs.passwd2.password().label(u'Répétez le mot de passe').validate(forms.password_validator), fs.gender.label(u'Genre').radio([('M', 'M'), ('F', 'F')]).with_renderer(forms.RadioSetRenderer), fs.firstname.label(u'Prénom'), fs.lastname.label(u'Nom de famille'), fs.email.label(u'Courriel'), fs.permissions.label(u'Permissions').with_renderer(forms.PermissionsRenderer), fs.groups.label(u'Groupes'), fs.email_sms.label(u'Passerelle SMS (courriel)').with_renderer(forms.EmailSmsRenderer), fs.dob.label(u'Date de naissance').with_renderer(forms.DateFieldRendererFr), ] fs.configure(include=inc) return fs class UsersController(BaseController): @has_perm('admin') def index(self): c.list = model.User.query().order_by('firstname, lastname').all() return render('/users/index.html') @has_perm('admin') def edit(self, id): # New or modify if id: c.usr = model.User.query.get(id) else: c.usr = model.User c.permissions_list = model.permissions_list fs = gen_fieldset(c.usr) fs = fs.bind(c.usr, data=request.POST or None) if not id: # Require password if it's first adding.. fs.insert_after('passwd2', fs.alert) fs.configure(options=[fs.passwd1.required()]) if request.POST and fs.validate(): fs.sync() if fs.passwd1.value: fs.model.password = fs.passwd1.value push_flash(INFO, u"Le mot de passe de l'usager a été modifié") if fs.alert.value: ### TODO: send a notification e-mail here push_flash(INFO, u"Un courriel de notification a été envoyé") meta.Session.commit() push_flash(SUCCESS, u"Usager sauvegardé avec succès") redirect_to(controller='users', action='index') c.fieldset = fs return render('/users/edit.html') ## in vigilia/lib/base.py rom vigilia import forms