欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python的Flask框架中實(shí)現(xiàn)登錄用戶的個(gè)人資料和頭像的教程

 更新時(shí)間:2015年04月20日 15:45:52   投稿:goldensun  
這篇文章主要介紹了Python的Flask框架中實(shí)現(xiàn)登錄用戶的個(gè)人資料和頭像的教程,這也是各個(gè)web框架的最基本功能之一,需要的朋友可以參考下

用戶資料頁(yè)面

在用戶資料頁(yè)面,基本上沒(méi)有什么特別要強(qiáng)調(diào)和介紹的新概念。只需要?jiǎng)?chuàng)建一個(gè)含有HTML的新視圖函數(shù)模板頁(yè)面即可。

下面是視圖函數(shù)(項(xiàng)目目錄/views.py):
 

@app.route('/user/<nickname>')
@login_required
def user(nickname):
  user = User.query.filter_by(nickname = nickname).first()
  if user == None:
    flash('不存在用戶:' + nickname + '!')
    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標(biāo)識(shí)主要是用來(lái)說(shuō)明此視圖函數(shù)不同于之前的那些。我們定義了一個(gè)名為<nickname>的參數(shù)。在函數(shù)里面它會(huì)轉(zhuǎn)化成跟它同名的參數(shù),當(dāng)用戶有請(qǐng)求的時(shí)候,例如這樣的一個(gè)URL:URL/user/miguel,次視圖函數(shù)就會(huì)識(shí)別為有一個(gè)名為nickname值為'miguel'的參數(shù),即nickname = 'miguel'。


沒(méi)必要為此方法的實(shí)現(xiàn)過(guò)程感到驚訝。首先我們需要通過(guò)把轉(zhuǎn)化后的nickname參數(shù)作為條件,嘗試著從數(shù)據(jù)庫(kù)里把此用戶的數(shù)據(jù)調(diào)用出來(lái)。如果沒(méi)有查詢到數(shù)據(jù),我們就像之前那樣,給用戶一個(gè)錯(cuò)誤的提示并且跳轉(zhuǎn)到主頁(yè)去。

一旦我們找到了改用戶,我們就在模板下面來(lái)顯示該用戶的文章。要注意下的是在用戶資料頁(yè)面我們只讓顯示該用戶的文章,所以文章的作者要是該用戶。

初始化的視圖模板非常的簡(jiǎn)單(項(xiàng)目目錄/templates/user.html):
 

<!-- extend base layout -->
{% extends "base.html" %}
 
{% block content %}
<h1>用戶昵稱: {{user.nickname}}!</h1>
<hr>
{% for post in posts %}
<p>
 {{post.author.nickname}} 發(fā)布了: <b>{{post.body}}</b>
</p>
{% endfor %}
{% endblock %}

用戶資料頁(yè)面就做好了,不過(guò)在站點(diǎn)中還沒(méi)有指向改頁(yè)面的鏈接地址。為了讓用戶很方便的來(lái)查看自己的資料信息我們就把鏈接地址放到最上面的導(dǎo)航上去(項(xiàng)目目錄/templates/base.html):


 

<div>Microblog:
    <a href="{{ url_for('index') }}">Home</a>
    {% if g.user.is_authenticated() %}
    | <a href="{{ url_for('user', nickname = g.user.nickname) }}">你的個(gè)人資料</a>
    | <a href="{{ url_for('logout') }}">退出登陸</a>
    {% endif %}
  </div>

注意一下我們已經(jīng)給函數(shù)傳參了之后的和之前的URL。

現(xiàn)在就來(lái)試一試這個(gè)項(xiàng)目。點(diǎn)擊上面的“你的資料”鏈接就會(huì)跳轉(zhuǎn)到用戶資料頁(yè)面。由于我們還沒(méi)有指向一個(gè)隨意用戶資料頁(yè)面的鏈接地址,所以在這里如果你想看他人的資料,就需要自己手動(dòng)輸入一下地址了。比如你想看miguel的資料,那么地址就是:http://localhost:5000/user/miguelt


頭像部分

我相信你會(huì)覺(jué)得目前的用戶資料頁(yè)面看起來(lái)很單調(diào)。為了好看,我們就來(lái)添加用戶頭像的功能。

為了避免我們服務(wù)器需要來(lái)處理大量上傳后的頭像圖片,我們?cè)谶@里就使用Gravatar給咋們提供的用戶頭像即可。

鑒于返回一個(gè)用戶頭像是屬于用戶這塊的,所以我們就把代碼放在theUserclass里面(項(xiàng)目目錄/models.py):

 

from hashlib import md5
# ...
class User(db.Model):
  # ...
  def avatar(self, size):
    return 'http://www.gravatar.com/avatar/' + md5(self.email).hexdigest() +
    '?d=mm&s=' + str(size)

avatar將會(huì)返回用戶頭像圖片的地址, 根據(jù)你的需要來(lái)請(qǐng)求你想要的圖片尺寸像素。


從Gravatar上得到圖像圖片很簡(jiǎn)單。你只需要用md5把用戶的郵箱hash加密之后合并成上面的那種url形式即可。當(dāng)然你也可以自由選擇自 定義圖像大小。其中“d=mm”是設(shè)置用戶在沒(méi)有Gravatar賬號(hào)的情況下顯示的默認(rèn)頭像?!癿m”選項(xiàng)會(huì)返回一張只有人輪廓的灰色圖片,稱之為“謎 樣人”。而“s=”選項(xiàng)是用來(lái)設(shè)置返回你給定的圖片尺寸像素。

當(dāng)然Gravatar也有自己的文檔來(lái)描述URL的拼接技術(shù)!

到這里Userclass就可以返回一個(gè)用戶頭像的圖片了,我們就需要把這個(gè)整合到用戶資料布局去(項(xiàng)目目錄/templates/user.html):
 

<!-- extend base layout -->
{% extends "base.html" %}
 
{% block content %}
<table>
  <tr valign="top">
    <td><img src="{{user.avatar(128)}}"></td>
    <td><h1>用戶昵稱: {{user.nickname}}</h1></td>
  </tr>
</table>
<hr>
{% for post in posts %}
<p>
 {{post.author.nickname}} 發(fā)布了: <b>{{post.body}}</b>
</p>
{% endfor %}
{% endblock %}

我們?cè)O(shè)計(jì)Userclass來(lái)返回用戶頭像的亮點(diǎn)在于:如果某一天我們要是覺(jué)得Gravatar網(wǎng)站上的頭像不是我們所想要的頭像的時(shí)候,我們只需要我們只需要重寫一下頭像處理的函數(shù)來(lái)返回我們想要的地址即可(即使有人盜鏈指向我們的服務(wù)器,我們也可以保護(hù)好自己的主機(jī)),這樣一來(lái)只需要修改這么點(diǎn)點(diǎn),所以的模板都還是自動(dòng)正常運(yùn)行。

我們已經(jīng)把用戶頭像部分添加到了用戶資料詳情頁(yè)面的頂部去了,不過(guò)在頁(yè)面底部我們還有顯示文章的沒(méi)做,在文章前面我們也需要顯示一下用戶的頭像。當(dāng) 然在用戶資料頁(yè)面需要對(duì)所以的文章都顯示同樣的頭像,不過(guò)要是把頭像函數(shù)移動(dòng)到主頁(yè)去來(lái)給所以的文章都顯示作者的頭像,那該多好。

我們只需要稍稍修改模板文件即可實(shí)現(xiàn)給文章顯示相應(yīng)作者頭像的功能(項(xiàng)目目錄/templates/user.html):
 

<!-- extend base layout -->
{% extends "base.html" %}
 
{% block content %}
<table>
  <tr valign="top">
    <td><img src="{{user.avatar(128)}}"></td>
    <td><h1>用戶昵稱: {{user.nickname}}</h1></td>
  </tr>
</table>
<hr>
{% for post in posts %}
<table>
  <tr valign="top">
    <td><img src="{{post.author.avatar(50)}}"></td><td><i>{{post.author.nickname}}
   發(fā)布了:</i><br>{{post.body}}</td>
  </tr>
</table>
{% endfor %}
{% endblock %}

這就是到此為止我們的用戶資料頁(yè)面:

微博客用戶詳情頁(yè)面

2015420154059892.png (344×310)


重復(fù)使用子模板

用戶資料頁(yè)面顯示了用戶自己的文章,不過(guò)網(wǎng)站的首頁(yè)需要顯示此刻不同用戶文章。在這里就有兩個(gè)用于顯示 用戶文章的模板文件了。我們可以直接復(fù)制把處理顯示文章的那段代碼然后直接粘貼到新的模板,其實(shí)那并不是最理想的方法,倘若有一天我們需要修改下顯示文章 那塊,我們就需要來(lái)更新所以的那些含有文章顯示代碼的模板文件。


反之,我們將會(huì)去新建一個(gè)子模板文件來(lái)處理文章顯示的功能,之后在需要顯示文章的時(shí)候包含一下這個(gè)文件即可。

開(kāi)始我們還是來(lái)創(chuàng)建一個(gè)子空模板文件,然后把用戶資料頁(yè)面中展示文章的那段代碼復(fù)制過(guò)來(lái)(項(xiàng)目目錄/templates/post.html):
 

<table>
  <tr valign="top">
    <td><img src="{{post.author.avatar(50)}}"></td><td><i>{{post.author.nickname}}
  發(fā)布了:</i><br>{{post.body}}</td>
  </tr>
</table>

然后我們使用Jinja2的包含功能調(diào)用一下該子模板文件(項(xiàng)目目錄/templates/user.html)
 

<!-- extend base layout -->
{% extends "base.html" %}
 
{% block content %}
<table>
  <tr valign="top">
    <td><img src="{{user.avatar(128)}}"></td>
    <td><h1>用戶昵稱: {{user.nickname}}</h1></td>
  </tr>
</table>
<hr>
{% for post in posts %}
  {% include 'post.html' %}
{% endfor %}
{% endblock %}

一旦有了完整的頁(yè)面我們就可以按照上面的方法去調(diào)用下子模板來(lái)顯示文章,不過(guò)現(xiàn)在還不急說(shuō),將在后面章節(jié)的教程中說(shuō)到。


更多相關(guān)個(gè)人信息

盡管到此用戶信息頁(yè)面比較精密了,不過(guò)還是有許多信息沒(méi)有顯示出來(lái)。用戶大多喜歡在網(wǎng)站上顯示自己更多的信息,因此我們就可以讓用戶填寫自己的信息顯示在這里。當(dāng)然我們也可以記錄下用戶每次登陸到本站的的時(shí)間,顯示到他們自己的資料詳情頁(yè)。


為了顯示等多的信息我們就需要更新下數(shù)據(jù)庫(kù)。特別需要在Userclass里面新加字段(項(xiàng)目目錄/models.py):

 
class User(db.Model):
  id = db.Column(db.Integer, primary_key = True)
  nickname = db.Column(db.String(64), unique = True)
  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)

我們每次修改數(shù)據(jù)庫(kù)的時(shí)候就需要生成新的記錄(migration)。需要注意下我們?cè)谔幚頂?shù)據(jù)更新到數(shù)據(jù)庫(kù)的時(shí)候記得創(chuàng)建一個(gè)(migration),現(xiàn)在我們就來(lái)看下最后結(jié)果。我們只需要下面的代碼就可以把新加的兩個(gè)字段更新到數(shù)據(jù)庫(kù)里去了:
 

./db_migrate.py

當(dāng)然相應(yīng)的響應(yīng)腳本是
 

New migration saved as db_repository/versions/003_migration.py
Current database version: 3

現(xiàn)在我們新加的兩個(gè)字段就保存到數(shù)據(jù)庫(kù)了。不過(guò)需要提醒的是在window系統(tǒng)下面調(diào)用此腳本是有點(diǎn)不一樣的。


如果不支持?jǐn)?shù)據(jù)遷移的話你還得手動(dòng)修改數(shù)據(jù)庫(kù),否則你就需要?jiǎng)h除之后重新從頭開(kāi)始創(chuàng)建數(shù)據(jù)。

接下來(lái)我們就需要修改下用戶詳情頁(yè)來(lái)顯示我們剛添加的字段(項(xiàng)目目錄/templates/user.html):

 

<!-- extend base layout -->
{% extends "base.html" %}
 
{% block content %}
<table>
  <tr valign="top">
    <td><img src="{{user.avatar(128)}}"></td>
    <td>
      <h1>用戶昵稱: {{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 %}
    </td>
  </tr>
</table>
<hr>
{% for post in posts %}
  {% include 'post.html' %}
{% endfor %}
{% endblock %}

由于我們需要只有當(dāng)用戶自己填寫了這兩個(gè)字段的時(shí)候才顯示出來(lái),所以我們主要利用Jinja2的判斷條件來(lái)顯示這些字段即可。

對(duì)于這點(diǎn),對(duì)所有的用戶而言,這兩個(gè)字段都是空的,什么都不會(huì)顯示的。
 

最后顯示的字段(last_seen)就特別的好處理。需要注意的是在上面我們已經(jīng)設(shè)置了用于注冊(cè)用戶請(qǐng)求的(flask.g和global, asg.user)接收參數(shù)。也就是需要在這個(gè)最佳段來(lái)記錄用戶的登陸時(shí)間(項(xiàng)目目錄/views.py):
 

from datetime import datetime
# ...
@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()

如果你登陸了之后就會(huì)在資料詳情頁(yè)面顯示最后的登陸時(shí)間,當(dāng)然如果你每刷新一次頁(yè)面的話相應(yīng)的登陸時(shí)間就會(huì)自動(dòng)更新。這是由于當(dāng)瀏覽器沒(méi)刷新一次就會(huì)去請(qǐng)求我們上面設(shè)置的接收參數(shù)并更新數(shù)據(jù)庫(kù)的處理函數(shù)。


在這里我們記錄的是國(guó)際標(biāo)準(zhǔn)時(shí)間UTC時(shí)區(qū)。在之前的章節(jié)中我們也提到了怎么去儲(chǔ)存一個(gè)適合所有時(shí)區(qū)的時(shí)間戳,這就會(huì)在有一個(gè)負(fù)面的錯(cuò)誤信息,因?yàn)樵谒杏脩舻馁Y料頁(yè)面顯示的都是UTC的時(shí)區(qū)的時(shí)間,這個(gè)問(wèn)題我會(huì)在接下來(lái)說(shuō)關(guān)于出來(lái)時(shí)間和日期的章節(jié)中詳細(xì)講解。

想顯示關(guān)于用戶的更多信息,我們得給他們一個(gè)鏈接, 最適合放在用戶資料的編輯頁(yè)面。
 
編輯用戶詳細(xì)資料

創(chuàng)建一個(gè)用戶資料編輯頁(yè)面那真是太簡(jiǎn)單了,我們只需要?jiǎng)?chuàng)建下面的web表單即可(項(xiàng)目目錄/forms.py):
 

from flask.ext.wtf import Form, TextField, BooleanField, TextAreaField
from flask.ext.wtf import Required, Length
 
class EditForm(Form):
  nickname = TextField('nickname', validators = [Required()])
  about_me = TextAreaField('about_me', validators = [Length(min = 0, max = 140)])

視圖模板文件(項(xiàng)目目錄/templates/edit.html):
 

<!-- 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>你的昵稱:</td>
      <td>{{form.nickname(size = 24)}}</td>
    </tr>
    <tr>
      <td>關(guān)于自己:</td>
      <td>{{form.about_me(cols = 32, rows = 4)}}</td>
    </tr>
    <tr>
      <td></td>
      <td><input type="submit" value="保存"></td>
    </tr>
  </table>
</form>
{% endblock %}

最后當(dāng)然就是創(chuàng)建視圖的方法(項(xiàng)目目錄/views.py):
 

from forms import LoginForm, EditForm
 
@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)

方便用戶編輯,我們需要在用戶的個(gè)人資料頁(yè)面添加一個(gè)到此頁(yè)面的鏈接地址(項(xiàng)目目錄/templates/user.html):
 

<!-- extend base layout -->
{% extends "base.html" %}
 
{% block content %}
<table>
  <tr valign="top">
    <td><img src="{{user.avatar(128)}}"></td>
    <td>
      <h1>用戶昵稱: {{user.nickname}}</h1>
      {% if user.about_me %}<p>{{user.about_me}}</p>{% endif %}
      {% if user.last_seen %}<p><i>最后登陸時(shí)間: {{user.last_seen}}</i></p>{% endif %}
      {% if user.id == g.user.id %}<p><a href="{{url_for('edit')}}">修改資料</a></p>{% endif %}
    </td>
  </tr>
</table>
<hr>
{% for post in posts %}
  {% include 'post.html' %}
{% endfor %}
{% endblock %}

不過(guò)你需要判斷的一下,條件就是只有當(dāng)用戶瀏覽自己的個(gè)人資料頁(yè)面的時(shí)候才顯示該鏈接,而不是瀏覽任何人的個(gè)人資料頁(yè)面都顯示出來(lái)。

下面是最新個(gè)人資料頁(yè)面的截圖,包含了我們新加的所以字段,也含有“關(guān)于我”的文字:

2015420154151326.png (356×355)


最后一點(diǎn)留給你自己去研究了

貌似通過(guò)上面的一些列制作,個(gè)人資料頁(yè)面感覺(jué)已經(jīng)很完善了,對(duì)不?仔細(xì)想來(lái),是這樣不過(guò)我們還有一些bug需要修復(fù)下。

不知道你有沒(méi)有發(fā)現(xiàn)?

提醒下你吧,在之前的章節(jié)中我們?yōu)g覽用戶登陸的時(shí)候其實(shí)我就已經(jīng)提到過(guò)這個(gè)bug的。現(xiàn)在我們?cè)谏厦娴拇a片中也犯了同樣錯(cuò)。

仔細(xì)想想吧,如果你知道是什么問(wèn)題的話可以在下面評(píng)論中說(shuō)下。我將會(huì)在下一個(gè)章節(jié)詳細(xì)地說(shuō)此bug,并說(shuō)怎么去修正它。


跟以前一樣我會(huì)把今天說(shuō)講到的代碼打包提供下載

下載地址 microblog-0.6.zip.

相關(guān)文章

  • Python一行代碼實(shí)現(xiàn)生成和讀取二維碼

    Python一行代碼實(shí)現(xiàn)生成和讀取二維碼

    二維碼被稱為快速響應(yīng)碼,可能看起來(lái)很簡(jiǎn)單,但它們能夠存儲(chǔ)大量數(shù)據(jù)。無(wú)論掃描二維碼時(shí)包含多少數(shù)據(jù),用戶都可以立即訪問(wèn)信息。本文將用一行Python代碼實(shí)現(xiàn)二維碼的讀取與生成,需要的可以參考一下
    2022-02-02
  • Django用戶認(rèn)證系統(tǒng)如何實(shí)現(xiàn)自定義

    Django用戶認(rèn)證系統(tǒng)如何實(shí)現(xiàn)自定義

    這篇文章主要介紹了Django用戶認(rèn)證系統(tǒng)如何實(shí)現(xiàn)自定義,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-11-11
  • python中numpy.empty()函數(shù)實(shí)例講解

    python中numpy.empty()函數(shù)實(shí)例講解

    在本篇文章里小編給大家分享的是一篇關(guān)于python中numpy.empty()函數(shù)實(shí)例講解內(nèi)容,對(duì)此有興趣的朋友們可以學(xué)習(xí)下。
    2021-02-02
  • 4個(gè)的Python自動(dòng)化腳本分享

    4個(gè)的Python自動(dòng)化腳本分享

    這篇文章主要給大家分享了4個(gè)的Python自動(dòng)化腳本,自動(dòng)化腳本無(wú)需手動(dòng)一次又一次地完成這些任務(wù),非常方便,下面我能就一起進(jìn)入文章來(lái)來(lái)了解實(shí)現(xiàn)吧,希望對(duì)你有所幫助
    2021-12-12
  • Python程序設(shè)計(jì)入門(4)模塊和包

    Python程序設(shè)計(jì)入門(4)模塊和包

    Python語(yǔ)言功能非常強(qiáng)大,除了類之外,還有模塊和包的概念,這有點(diǎn)像perl,本文主要介紹了包和模塊,需要的朋友可以參考下
    2014-06-06
  • python實(shí)現(xiàn)簡(jiǎn)單銀行管理系統(tǒng)

    python實(shí)現(xiàn)簡(jiǎn)單銀行管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)簡(jiǎn)單銀行管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-10-10
  • Python中類型關(guān)系和繼承關(guān)系實(shí)例詳解

    Python中類型關(guān)系和繼承關(guān)系實(shí)例詳解

    這篇文章主要介紹了Python中類型關(guān)系和繼承關(guān)系,較為詳細(xì)的分析了Python中類型關(guān)系和繼承關(guān)系的原理與使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-05-05
  • python基礎(chǔ)教程項(xiàng)目五之虛擬茶話會(huì)

    python基礎(chǔ)教程項(xiàng)目五之虛擬茶話會(huì)

    這篇文章主要為大家詳細(xì)介紹了python基礎(chǔ)教程項(xiàng)目五之虛擬茶話會(huì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-04-04
  • 對(duì)python列表里的字典元素去重方法詳解

    對(duì)python列表里的字典元素去重方法詳解

    今天小編就為大家分享一篇對(duì)python列表里的字典元素去重方法詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-01-01
  • OpenCV實(shí)戰(zhàn)之實(shí)現(xiàn)手勢(shì)虛擬縮放效果

    OpenCV實(shí)戰(zhàn)之實(shí)現(xiàn)手勢(shì)虛擬縮放效果

    本篇將會(huì)以HandTrackingModule為模塊,實(shí)現(xiàn)通過(guò)手勢(shì)對(duì)本人的博客海報(bào)進(jìn)行縮放。文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,需要的可以參考一下
    2022-11-11

最新評(píng)論