Python Flask学习_用户资料系统总结

本文详细介绍了如何在Python的Flask框架中构建用户资料系统,包括存储用户信息、显示资料页面、编辑资料功能。内容涵盖User模型的字段设置、用户资料页的路由与模板、普通用户和管理员的资料编辑权限,以及相关路由和表单处理。

几乎所有的社交博客都会给用户提供用户资料页,用来展示用户个人信息。

用户资料页用户自己可以访问,也可以编辑。可以访问别人的用户资料页,但是不能编辑。管理员可以访问所有人的用户资料页,也都可以编辑。

一、资料信息

用户资料信息在后台应是存储与数据库中的users表中,因此,在User模型中添加一些字段。

# app/models.py

class User(UserMixin,db.Model):
    #...    
    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)        #最后一次登录时间

about_me的类型是db.Text(),与db.String()最大的不同就是不需要指定最大长度。

member_since和last_seen记录的是一个时间点(称为时间戳),类型是db.DateTime(),默认的值可以由常量来指定,也可以由函数来指定,例如datetime.utcnow()函数,但是default接受的就是函数名,因此变成了datetime.utcnow。需要用到default时,会调用datetime.utcnow()。

last_seen表示最后一次登录时间,因此每次登录都需要更新。在User中提供一个方法来更新last_seen。

# app/models.py

class User(UserMixin,db.Model):
    #...
    def ping():
        self.last_seen = datetime.utcnow()
        db.session.add(self)

每次,收到用户请求时都需要调用ping()方法。auth蓝本中的before_app_request处理程序会在每次请求运行前运行

# app/auth/views.py

@auth.before_app_request
def before_request():
    '''在confirm()前,过滤未确认的账户。更改current_user.last_seen到最新的时间'''
    if current_user.is_authenticated:
        current_user.ping()
        if not current_user.confirmed and request.endpoint[:5] != 'auth.':
            return redirect(url_for('auth.unconfirmed'))

auth是Blueprint的实例,要想在应用到蓝本的请求前做些事情,需要使用before_request钩子,要想在针对全局的请求前做些事情就需要使用before_app_request钩子。这里@auth.before_app_request就是这样的钩子。

二、显示资料信息到用户资料页面 

1.用户页面的路由

# app/main/views.py

@main.route('/user/<username>')
def user(username):
    '''用户资料页。显示发表的文章。'''
    user = User.query.filter_by(username=username).first_or_404()
    if user is None:
        abort(404)
    return render_template('user.html', user=user)

2.用户页面的模板

# app/templates/user.html

{% extends "base.html" %}

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

{% block page_content %}
<div class="page-header">
    <div class="profile-header">
        <h1>{{ user.username }}</h1>
        {% if user.name or user.location %}
        <p>
            {% if user.name %}{{ user.name }}<br>{% endif %}
            {% if user.location %}
                from <a href="http://maps.google.com/?q={{ user.location }}">{{ user.location }}</a><br>
            {% 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>
    </div>
</div>
{% endblock %}

{% if user.name or user.location %}  : user.name和user.location只有有一个不为None,<p></p>才会渲染。

{% if current_user.is_administrator() %}  :如果current_user是管理员,则显示向user.email发email的一个链接。

3.在导航栏添加到用户资料页的链接

app/templates/base.html


三、资料编辑器

普通用户看自己的资料页能够编辑这才是合理的是吧?管理员看普通用户的资料页也能编辑这也是合理的!

(一)普通用户

1.普通用户资料编辑页面的表单

app/main/forms.py

class EditProfileForm(FlaskForm):
    '''普通用户的资料编辑表单'''
    name = StringField('Real Nmae',validators=[Length(0,64)])
    location = StringField('Location',validators=[Length(0,64)])
    about_me = TextAreaField('About me')
    submit = SubmitField('Submit')

2.普通用户资料编辑页面

# app/templdates/edit_profile.html

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

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

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

直接通过wtf.quick_form()快速渲染表单。

3.资料编辑的路由

# app/main/views.py

@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._get_current_object())
        db.session.commit()
        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)

'GET'请求时(表单未填写),form.validate_on_submit()返回False。执行的是把current_user的值赋值给form,因此表单显示时有初值。

'POST'请求时(表单已填写,并提交),form.validate_on_submit()返回True。执行的是把form的值赋值给current_user,再提交到数据库,最后重定向到main.user页面。

(二)管理员用户

管理员不仅能修改普通用户的name,location,about_me,应该还能修改email,username...。也就是说只要管理员愿意,用户的数据是可以随便修改的。

1.管理员编辑用户资料页的表单

# app/main/views.py

@main.route('/edit-profile/<int:id>',methods=['GET','POST'])
@login_required
@admin_required
def edit_profile_admin(id):
    user = User.query.get_or_404(id)                            #数据库中查不到则返回404错误
    form = EditProfileAdminForm(user=user)
    if form.validate_on_submit():
        user.email = form.email.data
        user.username = form.username.data
        user.confirmed = form.confirmed.data
        user.role = Role.query.get(form.role.data)
        user.name = form.name.data
        user.location = form.location.data
        user.about_me = form.about_me.data
        db.session.add(user)
        flash('The Profile has been updated')
        return redirect(url_for('.user',username=user.username))
    form.email.data = user.email
    form.username.data = user.username
    form.confirmed.data = user.confirmed
    form.role.data = user.role_id
    form.name.data = user.name
    form.location.data = user.location
    form.about_me.data = user.about_me
    return render_template('edit_profile.html',form=form,user=user)

@admin_required装饰器是自定义的装饰器。要求是管理员权限,才会执行此视图函数。

app/decorator.py

def permission_required(permission):
    '''定义装饰器@permission_required(permission)'''
    def decorator(f):
        @wraps(f)
        def decorated_function(*args,**kwargs):
            if not current_user.can(permission):
                abort(403)
            return f(*args,**kwargs)
        return decorated_function
    return decorator

def admin_required(f):
    '''定义装饰器@admin_required'''
    return permission_required(Permission.ADMINISTER)(f)

2.页面

return render_template('edit_profile.html',form=form,user=user)   ,可以看到和普通用户视图函数使用的模板是一样的。这是因为edit_profile.html中使用的就是wtf.quick_form()渲染了form,因此,是通用的。

3.资料编辑页的链接 


{% if user == current_user %}如果当前用户访问的是自己的资料编辑页,则显示一个btn,btn上显示“Edit Profile”,链接到.edit_profile视图函数。

{% if current_user.is_administrator() %}如果用户是管理员,则再显示一个btn-danger,btn上显示"Edit Profile [Admin]",链接到.edit_profile_admin视图函数。





评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值