做網(wǎng)站怎么切圖網(wǎng)站seo收錄工具
1
.實現(xiàn)投票功能,2
.創(chuàng)建文章數(shù)據(jù),3
.對文章進行排序。
實現(xiàn)投票功能
實現(xiàn)投票功能,要注重文章的時效性與投票的公平性,所以需要給投票功能加上一些約束條件:
- 文章發(fā)布滿一個星期后,不再允許用戶對該文章投票
- 一個用戶對一篇文章只能投一次票
所以我們需要使用:
- 一個有序集合?
time
,存儲文章的發(fā)布時間 - 一個集合?
voted:*
,存儲已投票用戶名單- 其中?
*
?是被投票文章的?ID
- 其中?
- 一個有序集合?
score
,存儲文章的得票數(shù)
ONE_WEEK_IN_SECONDS = 7 * 24 * 60 * 60
def article_vote(r, user_id, article_id):
# 使用 time.time() 獲取當前時間
# 減去一周的秒數(shù),從而獲取一周前的Unix時間
cutoff = time.time() - ONE_WEEK_IN_SECONDS
if r.zscore('time', article_id) < cutoff:
return
if r.sadd('voted:' + article_id, user_id):
r.zincrby('score', article_id, 1)
當用戶嘗試投票時,使用 ZSCORE
命令讀取 time
有序集合,得到這篇文章的發(fā)布時間,再判斷文章的發(fā)布時間是否超過一周。ZSCORE
命令的語法如下:
r.zscore(key, member)
key
?:是有序集合的鍵名member
?:是有序集合中的某個成員
若未超過,則使用 SADD
命令嘗試將用戶追加到這篇文章的已投票用戶名單中,如果添加成功,則說明該用戶未投過票。SADD
命令的語法是:
r.sadd(key, member)
key
?:是集合的鍵名member
?:是要添加進集合的元素
由于集合中的元素是唯一的,所以sadd
函數(shù)會根據(jù)member
是否存在在集合中做出不同返回:
- 若該元素不存在在集合中,返回?
True
- 若該元素已存在在集合中,返回?
False
所以返回為 True
時使用 ZINCRBY
命令來為文章的投票數(shù)加 1
。zincrby
函數(shù)語法如下:
r.zincrby(key, member, increment)
key
?:是有序集合的鍵名member
?:是有序集合中要增加分值的成員increment
?:是要增加的分值
創(chuàng)建文章數(shù)據(jù)
現(xiàn)在系統(tǒng)中還缺少文章數(shù)據(jù),所以我們要提供一個創(chuàng)建文章的函數(shù),并把文章數(shù)據(jù)存儲到 Redis
中。創(chuàng)建文章的步驟如下:
- 創(chuàng)建新的文章?
ID
- 將文章作者加入到這篇文章的已投票用戶名單中
- 存儲文章詳細信息到?
Redis?
中 - 將文章的發(fā)布時間和初始投票數(shù)加入到?
time
?和?score
?兩個有序集合中
def post_article(r, user, title, link):
# 創(chuàng)建新的文章ID,使用一個整數(shù)計數(shù)器對 article 鍵執(zhí)行自增
# 如果該鍵不存在,article 的值會先被初始化為 0
# 然后再執(zhí)行自增命令
article_id = str(r.incr('article'))
voted = 'voted:' + article_id
r.sadd(voted, user)
r.expire(voted, ONE_WEEK_IN_SECONDS)
now = time.time()
article = 'article:' + article_id
r.hmset(article, {
'title': title,
'link': link,
'poster': user,
})
r.zadd('score', article_id, 1)
r.zadd('time', article_id, now)
return article_id
將文章作者加入已投票用戶名單中和之前一樣,這里不再贅述,但在這里我們需要為這個已投票用戶名單設(shè)置一個過期時間,讓它在一周后(到期后)自動刪除,減少 Redis
的內(nèi)存消耗。為鍵設(shè)置過期時間的命令是:
r.expire(key, seconds)
key
?:要設(shè)置過期時間的鍵名seconds
?:過期時間的長度(單位:秒)
這里我們要設(shè)置的時間是一周,所以我們可以使用上面定義好的全局變量 ONE_WEEK_IN_SECONDS
。
接下來要存儲文章詳細信息了,前面介紹過 hset
可以執(zhí)行單個字段(域)的設(shè)置,這里我們使用 hmset
一次性設(shè)置多個字段(域),其語法如下:
r.hmset(key, {field: value, [field: value ...]})
我們可以使用 Python
的散列來一次性存儲多個字段(域)到 Redis
,只需要將整個散列當作 key
對應(yīng)的值通過 hmset
函數(shù)設(shè)置進去就行。
最后,將初始投票數(shù)和創(chuàng)建時間設(shè)置到 score
和 time
中都可以通過 ZADD
命令來實現(xiàn):
r.zadd(key, member, score)
key
?:有序集合的鍵名member
?:要加入有序集合的成員score
?:該成員的分值
這里需要注意的是,因為該篇文章的作者已經(jīng)被加入到該文章已投票用戶名單中,為了保持數(shù)據(jù)一致性,我們需要將文章的初始投票數(shù)設(shè)為 1
。
對文章進行排序
實現(xiàn)了文章投票和創(chuàng)建文章功能,接下來我們就需要將評分最高的文章和最新發(fā)布的文章從 Redis
中取出了。
-
首先我們要根據(jù)排序方式的不同:
- 按評分排序,則從?
score
?有序集合中取出一定量的文章?ID
(score
有序集合存放文章ID
和對應(yīng)的投票數(shù)) - 按時間排序,則從?
time
?有序集合中取出一定量的文章?ID
(time
有序集合存放文章ID
和對應(yīng)的發(fā)布時間)
- 按評分排序,則從?
-
構(gòu)成一個有序文章信息列表,每個元素都:
- 使用?
HGETALL
?命令,取出每篇文章的全部信息
- 使用?
def get_articles(r, start, end, order='score'):
ids = r.zrevrange(order, start, end)
articles = []
for id in ids:
article_data = r.hgetall(id)
article_data['id'] = id
articles.append(article_data)
return articles
這里因為需要對有序集合進行排序,所以我們在取出文章 ID
時需要使用到 ZREVRANGE
命令,以分值從大到小的排序方式取出文章 ID
。ZREVRANGE
命令的語法是:
r.zrevrange(key, start, stop)
key
?:有序集合的鍵名start
?:開始的數(shù)組下標stop
?:結(jié)束的數(shù)組下標
得到多個文章 ID
后,我們還需要根據(jù)每一個文章 ID
獲取文章的全部信息,這時就需要使用到 HGETALL
命令,它的語法如下:
r.hgetall(key)
key
?:哈希的鍵名
我們?nèi)〕鑫恼碌娜啃畔⒑?#xff0c;還為文章信息添加了一個字段 id
。這是因為文章 ID
在 Redis
中是作為鍵名存儲的,不在值當中,所以我們需要附加這個字段到文章信息中。
實現(xiàn)這些方法后,我們大體實現(xiàn)了一個文章投票的后端處理邏輯,能夠為文章投票并能根據(jù)投票結(jié)果改變文章的排序情況。
編程要求
根據(jù)提示,在右側(cè)Begin-End
區(qū)域補充代碼,完成簡化版文章投票網(wǎng)站的后端處理邏輯:
-
在
article_vote()
函數(shù)中:- 該方法作用是:對文章投票
- 參數(shù)說明:
r
:Redis 客戶端
-
user_id
:投票用戶 -
article_id
:被投票文章- 已提供一周前?
Unix
?時間戳,存放在變量?cutoff
- 當滿足以下條件時,為文章投一票:
- 該文章發(fā)布不超過一周
- 已提供一周前?
-
該用戶沒有為該文章投過票
-
在
post_article()
函數(shù)中:- 該方法作用是:創(chuàng)建文章
- 參數(shù)說明:
r
:Redis 客戶端
-
user
:發(fā)布用戶 -
title
:文章標題 -
link
:文章鏈接- 已提供:
article_id
,新文章?ID
- 已提供:
-
voted
,新文章已投票用戶名單存儲鍵名 -
article
,新文章詳細信息存儲鍵名 -
now
,文章創(chuàng)建時間- 按照?
ID
?遞增的順序依次創(chuàng)建文章 - 保證發(fā)布文章的用戶不能給自己的文章投票
- 文章在發(fā)布一周后刪除已投票用戶名單
- 存儲文章詳細信息到?
Redis?
中,包括字段:- 文章標題
- 按照?
-
文章鏈接
-
發(fā)布用戶
- 存儲文章的發(fā)布時間和初始投票數(shù)
- 初始投票數(shù)為?
1
- 初始投票數(shù)為?
- 存儲文章的發(fā)布時間和初始投票數(shù)
-
在
get_articles()
函數(shù)中:- 該方法作用是:對文章進行排序
- 參數(shù)說明:
r
:Redis 客戶端start
:從排序為?start
?的文章開始獲取
-
end
:到排序為end
的文章結(jié)束獲取 -
order
:排序方式,分為兩種:time
:按時間排序score
:按投票數(shù)排序
-
已提供文章信息空列表,
articles
-
實現(xiàn)按時間/投票數(shù)排序
-
將排序后的文章及其全部信息組成一個列表:
- 按照不同排序規(guī)則取出排序在參數(shù)提供的區(qū)間范圍內(nèi)的文章
- 及每篇文章的全部信息,包括文章?
ID
#!/usr/bin/env python #-*- coding:utf-8 -*- import time ONE_WEEK_IN_SECONDS = 7 * 24 * 60 * 60 def article_vote(r, user_id, article_id):cutoff = time.time() - ONE_WEEK_IN_SECONDS# 請在下面完成要求的功能#********* Begin *********#if r.zscore('time', article_id) < cutoff:returnif r.sadd('voted:' + article_id, user_id):r.zincrby('score', article_id, 1)#********* End *********# def post_article(r, user, title, link):article_id = str(r.incr('article'))voted = 'voted:' + article_idnow = time.time()article = 'article:' + article_id# 請在下面完成要求的功能#********* Begin *********#r.sadd(voted, user)r.expire(voted, ONE_WEEK_IN_SECONDS)r.hmset(article, {'title': title,'link': link,'poster': user,})r.zadd('score', article_id, 1)r.zadd('time', article_id, now)#********* End *********#return article_id def get_articles(r, start, end, order='score'):articles = []# 請在下面完成要求的功能#********* Begin *********#ids = r.zrevrange(order, start, end)for id in ids:article_data = r.hgetall(id)article_data['id'] = idarticles.append(article_data)#********* End *********#return articles