08-Follower
这章将告诉你如何实现类似于Twitter和其他社交网络的“粉丝”功能。
在本章中,我将更多地使用应用的数据库。 我希望应用的用户能够轻松便捷地关注其他用户。
本章的GitHub链接为: Source, Diff, Zip
完善用户模型
首先我们列下要实现的用户操作:
关注 - Follow
取消关注 - UnFollow
关注自己 - FollowSelf
follower数量 - FollowersCount
following数量 - FollowingCount
关注的Posts - FollowingPosts 这个将被用在页面美化那章中的登陆后的IndexView显示
判断是否被关注 - IsFollowedByUser
(*)创建Post - CreatePost 这个是我们为了方便创建数据加入的,和粉丝操作关系不大
Tip: 这里 Followers 可以通过 Gorm 的
Association("Followers")来实现, Following 好像不支持(不确定,看了几遍文档没有找到),不过这里我们一顿骚操作,自己来实现一下嘛
model/user.go
...
// Follow func
// follow someone usr_id other.id follow_id u.id
func (u *User) Follow(username string) error {
other, err := GetUserByUsername(username)
if err != nil {
return err
}
return db.Model(other).Association("Followers").Append(u).Error
}
// Unfollow func
func (u *User) Unfollow(username string) error {
other, err := GetUserByUsername(username)
if err != nil {
return err
}
return db.Model(other).Association("Followers").Delete(u).Error
}
// FollowSelf func
func (u *User) FollowSelf() error {
return db.Model(u).Association("Followers").Append(u).Error
}
// FollowersCount func
func (u *User) FollowersCount() int {
return db.Model(u).Association("Followers").Count()
}
// FollowingIDs func
func (u *User) FollowingIDs() []int {
var ids []int
rows, err := db.Table("follower").Where("follower_id = ?", u.ID).Select("user_id, follower_id").Rows()
if err != nil {
log.Println("Counting Following error:", err)
return ids
}
defer rows.Close()
for rows.Next() {
var id, followerID int
rows.Scan(&id, &followerID)
ids = append(ids, id)
}
return ids
}
// FollowingCount func
func (u *User) FollowingCount() int {
ids := u.FollowingIDs()
return len(ids)
}
// FollowingPosts func
func (u *User) FollowingPosts() (*[]Post, error) {
var posts []Post
ids := u.FollowingIDs()
if err := db.Preload("User").Order("timestamp desc").Where("user_id in (?)", ids).Find(&posts).Error; err != nil {
return nil, err
}
return &posts, nil
}
// IsFollowedByUser func
func (u *User) IsFollowedByUser(username string) bool {
user, _ := GetUserByUsername(username)
ids := user.FollowingIDs()
for _, id := range ids {
if u.ID == id {
return true
}
}
return false
}
// CreatePost func
func (u *User) CreatePost(body string) error {
post := Post{Body: body, UserID: u.ID}
return db.Create(&post).Error
}
...然后在 AddUser 的时候加入 FollowSelf, 即自己关注自己,方便在显示 Profile 页的时候,展示 FollowingPosts 将自己的 Post 也列进去
model/user.go
由于我们一开始的建立用户,没有加入 Follower 功能,我们重新初始化一遍数据
cmd/init_db\main.go
执行
然后查看 follower 表,里面就有数据了

说明: 如上图 user_id 表示用户, follower_id 表示关注者, bonfy(id:1) 关注者 只有自己, 而 rene(id:2) 关注者 有两位, 这也是 u1.Follow(u2.Username) 的执行结果
本小节 Diff
完善页面显示
增加 Follow and Unfollow 操作
controller/home.go
Follow 和 Unfollow之后通过 Redirect 回到原来的页面
完善Profile页面
vm/profile.go
templates/content/profile.html
运行

说明: 这个是通过 rene 登陆之后访问
http://127.0.0.1:8888/user/bonfy查看 bonfy 的profile, 由于 rene 没有 follow bonfy,可以点击Follow按钮,实现Follow操作本小节 Diff
Links
下一节: 09-Pagination
Last updated