Flask学习笔记-(五)用户个人资料页实现

用户个人资料页实现

1. 编写用户资料视图函数

​ 新建app/user.py脚本,编写用户资料视图函数。其中通过decorators = [login_required]设置只能登录用户访问,查询时通过first_or_404()可以实现查询不到数据则自动报404错误。

import hashlib
from flask.views import View
from flask import render_template
from flask_login import login_required

from app.models import User


class UserInfoView(View):
    """用户信息查询"""
    methods = ['GET']
    decorators = [login_required]

    def dispatch_request(self, username):
        user = User.query.filter_by(username=username).first_or_404()
        posts = [
            {'author': user, 'body': '测试1'},
            {'author': user, 'body': '测试2'},
        ]
        return render_template('user/user_info.html', user=user, posts=posts)

2. 注册用户蓝图

​ 新增用户蓝图注册,并将用户资料视图类注册到蓝图中。

2.1. 创建用户蓝图并注册用户资料视图

​ 修改app/user.py脚本,创建用户蓝图,并将用户资料视图注册到用户蓝图上。

from flask import Blueprint

# 创建用户蓝图
bp = Blueprint('user', __name__, url_prefix='/user')

# 将用户资料视图注册到用户蓝图上
bp.add_url_rule('/info/<username>', view_func=UserInfoView.as_view('user_info'))

2.2. 注册用户蓝图

​ 修改app/__init__.py脚本,新增用户蓝图注册。

def create_app():
......
	# 用户蓝图注册
    from app import user
    application.register_blueprint(user.bp)
......

3. 编写用户资料页模板

​ 新增app/templates/user/user_info.html文件,用户展示用户资料信息。

{% extends 'base.html' %}

{% block content %}
    <h1>用户:{{ user.username }}</h1>
    <hr>
    {% for post in posts %}
    <p>
        {{ post.author.username }} says: <b>{{ post.body }}</b>
    </p>
    {% endfor %}
{% endblock %}

4. 修改base页面增加用户资料链接

​ 修改app/templates/base.html文件,新增用户资料链接。通过current_user.username获取当前登录用户的用户名,并通过URL传递参数。

......
<body>
    <div>
        博客:
        <a href="{{ url_for('index') }}">首页</a>
        {% if current_user.is_anonymous %}
            <a href="{{ url_for('login') }}">登录</a>
        {% else %}
            <a href="{{ url_for('user.user_info', username=current_user.username) }}">个人资料</a>
            <a href="{{ url_for('logout') }}">退出</a>
        {% endif %}
    </div>
......

5. 添加用户头像

5.1. 安装Flask-Avatars扩展库

​ 用户头像功能,可以通过安装Flask-Avatars扩展库。

pip install Flask-Avatars

5.2. 注册Flask-Avatars扩展库

​ 修改app/__init__.py,新增Flask-Avatars扩展库注册。

from flask_avatars import Avatars

# 实例化flask_avatars
avatars = Avatars()


def create_app():
......
	# 初始化flask_avatars
    avatars.init_app(application)
......

5.3. 创建生成用户头像的模板的环境处理器

​ 生成用户头像,当前项目使用gravatar头像,生成该头像就需要传入邮箱的hash值。修改app/__init__.py脚本,增加email_hash的计算,并通过email_hash获取头像的方法,并将其注册到环境处理其中。模板的环境处理器可以将变量、函数加入到模板环境中,传入后可以在模板中直接调用。

def create_app():
......
    @application.context_processor
    def utility_processor():
        """模板环境处理器注册"""
        def get_avatars(email, *args, **kwargs):
            """根据用户邮箱获取用户头像"""
            import hashlib
            email_hash = hashlib.md5(email.lower().encode('utf-8')).hexdigest()
            return avatars.gravatar(email_hash, *args, **kwargs)
        return dict(get_avatars=get_avatars)

    return application

5.4. 用户资料模板中使用注册方法获取用户头像

​ 修改app/templates/user/user_info.html文件,增加用户头像展示。通过get_avatars(user.email, 64)获取用户头像地址。第一个参数传入用户的email地址,第二个参数用于设置头像图片大小。

{% extends 'base.html' %}

{% block content %}
    <table>
        <tr valign="top">
            <td><img src="{{ get_avatars(user.email, 64) }}"></td>
            <td><h1>用户:{{ user.username }}</h1></td>
        </tr>
    </table>
    <hr>
    {% for post in posts %}
    <table>
        <tr valign="top">
            <td><img src="{{ get_avatars(post.author.email, 36) }}"></td>
            <td>{{ post.author.username }} says:<br>{{ post.body }}</td>
        </tr>
    </table>
    {% endfor %}
{% endblock %}

5.5. 启动服务查看结果

在这里插入图片描述

在这里插入图片描述

6. 提取帖子模板

6.1. 创建子模板

​ 由于首页、用户资料页均需要展示帖子信息,而且格式一致,所以考虑将帖子展示部分提取出子模板进行共用。新建app/templates/common/post.html文件,用于编写共用的帖子展示模板。

    <table>
        <tr valign="top">
            <td><img src="{{ get_avatars(post.author.email, 36) }}"></td>
            <td>{{ post.author.username }} says:<br>{{ post.body }}</td>
        </tr>
    </table>

6.2. 用户资料模板调用子模板

​ 修改app/templates/user/user_info.html模板文件,修改为通过include调用子模板方式。

{% extends 'base.html' %}

{% block content %}
    <table>
        <tr valign="top">
            <td><img src="{{ get_avatars(user.email, 64) }}"></td>
            <td><h1>用户:{{ user.username }}</h1></td>
        </tr>
    </table>
    <hr>
    {% for post in posts %}
        {% include 'common/post.html' %}
    {% endfor %}
{% endblock %}

6.3. 首页模板修改为调用子模板

​ 修改app/templates/index/index.html模板文件,修改为调用子模板方式。

{% extends 'base.html' %}

{% block content %}
    <h1>Hi, {{ current_user.username }}!</h1>
    {% for post in posts %}
        {% include 'common/post.html' %}
    {% endfor %}
{% endblock %}

​ 修改app/index.py脚本,修改测试数据。

class IndexView(View):
    methods = ['GET']
    decorators = [login_required]

    def dispatch_request(self):
        posts = [
            {
                'author': {'username': '李白', 'email': 'lib@126.com'},
                'body': '举头望明月,低头思故乡'
            },
            {
                'author': {'username': '李清照', 'email': 'liqz@126.com'},
                'body': '知否,知否,应是绿肥红瘦'
            }
        ]

        return render_template('index/index.html', title='首页', posts=posts)

6.4. 启动服务查看结果

在这里插入图片描述

在这里插入图片描述

7. 扩展用户资料信息

7.1. 扩展用户模型

​ 在app/models.py用户模型中增加关于自己、最后访问时间等字段,用于记录用户的个人介绍和登录情况。

class User(UserMixin, db.Model):
......
    # 个人介绍
    about_me = db.Column(db.String(140))
    # 最后访问时间
    last_seen = db.Column(db.DateTime, default=datetime.timezone)
......

7.2. 数据库迁移

flask db migrate -m '新增about_me、last_seen字段'
flask db upgrade

7.3. 用户资料模板增加展示项

​ 修改app/templates/user/user_info.html文件,增加about_me、last_seen展示。

......
            <td><img src="{{ get_avatars(user.email, 64) }}"></td>
            <td>
                <h1>用户:{{ user.username }}</h1>
                {% if user.about_me %}
                    <p>{{ user.about_me }}</p>
                {% endif %}
                {% if user.last_seen %}
                    最后访问于:<p>{{ user.last_seen }}</p>
                {% endif %}
            </td>
......

7.4. 注册周期函数实现最后访问时间的更新

​ 修改app/__init__.py脚本,增加@before_request周期函数的处理,用于在每次请求时,登记其最后访问时间字段。

def create_app():
......
	@application.before_request
    def before_request():
        """请求前周期函数"""
        # 用户已登录则登记用户请求时间
        if current_user.is_authenticated:
            current_user.last_seen = datetime.timezone
            db.session.commit()

    return application

8. 新增资料编辑功能

8.1. 新增用户资料编辑表单

​ 修改app/forms.py脚本,增加用户资料编辑表单。

class UserInfoEditForm(FlaskForm):
    """用户信息编辑表单"""
    username = StringField('用户名', validators=[DataRequired()])
    about_me = TextAreaField('个人简介', validators=[Length(min=0, max=140)])
    submit = SubmitField('提交')

8.2. 新增用户资料编辑模板

​ 新增app/templates/user/user_info_edit.html文件,新建用户资料修改模板。

{% extends 'base.html' %}

{% block content %}
    <h1>个人资料编辑</h1>
    <form action="" method="post">
        {{ form.hidden_tag() }}
        <p>
            {{ form.username.label }}<br>
            {{ form.username(size=32) }}<br>
            {% for error in form.username.errors %}
                <span style="color: red;">[{{ error }}]</span>
            {% endfor %}
        </p>
        <p>
            {{ form.about_me.label }}<br>
            {{ form.about_me(cols=50, rows=4) }}<br>
            {% for error in form.about_me.errors %}
                <span style="color: red;">[{{ error }}]</span>
            {% endfor %}
        </p>
        <p>{{ form.submit() }}</p>
    </form>
{% endblock %}

8.3. 新增用户资料编辑视图

修改app/user.py文件,新建用户资料修改视图,并注册到用户蓝图中。

class UserInfoEditView(View):
    """用户资料编辑"""
    methods = ['GET', 'POST']
    decorators = [login_required]

    def dispatch_request(self):
        form = UserInfoEditForm()
        # 验证通过更新当前登录用户信息
        if form.validate_on_submit():
            current_user.username = form.username.data
            current_user.about_me = form.about_me.data
            db.session.commit()
            flash('您的修改已保存')
            return redirect(url_for('user_info_edit'))
        elif request.method == 'GET':
            # 查询是获取当前用户的信息
            form.username.data = current_user.username
            form.about_me.data = current_user.about_me
        return render_template('user/user_info_edit.html', title='个人信息编辑', form=form)
        
# 将用户资料修改视图注册到用户蓝图上
bp.add_url_rule('/edit', view_func=UserInfoEditView.as_view('user_info_edit'))

8.4. 用户模板增加用户资料编辑链接

​ 修改app/templates/user/user_info.html文件,新增用户资料编辑链接。

......
                {% if user.last_seen %}
                    最后访问于:<p>{{ user.last_seen }}</p>
                {% endif %}
                {% if user == current_user %}
                    <p><a href="{{ url_for('user.user_info_edit') }}">编辑您的资料</a></p>
                {% endif %}
            </td>
......

8.5. 启动服务查看结果

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值