Skip to content

Commit 6aa8227

Browse files
Chapter 10: Profiles editor (10b)
1 parent 6837b08 commit 6aa8227

File tree

4 files changed

+117
-4
lines changed

4 files changed

+117
-4
lines changed

app/main/forms.py

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,50 @@
11
from flask_wtf import FlaskForm
2-
from wtforms import StringField, SubmitField
3-
from wtforms.validators import DataRequired
2+
from wtforms import StringField, TextAreaField, BooleanField, SelectField,\
3+
SubmitField
4+
from wtforms.validators import DataRequired, Length, Email, Regexp
5+
from wtforms import ValidationError
6+
from ..models import Role, User
47

58

69
class NameForm(FlaskForm):
710
name = StringField('What is your name?', validators=[DataRequired()])
811
submit = SubmitField('Submit')
12+
13+
14+
class EditProfileForm(FlaskForm):
15+
name = StringField('Real name', validators=[Length(0, 64)])
16+
location = StringField('Location', validators=[Length(0, 64)])
17+
about_me = TextAreaField('About me')
18+
submit = SubmitField('Submit')
19+
20+
21+
class EditProfileAdminForm(FlaskForm):
22+
email = StringField('Email', validators=[DataRequired(), Length(1, 64),
23+
Email()])
24+
username = StringField('Username', validators=[
25+
DataRequired(), Length(1, 64),
26+
Regexp('^[A-Za-z][A-Za-z0-9_.]*$', 0,
27+
'Usernames must have only letters, numbers, dots or '
28+
'underscores')])
29+
confirmed = BooleanField('Confirmed')
30+
role = SelectField('Role', coerce=int)
31+
name = StringField('Real name', validators=[Length(0, 64)])
32+
location = StringField('Location', validators=[Length(0, 64)])
33+
about_me = TextAreaField('About me')
34+
submit = SubmitField('Submit')
35+
36+
def __init__(self, user, *args, **kwargs):
37+
super(EditProfileAdminForm, self).__init__(*args, **kwargs)
38+
self.role.choices = [(role.id, role.name)
39+
for role in Role.query.order_by(Role.name).all()]
40+
self.user = user
41+
42+
def validate_email(self, field):
43+
if field.data != self.user.email and \
44+
User.query.filter_by(email=field.data).first():
45+
raise ValidationError('Email already registered.')
46+
47+
def validate_username(self, field):
48+
if field.data != self.user.username and \
49+
User.query.filter_by(username=field.data).first():
50+
raise ValidationError('Username already in use.')

app/main/views.py

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1-
from flask import render_template, abort
1+
from flask import render_template, redirect, url_for, abort, flash
2+
from flask_login import login_required, current_user
23
from . import main
3-
from ..models import User
4+
from .forms import EditProfileForm, EditProfileAdminForm
5+
from .. import db
6+
from ..models import Role, User
7+
from ..decorators import admin_required
48

59

610
@main.route('/')
@@ -12,3 +16,49 @@ def index():
1216
def user(username):
1317
user = User.query.filter_by(username=username).first_or_404()
1418
return render_template('user.html', user=user)
19+
20+
21+
@main.route('/edit-profile', methods=['GET', 'POST'])
22+
@login_required
23+
def edit_profile():
24+
form = EditProfileForm()
25+
if form.validate_on_submit():
26+
current_user.name = form.name.data
27+
current_user.location = form.location.data
28+
current_user.about_me = form.about_me.data
29+
db.session.add(current_user._get_current_object())
30+
db.session.commit()
31+
flash('Your profile has been updated.')
32+
return redirect(url_for('.user', username=current_user.username))
33+
form.name.data = current_user.name
34+
form.location.data = current_user.location
35+
form.about_me.data = current_user.about_me
36+
return render_template('edit_profile.html', form=form)
37+
38+
39+
@main.route('/edit-profile/<int:id>', methods=['GET', 'POST'])
40+
@login_required
41+
@admin_required
42+
def edit_profile_admin(id):
43+
user = User.query.get_or_404(id)
44+
form = EditProfileAdminForm(user=user)
45+
if form.validate_on_submit():
46+
user.email = form.email.data
47+
user.username = form.username.data
48+
user.confirmed = form.confirmed.data
49+
user.role = Role.query.get(form.role.data)
50+
user.name = form.name.data
51+
user.location = form.location.data
52+
user.about_me = form.about_me.data
53+
db.session.add(user)
54+
db.session.commit()
55+
flash('The profile has been updated.')
56+
return redirect(url_for('.user', username=user.username))
57+
form.email.data = user.email
58+
form.username.data = user.username
59+
form.confirmed.data = user.confirmed
60+
form.role.data = user.role_id
61+
form.name.data = user.name
62+
form.location.data = user.location
63+
form.about_me.data = user.about_me
64+
return render_template('edit_profile.html', form=form, user=user)

app/templates/edit_profile.html

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{% extends "base.html" %}
2+
{% import "bootstrap/wtf.html" as wtf %}
3+
4+
{% block title %}Flasky - Edit Profile{% endblock %}
5+
6+
{% block page_content %}
7+
<div class="page-header">
8+
<h1>Edit Your Profile</h1>
9+
</div>
10+
<div class="col-md-4">
11+
{{ wtf.quick_form(form) }}
12+
</div>
13+
{% endblock %}

app/templates/user.html

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,13 @@ <h1>{{ user.username }}</h1>
1818
{% endif %}
1919
{% if user.about_me %}<p>{{ user.about_me }}</p>{% endif %}
2020
<p>Member since {{ moment(user.member_since).format('L') }}. Last seen {{ moment(user.last_seen).fromNow() }}.</p>
21+
<p>
22+
{% if user == current_user %}
23+
<a class="btn btn-default" href="{{ url_for('.edit_profile') }}">Edit Profile</a>
24+
{% endif %}
25+
{% if current_user.is_administrator() %}
26+
<a class="btn btn-danger" href="{{ url_for('.edit_profile_admin', id=user.id) }}">Edit Profile [Admin]</a>
27+
{% endif %}
28+
</p>
2129
</div>
2230
{% endblock %}

0 commit comments

Comments
 (0)