zoukankan      html  css  js  c++  java
  • Flask 学习 九 用户资料

    资料信息

    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())# 和String的区别是不需要指定最大长度
        member_since=db.Column(db.DateTime(),default=datetime.utcnow)# default 可以接受函数为默认值,在需要的时候回自定调用指定的函数,所以不需要加()
        last_seen=db.Column(db.DateTime(),default=datetime.utcnow)# 初始值是当前时间 
            #.....
            def ping(self):
              self.last_seen=datetime.utcnow() # 获取当前时间
              db.session.add(self)# 提交时间到数据库

    app/auth/views.py

    利用auth蓝本中的before_app_first_request方法,来完成每次请求前都要运行ping方法,来实现更新已登录用户的访问时间

    @auth.before_app_first_request
    def before_request():
        if current_user.is_authenticated:
            current_user.ping()
            if not current_user.confirmed and request.endpoint[:5] !='auth.': # 不在认证蓝本中
                return redirect(url_for('auth.unconfirmed'))

     用户资料页面

    为每个用户都创建资料页面

    app/mian/views.py  资料页面路由

    from flask import abort
    
    @main.route('/user/<username>')
    def user(username):
        user = User.query.filter_by(username=username).first()
        if user is None:
            abort(404)
        return render_template('user.html',user=user)

     user.html

    {% extends 'base.html' %}
    {% block title %}flasky -page-not-find{% endblock %}
    
    {% block page_content %}
        <div class="page-header">
        <img class="img-rounded profile-thumbnail" src="{{ user.gravatar(size=256) }}">
        <div class="profile-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://map.baidu.com/?{{ 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>
                注册时间:{{ moment(user.member_since).format('L') }}.
                最后登陆时间:{{ moment(user.last_seen).fromNow() }}
            </p>
        </div>
        </div>
    {% endblock %}

    base.html 添加一条导航,更方便的访问自己的个人资料,未认证的用户看不到导航条

     <ul class="nav navbar-nav">
                <li><a href="/">主页</a></li>
                {% if current_user.is_authenticated %}
                    <li>
                    <a href="{{ url_for('main.user',username=current_user.username) }}">个人资料</a>
                    </li>
                {% endif %}
    </ul>

    资料编辑器-用户级别的资料编辑器

    app/main/forms.py 资料编辑表单

    class EditProflieForm(FlaskForm):
        name = StringField('真实姓名', validators=[Length(0,64)])
        location = StringField('位置', validators=[Length(0,64)])
        about_me = TextAreaField('关于我')
        submit = SubmitField('提交')

    app/main/views.py 资料编辑路由

    @main.route('/edit-profile',methods=['get','post'])
    @login_required
    def edit_profile():
        form = EditProflieForm()
        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('你的资料已经更新')
            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)

    user.html 资料编辑链接

    <p>
       {% if user ==current_user.user %}
        <a  class="btn btn-default" href="{{ url_for('.edit_profile') }}">编辑资料</a>
       {% endif %}
    </p>

    管理员级别的用户编辑器

    main/forms.py

    class EditProflieAdminForm(FlaskForm):
        email=StringField('邮箱', validators=[DataRequired(), Length(1, 64),Email()])
        username = StringField('用户名', validators=[DataRequired(), Length(1, 64), Regexp('^[A-Za-z][A-Za-z0-9_.]*$',0,'用户名必须是字母,数字,点号,下划线')])
        confirmed = BooleanField('确认')
        role = SelectField('角色',coerce=int)# 因为角色id是个整数,所以把字段值转化为整数而不是字符串
        name = StringField('真实姓名', validators=[Length(0, 64)])
        location = StringField('位置', validators=[Length(0, 64)])
        about_me = TextAreaField('关于我')
        submit = SubmitField('提交')
        def __init__(self,user,*args,**kwargs):
            super(EditProflieAdminForm,self).__init__(*args,**kwargs)
            #选项由元祖组成,选项的标识符和显示空间中的文本字符串
            self.role.choices=[(role.id,role.name) for role in Role.query.order_by(Role.name).all()]
            self.user=user
        def validate_email(self, filed):
            #首先检查字段是否发生了变化,并保证新值不和其他用户的字段值重复
            if filed.data != self.user.email and User.query.filter_by(email=filed.data).first():
                raise ValidationError('邮箱已被注册')
    
        def validate_username(self, filed):
            # 首先检查字段是否发生了变化,并保证新值不和其他用户的字段值重复
            if filed.data != self.username and User.query.filter_by(username=filed.data).first():
                raise ValidationError('用户名已被使用')

    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)
        form =EditProflieAdminForm(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('资料已经更新')
            return redirect(url_for('.user',username = user.username))
        form.email.data=user.email
        form.username.data = user.username
        form.confirmed.data=user.confirmed
        # choice属性设置的元祖列表使用数字标识符表示各选项
        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)

    user.html 管理员使用的资料编辑链接

    <p>
          {% if current_user.is_administrator() %}
           <a class="btn btn-danger" href="{{ url_for('.edit_profile_admin',id=user.id) }}">编辑资料[管理员]</a>
          {% endif %}
    </p>

    edit_profile.html

    {% extends "base.html" %}
    {% import "bootstrap/wtf.html" as wtf %}
    
    {% block title %}Flasky - 编辑资料{% endblock %}
    
    {% block page_content %}
    <div class="page-header">
        <h1>编辑你的资料</h1>
    </div>
    <div class="col-md-4">
        {{ wtf.quick_form(form) }}
    </div>
    {% endblock %}

    用户头像 app/models.py

    import hashlib
    from flask import request
    
    def gravatar(self,size=100,default='identicon',rating='g'):
            if request.is_secure:
                url = 'https://secure.gravatar.com/avatar'
            else:
                url='http://www.gravatar.com/avatar'
            hash = self.avatar_hash or hashlib.md5(self.email.encode('utf-8')).hexdigest()
            return '{url}/{hash}?s={size}&d={default}&r={rating}'.format(url=url,hash=hash,size=size,default=default,rating=rating)

    添加资料页面头像 user.html

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

    将邮件生成的md5值保存到数据库,如果更新继续创建

    class User(UserMixin,db.Model):
           def __init__(self,**kwargs):
                if self.email is not None and self.avatar_hash is None:
                        self.avatar_hash=hashlib.md5(self.email.encode('utf-8')).hexdigest()    
          avatar_hash = db.Column(db.String(32))# 头像哈希值存储到数据库
           def change_email(self, token):
                ....
                self.email = new_email
            self.avatar_hash=hashlib.md5(self.email.encode('utf-8')).hexdigest()
            db.session.add(self)
            return True
           def gravatar(self,size=100,default='identicon',rating='g'):
            if request.is_secure:
                url = 'https://secure.gravatar.com/avatar'
            else:
                url='http://www.gravatar.com/avatar'
            hash = self.avatar_hash or hashlib.md5(self.email.encode('utf-8')).hexdigest()
            return '{url}/{hash}?s={size}&d={default}&r={rating}'.format(url=url,hash=hash,size=size,default=default,rating=rating)
            self.last_seen=datetime.utcnow()
            db.session.add(self)
  • 相关阅读:
    three.js 制作一个三维的推箱子游戏
    three.js 郭先生制作太阳系
    three.js 制作魔方
    three.js 欧拉角和四元数
    mysql
    重装系统后需要安装的软件
    python3.7 安装PyQt5
    Java读取文件
    linux 环境jdk安装
    linux 修改用户字符集
  • 原文地址:https://www.cnblogs.com/Erick-L/p/6897184.html
Copyright © 2011-2022 走看看