您现在的位置是:首页 > 学无止境 > go 网站首页学无止境

beego搭建博客的admin管理(一):用户管理

  • summer
  • go
  • 2019年3月18日 19:47
  • 410已阅读

0、前言


最近在学习beego,发现了一个问题:beego框架作为golang web开发的几大框架之一,但却没有一个类似Django Admin的后台管理模块。于是就想着可以自己使用beego来搭建一个博客的后台Admin管理系统,同时也可以通过做这样的小项目来加深自己对golang和beego的理解、使用。


1、框架使用


  • 前端:这里使用的是x-admin v2.0的后台模板
  • 后台:毫无疑问使用的是beego框架
  • 前后端通信使用ajax方式

2、models对象


根据我们博客的设计,我们需要创建以下几个model,结构如下所示,每一个文件对应该model的数据库等操作:

models/
├── base.go
├── maincategory.go
├── object.go
├── passages.go
├── subcategory.go
├── tags.go
└── user.go

在本篇博客中,我们暂且先完成user相关的部分。下面是我们设计的user结构

type User struct {
    // id
    Id int `json:"id" form:"-"`
    // 昵称
    Nickname string `orm:"size(32)" json:"nickname" form:"nickname"`
    // 密码
    Password string `orm:"size(64);" json:"password" form:"password"`
    // 邮箱
    Username string `orm:"size(128);unique;" json:"username" form:"username"`
    // 性别
    Sex bool `orm:"default(0);" json:"sex" form:"sex"`
    // 状态
    Status bool `orm:"default(0);" json:"status" form:"status"`
    // 是否是管理员
    IsAdmin bool `orm:"default(0);" json:"is_admin" form:"is_admin"`
    // 加入时间
    JoinTime time.Time `orm:"auto_now_add;type(datetime);" json:"join_time" form:"-"`
    // 是否停用
    Del bool `orm:"default(0);" json:"del" form:"del"`
}

对于User,我们实现了以下方法:新增、更新、删除、查询四个结构

如下所示:

// 保存新user
func (u *User) Save() (int64, error) {
    u.Password = Md5([]byte(u.Password))
    return orm.NewOrm().Insert(u)
}

// 更新数据
func (u *User) Update(fields ...string) error{
    user, _ := GetUserById(u.Id)
    if user.Password != u.Password{
        u.Password = Md5([]byte(u.Password))
    }

    if _, err := orm.NewOrm().Update(u, fields...); err != nil {
        return err
    }
    return nil
}

// 删除数据
func (u *User) Delete() error{
    if _, err := orm.NewOrm().Delete(u); err != nil{
        return err
    }
    return nil
}

// 查询数据
func (u *User) Query() orm.QuerySeter {
    return orm.NewOrm().QueryTable(u)
}

通过这几个方法,我们基本可以实现对User的各种操作。

利用这几种方法,我们实现了GetUserById()GetUserByName()还有UserList()三个函数


3、controller设计


首先,我们看一下controllers/的文件分布:

controllers/
├── admin.go
├── common.go
├── mainCates.go
├── passage.go
├── subCates.go
└── user.go

在这里,我们也只关注admin.gocommon.gouser.go三个文件。首先我们来看一下common.go里面的部分内容:

type BaseController struct {
    beego.Controller
}

func (b *BaseController) ajaxMsg(code int, data interface{}, msg interface{}, other map[string]interface{}) {
    out := make(map[string]interface{})
    out["code"] = code
    out["data"] = data
    out["message"] = msg
    if other != nil{
        for k, v := range other{
            out[k] = v
        }
    }
    b.Data["json"] = out
    b.ServeJSON()
    b.StopRun()
}

func (b *BaseController) Authentication() (string, bool) {
    admin := b.GetSession("admin")
    username := b.GetSession("username")
    if admin != nil && username != nil{
        if admin.(string) == "admin"{
            return username.(string),true
        } else {
            return "", false
        }
    }
    return "", false
}

// 登录
func Login(username, password string) (bool, error){
    user := models.User{
        Username: username,
    }
    if err := orm.NewOrm().Read(&user,"username"); err == nil {
        if user.Password == models.Md5([]byte(password)){
            return user.IsAdmin, nil
        } else {
            return false, PasswordError
        }
    } else {
        return false, UserDoesNotExistError
    }
}

我们定义了一个BaseController作为一个基本的Controller,然后给其添加了两个方法ajaxMsgAuthentication,分别用于与前端通信session认证。同时我们登录函数也放在了该文件中。 再来看一下admin.go,这里面主要是在渲染前端页面,而并没有过多的逻辑函数,这里我们只列出部分函数作为参考:

type AdminController struct {
    BaseController
}

func (a *AdminController) Index() {
    username, admin := a.Authentication()
    if !admin {
        a.Abort("403")
    }
    a.Data["username"] = username
    a.TplName = "index.html"
}

func (a *AdminController) Welcome() {
    username, admin := a.Authentication()
    if !admin {
        a.Abort("403")
    }
    a.Data["username"] = username
    a.Data["time"] = time.Now()
    a.TplName = "welcome.html"
}

最后看一下user.go,首先看一下登录函数:

func (u *UserController) Login() {
    if u.Ctx.Input.IsGet(){
        u.TplName = "login.html"
    } else {
        username := u.GetString("username")
        password := u.GetString("password")
        if _, err := Login(username, password); err == nil {
            u.SetSession("username", username)
            u.ajaxMsg(0, "", "success to login", nil)
        } else if err == PasswordError {
            u.ajaxMsg(20003, "", "password is wrong", nil)
        } else {
            u.ajaxMsg(20004, "", "the user does not exist", nil)
        }
    }
}

这是我们在routes/router.go中注册一下我们的路由,便可以查看到效果了

    beego.Router("/admin/", &controllers.UserController{}, "get,post:Login")

运行bee run,打开127.0.0.1:8080/admin便可看到效果了。具体如下 当然,此时需要我们在数据库自己添加一个admin用户才可以登录,或者写一个接口函数进行注册(在本文中我们默认有了admin用户)。 接下来是关于User操作的controller函数,具体如下:

func (u *UserController) Create() {
    user := models.User{}
    if err1 := u.ParseForm(&user); err1 != nil{
        u.ajaxMsg(70001, nil, err1.Error(), nil)
    }
    // 检查用户名是否已经存在
    _, err := models.GetUserByName(user.Username)
    if err == nil{
        u.ajaxMsg(20001, nil, "The username exists.", nil)
    }

    if _, err := user.Save(); err != nil{
        u.ajaxMsg(80001, nil, err.Error(), nil)
    }
    u.ajaxMsg(0, user, "success to save the user.", nil)
}

func (u *UserController) Put() {
    admin, err := u.Authentication()
    if err != nil || admin.IsAdmin == false {
        u.Abort("403")
    }

    uid, err := u.GetInt(":uid")
    if err != nil {
        u.ajaxMsg(70001, nil, err.Error(), nil)
    }
    user, err := models.GetUserById(uid)
    if err != nil{
        u.ajaxMsg(20004, nil, "not found the user.", nil)
    }

    if err1 := u.ParseForm(user); err1 != nil{
        u.ajaxMsg(70001, nil, err1.Error(), nil)
    }

    user.Update()
    u.ajaxMsg(0, user, "success to update the user.", nil)
}

func (u *UserController) Delete() {
    admin, err := u.Authentication()
    if err != nil || admin.IsAdmin == false {
        u.Abort("403")
    }

    uid, err := u.GetInt(":uid")
    if err != nil {
        u.ajaxMsg(70001, nil, err.Error(), nil)
    }
    user, err := models.GetUserById(uid)
    if err != nil{
        u.ajaxMsg(20004, nil, "not found the user.", nil)
    }
    user.Delete()
    u.ajaxMsg(0, user, "success to delete the user.", nil)
}

// 批量处理
func (u *UserController) OpAll() {
    admin, err := u.Authentication()
    if err != nil || admin.IsAdmin == false {
        u.Abort("403")
    }
    ids := strings.Split(u.GetString("ids"), ";")
    del, _ := u.GetInt("del")
    for _, v := range ids {
        uid, _ := strconv.Atoi(v)
        user, err := models.GetUserById(uid)
        if err != nil{
            u.ajaxMsg(20004, nil, "not found the user.", nil)
        }
        if del == 1 {
            user.Del = true
        } else {
            user.Del = false
        }
        user.Update()
    }

    u.ajaxMsg(0, nil, "success to operate the users.", nil)
}

同样在routes/touter.go中注册路由

beego.Router("/admin/member/", &controllers.UserController{}, "post:Create;put:OpAll")
beego.Router("/admin/member/:uid", &controllers.UserController{}, "put:Put;delete:Delete")
// 登出
beego.Router("/admin/logout/", &controllers.UserController{}, "*:Logout")
beego.AutoRouter(&controllers.AdminController{})

bee会自动更新并重启服务,重新登录admin,便可以看到User相关操作



4、其他


另外,我们还需要实现一个搜索的功能,具体需求如下图。我们需要通过用户的创建时间和用户名来模糊搜索符合条件的用户。 在这里,我们添加一个Search()函数,函数原型为func Search(start, end, username string, del bool) ([]*models.User, int)。在Search()中,我们首先对username进行模糊搜索,然后再根据是否传入startend来判断是否需要进行下一步的操作

func Search(start, end, username string, del bool) ([]\*models.User, int){
    var users []*models.User
    var query orm.QuerySeter
    query = new(models.User).Query().Filter("Username__icontains", username).Filter("Del", del)

    if start != "" {
        query = query.Filter("JoinTime__gte", start)
    }

    if end != "" {
        query = query.Filter("JoinTime__lte", end)
    }

    query.All(&users)
    total := len(users)
    return users, total
}

然后就可以在之前的MemberList()中加入一个判断,判断当前请求是否是来自于搜索,再根据判断结果返回相应的内容。

if q := a.GetString("q"); q == "search" {
        start := a.GetString("start", "")
        end  := a.GetString("end", "")
        username := a.GetString("username", "")
        userList, total := Search(start, end, username, false)
        a.Data["userlist"] = userList
        a.Data["total"] = total
    } else {
        userList, total := models.UserList(true)
        a.Data["userlist"] = userList
        a.Data["total"] = total
    }

github项目地址:beego-admin(更新中)


版权声明:本文为博主原创文章,转载时请注明来源。https://blog.thinker.ink/passage/20/

 

文章评论

Top