1. 程式人生 > >記錄一次完整的flask小型應用開發(3)

記錄一次完整的flask小型應用開發(3)

接下來,我們開始實現使用者資料頁面,即每個使用者可以展示給其他人的個人個性介面
為了讓個人資訊介面看起來更加的充實,我們對User模型新增幾個欄位來記錄更多的使用者資訊:

name = db.Column(db.String(64))
location = db.Column(db.String(64))
about_me = db.Column(db.Text())
member_since = db.Column(db.DateTime(), default=datetime.utcnow)
# 給時間建立初始值,即自動生成的預設值
last_seen = db.Column(db.DateTime(), default=datetime.utcnow)

這個last_seen欄位表示每次只要使用者訪問了網站這個值就會被重新整理,所以我們需要定義一個方法,使用者只要提交了一次請求,就更新這個時間值。先在User模型中定義這個方法:

    def ping(self):
        self.last_seen = datetime.utcnow()
        db.session.add(self)

接下來需要在每次使用者提交請求的時候呼叫這個方法即可,想起之前定義的auth藍本中有一個before_app_request會在每次請求前執行,所以我們可以在這個處理程式裡面呼叫這個方法:

@auth.before_app_request
def before_request():
    if current_user.is_authenticated:
        current_user.ping()
        if not current_user.confirmed \
                and request.endpoint \
                and request.blueprint != 'auth' \
                and request.endpoint != 'static':
            return redirect(url_for('auth.unconfirmed'))

使用者資料頁面

現在我們充實了使用者的各種資訊,所以我們現在可以開始定製個人的使用者資料頁面了。
首先我們定義路由,因為不是認證功能了,所以不要在auth裡面實現了,可以在main裡面實現:

# 為每個使用者定義個人資料頁面路由
@main.route('/user/<username>')
def user(username):
    user = User.query.filter_by(username=username).first()
    # 在資料庫中搜索URL指定的使用者名稱
    if user is None:
        abort(404)
    return render_template('user.html', user=user)

老樣子,實現了路由功能,我們還需要模板來展示:

{% extends "base.html" %}

{% block title %}Flasky - {{ user.username }}{% endblock %}

{% block page_content %}
<div class="page-header">
    <h1>{{ user.username }}</h1>
    {% if user.name or user.location %}
    <p>
        {% if user.name %}{{ user.name }}{% endif %}
        {% if user.location %}
            from <a href="http://maps.google.com/?q={{ user.location }}">{{ user.location }}</a>
        {% endif %}
    </p>
    {% endif %}
    {% if current_user.is_administrator() %}
    <p><a href="mailto:{{ user.email }}">{{ user.email }}</a></p>
    {% endif %}
    {% if user.about_me %}<p>{{ user.about_me }}</p>{% endif %}
    <p>Member since {{ moment(user.member_since).format('L') }}. Last seen {{ moment(user.last_seen).fromNow() }}.</p>
    <p>
        {% if user == current_user %}
        <a class="btn btn-default" href="{{ url_for('.edit_profile') }}">Edit Profile</a>
        {% endif %}
        {% if current_user.is_administrator() %}
        <a class="btn btn-danger" href="{{ url_for('.edit_profile_admin', id=user.id) }}">Edit Profile [Admin]</a>
        {% endif %}
    </p>
</div>
{% endblock %}

這裡如果使用者是管理員,那麼就顯示使用者的電子郵箱,並且渲染成mailto連結,現在我們還想使用者可以在頁面上方的導航欄裡面直接看到profile選項,點進去可以看到使用者的個人資料,那麼,我們在base.html裡面加上:

{% if current_user.is_authenticated %}
<li><a href="{{ url_for('main.user', username=current_user.username) }}">Profile</a></li>
{% endif %}

使用者資料編輯

首先建立普通使用者級別的資料編輯器:

class EditProfileForm(FlaskForm):
    # 普通使用者級別的資料編輯表單
    name = StringField('Real name', validators=[Length(0, 64)])
    location = StringField('Location', validators=[Length(0, 64)])
    about_me = TextAreaField('About me')
    submit = SubmitField('Submit')

然後定義這個路由:

@main.route('/edit-profile', methods=['GET', 'POST'])
@login_required
def edit_profile():
    form = EditProfileForm()
    if form.validate_on_submit():
        current_user.name = form.name.data
        current_user.location = form.location.data
        current_user.about_me = form.about_me.data
        db.session.add(current_user)
        flash('your profile has been updated')
        return redirect(url_for('.user', username=current_user.username))
    # 這裡相當於提交之前,所有為表單的所有欄位設定了初始值
    form.name.data = current_user.name
    form.location.data = current_user.location
    form.about_me.data = current_user.about_me
    return render_template('edit_profile.html', form=form)

這裡實現了功能,我們需要這個編輯資料頁面的渲染模板:

{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %}

{% block title %}Flasky - Edit Profile{% endblock %}

{% block page_content %}
<div class="page-header">
    <h1>Edit Your Profile</h1>
</div>
<div class="col-md-4">
    {{ wtf.quick_form(form) }}
</div>
{% endblock %}

現在還缺少的是使用者從哪裡可以點選進入編輯資料頁面,我們直接在profile頁面定義一個入口:

{% if user == current_user %}
 <a class="btn btn-default" href="{{ url_for('.edit_profile') }}">Edit Profile</a>
{% endif %}

檢查一下功能是沒問題的~!!!

設定使用者頭像

最後我們設定一下使用者的頭像,用於美化頁面。
我們使用Gravatar提供的使用者頭像功能,它能將頭像和電子郵件關聯起來,我們將構建頭像URL的方法寫入User模型中

    def gravatar(self, size=100, default='identicon', rating='g'):
        url = 'https://secure.gravatar.com/avatar'
        hash = hashlib.md5(self.email.lower().encode('utf-8')).hexdigest()
        return '{url}/{hash}?s={size}&d={default}&r={rating}'.format(
            url=url, hash=hash, size=size, default=default, rating=rating)

然後我們將這個頭像顯示到個人資料頁面中:

<img class="img-rounded profile-thumbnail" src="{{ user.gravatar(size=256) }}">

好了,現在頁面中就能顯示圖片了!!!