user profile page

This commit is contained in:
Miguel Grinberg 2012-12-16 00:31:21 -08:00
parent 5ae5241485
commit d8e9bfe8bd
8 changed files with 133 additions and 5 deletions

View File

@ -1,7 +1,10 @@
from flask.ext.wtf import Form, TextField, BooleanField
from flask.ext.wtf import Required
from flask.ext.wtf import Form, TextField, BooleanField, TextAreaField
from flask.ext.wtf import Required, Length
class LoginForm(Form):
openid = TextField('openid', validators = [Required()])
remember_me = BooleanField('remember_me', default = False)
class EditForm(Form):
nickname = TextField('nickname', validators = [Required()])
about_me = TextAreaField('about_me', validators = [Length(min = 0, max = 140)])

View File

@ -1,3 +1,4 @@
from hashlib import md5
from app import db
ROLE_USER = 0
@ -9,6 +10,8 @@ class User(db.Model):
email = db.Column(db.String(120), index = True, unique = True)
role = db.Column(db.SmallInteger, default = ROLE_USER)
posts = db.relationship('Post', backref = 'author', lazy = 'dynamic')
about_me = db.Column(db.String(140))
last_seen = db.Column(db.DateTime)
def is_authenticated(self):
return True
@ -22,6 +25,9 @@ class User(db.Model):
def get_id(self):
return unicode(self.id)
def avatar(self, size):
return 'http://www.gravatar.com/avatar/' + md5(self.email).hexdigest() + '?d=mm&s=' + str(size)
def __repr__(self):
return '<User %r>' % (self.nickname)

View File

@ -10,6 +10,7 @@
<div>Microblog:
<a href="{{ url_for('index') }}">Home</a>
{% if g.user.is_authenticated() %}
| <a href="{{ url_for('user', nickname = g.user.nickname) }}">Your Profile</a>
| <a href="{{ url_for('logout') }}">Logout</a>
{% endif %}
</div>

23
app/templates/edit.html Normal file
View File

@ -0,0 +1,23 @@
<!-- extend base layout -->
{% extends "base.html" %}
{% block content %}
<h1>Edit Your Profile</h1>
<form action="" method="post" name="edit">
{{form.hidden_tag()}}
<table>
<tr>
<td>Your nickname:</td>
<td>{{form.nickname(size = 24)}}</td>
</tr>
<tr>
<td>About yourself:</td>
<td>{{form.about_me(cols = 32, rows = 4)}}</td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="Save Changes"></td>
</tr>
</table>
</form>
{% endblock %}

5
app/templates/post.html Normal file
View File

@ -0,0 +1,5 @@
<table>
<tr valign="top">
<td><img src="{{post.author.avatar(50)}}"></td><td><i>{{post.author.nickname}} says:</i><br>{{post.body}}</td>
</tr>
</table>

20
app/templates/user.html Normal file
View File

@ -0,0 +1,20 @@
<!-- extend base layout -->
{% extends "base.html" %}
{% block content %}
<table>
<tr valign="top">
<td><img src="{{user.avatar(128)}}"></td>
<td>
<h1>User: {{user.nickname}}</h1>
{% if user.about_me %}<p>{{user.about_me}}</p>{% endif %}
{% if user.last_seen %}<p><i>Last seen on: {{user.last_seen}}</i></p>{% endif %}
{% if user.id == g.user.id %}<p><a href="{{url_for('edit')}}">Edit</a></p>{% endif %}
</td>
</tr>
</table>
<hr>
{% for post in posts %}
{% include 'post.html' %}
{% endfor %}
{% endblock %}

View File

@ -1,8 +1,9 @@
from flask import render_template, flash, redirect, session, url_for, request, g
from flask.ext.login import login_user, logout_user, current_user, login_required
from app import app, db, lm, oid
from forms import LoginForm
from forms import LoginForm, EditForm
from models import User, ROLE_USER, ROLE_ADMIN
from datetime import datetime
@lm.user_loader
def load_user(id):
@ -11,6 +12,10 @@ def load_user(id):
@app.before_request
def before_request():
g.user = current_user
if g.user.is_authenticated():
g.user.last_seen = datetime.utcnow()
db.session.add(g.user)
db.session.commit()
@app.route('/')
@app.route('/index')
@ -70,3 +75,36 @@ def after_login(resp):
def logout():
logout_user()
return redirect(url_for('index'))
@app.route('/user/<nickname>')
@login_required
def user(nickname):
user = User.query.filter_by(nickname = nickname).first()
if user == None:
flash('User ' + nickname + ' not found.')
return redirect(url_for('index'))
posts = [
{ 'author': user, 'body': 'Test post #1' },
{ 'author': user, 'body': 'Test post #2' }
]
return render_template('user.html',
user = user,
posts = posts)
@app.route('/edit', methods = ['GET', 'POST'])
@login_required
def edit():
form = EditForm()
if form.validate_on_submit():
g.user.nickname = form.nickname.data
g.user.about_me = form.about_me.data
db.session.add(g.user)
db.session.commit()
flash('Your changes have been saved.')
return redirect(url_for('edit'))
else:
form.nickname.data = g.user.nickname
form.about_me.data = g.user.about_me
return render_template('edit.html',
form = form)

View File

@ -0,0 +1,32 @@
from sqlalchemy import *
from migrate import *
from migrate.changeset import schema
pre_meta = MetaData()
post_meta = MetaData()
user = Table('user', post_meta,
Column('id', Integer, primary_key=True, nullable=False),
Column('nickname', String(length=64)),
Column('email', String(length=120)),
Column('role', SmallInteger, default=ColumnDefault(0)),
Column('about_me', String(length=140)),
Column('last_seen', DateTime),
)
def upgrade(migrate_engine):
# Upgrade operations go here. Don't create your own engine; bind
# migrate_engine to your metadata
pre_meta.bind = migrate_engine
post_meta.bind = migrate_engine
post_meta.tables['user'].columns['about_me'].create()
post_meta.tables['user'].columns['last_seen'].create()
def downgrade(migrate_engine):
# Operations to reverse the above upgrade go here.
pre_meta.bind = migrate_engine
post_meta.bind = migrate_engine
post_meta.tables['user'].columns['about_me'].drop()
post_meta.tables['user'].columns['last_seen'].drop()