<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Go語言實戰 - revel框架教程之用戶注冊

      用戶注冊、登錄和注銷是任何一個網站都必然會有的功能,可以說,這是重新造輪子做多的領域,每個做網站的人應該都做過很多遍。見微知著,從這么一個小功能其實就可以看到所使用的web框架中的大部分東西。

      今天就讓我們用這個基本模塊來看看revel吧。

      先整理一下我們選用的技術框架和組件:

      web框架:revel 

      數據庫:mongodb

      數據庫driver:mgo

      工欲善其事,必先利其器,這里著重推薦一個mongodb的GUI客戶端 - mongovue,可以說,如果沒有這個工具,在開發的過程中我們會痛苦許多許多。

      這里假設你已經有了對Go語言最基本的知識,已經配置好GOROOT和GOPATH。

      首先,在GOPATH下面運行下面的命令安裝revel,并且把revel的工具編譯出來。

      go get github.com/robfig/revel

      go build –o bin/revel.exe github.com/robfig/revel/revel

      完成之后去GOPATH\bin下面看看是否已經編譯出來了revel.exe。為了方便使用,我把GOPATH\bin添加到了環境變量PATH中。

      到你希望存放工程文件的地方運行

      revel new myapp

      整個工程的框架就建立好了,看下面的文件夾結構就可以看出,revel是一個MVC框架。

      image

      此時整個工程就可以運行了,運行下面的命令行啟動站點。

      revel run myapp

      打開瀏覽器 http://127.0.0.1:9000,就可以看到下面的結果

      image

      內部的細節暫時不多說,來吧,先讓用戶可以注冊。注意,在整個開發過程中大部分時候不需要重新啟動revel。

      1. 準備Model

       

      按照MVC的開發節奏,我們先準備model。在app目錄下新建一個models目錄,然后在里面新建entity.go(這個文件的命名大家可自便),打開entity.go加入User的實體定義。

      type User struct {
        Email    string
        Nickname string
        Password []byte
      }

      type MockUser struct {
        Email           string
        Nickname        string
        Password        string
        ConfirmPassword string
      }

      為什么定義MockUser呢?原因后面會提到。

      現在寫dal(數據訪問層),在app\models目錄下新建dal.go。dal的寫法其實可以用revel的插件機制,這里為了避免一下子引入太多概念,先用這種簡單的方式。

      package models

      import (
        "github.com/robfig/revel"
        "labix.org/v2/mgo"
      )

      const (
        DbName                         = "myapp"
        UserCollection                 = "user"
      )

      type Dal struct {
        session *mgo.Session
      }

      func NewDal() (*Dal, error) {
        revel.Config.SetSection("db")
        ip, found := revel.Config.String("ip")
        if !found {
          revel.ERROR.Fatal("Cannot load database ip from app.conf")
        }

        session, err := mgo.Dial(ip)
        if err != nil {
          return nil, err
        }

        return &Dal{session}, nil
      }

      func (d *Dal) Close() {
        d.session.Close()
      }

      revel已經提供了配置系統,打開conf\app.conf,添加下面內容

      [db]
      ip = 127.0.0.1

      現在實現注冊需要用到的方法,在app\models目錄下添加文件dal_account.go,代碼如下。

      func (d *Dal) RegisterUser(mu *MockUser) error {
        uc := d.session.DB(DbName).C(UserCollection)

        //先檢查email和nickname是否已經被使用
        i, _ := uc.Find(M{"nickname": mu.Nickname}).Count()
        if i != 0 {
          return errors.New("用戶昵稱已經被使用")
        }

        i, _ = uc.Find(M{"email": mu.Email}).Count()
        if i != 0 {
          return errors.New("郵件地址已經被使用")
        }

        var u User
        u.Email = mu.Email
        u.Nickname = mu.Nickname
        u.Password, _ = bcrypt.GenerateFromPassword([]byte(mu.Password), bcrypt.DefaultCost)

        err := uc.Insert(u)

        return err
      }

      看出來MockUser存在的意義了嗎?用戶在頁面上填寫的是明文的密碼,這可不能直接存入數據庫,需要先加密,這里用到了"code.google.com/p/go.crypto/bcrypt"這個庫。

      2. 準備Controller

      準備controller,在app\controllers新建一個文件account.go,在里面實現Account控制器,代碼如下。

      package controllers

      import (
        "github.com/robfig/revel"
        "myapp/app/models"
      )

      type Account struct {
        *revel.Controller
      }

      func (c *Account) Register() revel.Result {
        return c.Render()
      }

      func (c *Account) PostRegister(user *models.MockUser) revel.Result {
        return c.Render()
      }

      3. 添加Route

      準備route,打開conf\routes,添加Register的URL映射。

      # Routes
      # This file defines all application routes (Higher priority routes first)
      # ~~~~

      module:testrunner

      GET     /                                          App.Index

      GET     /register                                Account.Register

      POST   /register                                Account.PostRegister

      # Ignore favicon requests
      GET     /favicon.ico                           404

      # Map static resources from the /app/public folder to the /public path
      GET     /public/*filepath                     Static.Serve("public")

      # Catch all
      *       /:controller/:action                   :controller.:action

      假定大家都知道Restful是啥意思,這里就是把兩個url映射到了Controller的兩個Action。

      可以看到,這里定義了所有的URL到Controller之間的映射,很方便。這個文件在運行前會被revel轉換成app\routes\routes.go文件參與編譯。后面在講到ReverseRedirect的時候需要用到這個文件里的內容。

      4. 準備View

      準備view,在app\views下面新建文件Register.html,關鍵內容如下

      <form action="{{url "Account.PostRegister"}}" method="POST">
          {{with $field := field "user.Email" .}}
          <div class="control-group {{$field.ErrorClass}}">
            <label class="control-label" for="{{$field.Id}}">電子郵件</label>
            <div class="controls">
              <input type="email" id="{{$field.Id}}" name="{{$field.Name}}" value="{{$field.Flash}}" required>
              {{if $field.Error}}
              <span class="help-inline">{{$field.Error}}</span>
              {{end}}
            </div>
          </div>
          {{end}}
          …

      一點一點解釋一下上面藍色部分關鍵字的含義。

      url是revel提供的一個template function,可以很方便的把Controller的Action變成與之相對的url,它的運作原理實際上就是去剛才定義好的routes映射里面查找。

      field是revel提供的一個template function,專門方便生成form,還記得PostRegister方法的簽名嗎?

      func (c *Account) PostRegister(user *models.MockUser) revel.Result

      它接受一個名為user的*models.User類型的參數,所以,使用{{with $field := field “user.Email”}}就可以通知revel將form的參數封裝到user結構中再傳遞給PostRegister。

      我們都知道用戶注冊的時候填寫的值是需要做有效性檢驗的,當用戶填寫的值不符合標準時需要出現錯誤提示,通常來說會是下面這樣

      image

      $field.ErrorClass的作用就是當這個參數出現錯誤的時候可以方便的通過添加class的方式在頁面上顯示錯誤狀態。ErrorClass的值可以通過下面的代碼修改。

      revel.ERROR_CLASS = "error"

      $field.Id和$field.Name就不解釋了,大家待會兒打開瀏覽器中看看生成的源代碼就明白了。

      $field.Flash這里就需要解釋一下Flash的概念了。

      Flash是一個字典,適用于在兩個Request中間傳遞數據,數據存儲在cookie中。

      大家都知道,HTTP協議本身是無狀態的,所以,考慮一下這個用例,用戶在注冊的時候輸入了一個無效的email地址,點擊注冊之后頁面刷新了一下,“電子郵件”下面出現一行紅字“你輸入的Email地址無效”,此刻文本框里面需要出現上次用戶輸入的值。那么,$field.Flash就是在Flash里去找以$field.Name為Key的值。

      $field.Error就是在Flash里找以$field.Name_error為Key的值,也就是上圖中紅色的“密碼必須大于等于6位”這個錯誤信息。

      好了,現在大家就按照這個節奏在view中添加“昵稱”,“密碼”和“確認密碼”吧。

      添加完成之后就去訪問http://127.0.0.1/register看看吧。是不是這樣呢?

      image

      revel會通過Controller.Action的名稱去查找同名的view文件,例如,Register方法對應的就是Register.html。這里需要注意的一點是,revel是通過反射去查找Controller.Render方法的調用者,而且只向上查找一層。

      例如,下面這段代碼是不能工作的。

      func (c *Account) someMethod() revel.Result {
        ...
        return c.Render()
      }

      func (c *Account) Register() revel.Result {
        return c.someMethod()
      }

       

      5. 實現Controller

      現在讓我們為PostRegister添加處理注冊的邏輯。

      首先,驗證參數的有效性。

      func (c *Account) PostRegister(user *models.MockUser) revel.Result {
        c.Validation.Required(user)
        c.Validation.Email(user.Email)
        c.Validation.Required(user.Nickname)
        c.Validation.Required(user.Password)
        c.Validation.Required(user.ConfirmPassword == user.Password)

        if c.Validation.HasErrors() {
          c.FlashParams()
          return c.Redirect((*Account).Register)
        }

        return c.Render()
      }

      revel提供了挺好用的Validation機制,上面的代碼應該不需要太多解釋,只有一行

      c.FlashParams()

      它的作用就是把form提交的參數原樣存入Flash中,還記得剛才的$field.Flash嗎?

      現在去玩玩注冊頁面吧,填寫一些錯誤的值看看反應吧,嗯,你應該很快就會發現,錯誤信息雖然已經顯示出來,但可惜卻是英文的,修改一下吧。

      func (c *Account) PostRegister(user *models.MockUser) revel.Result {
        c.Validation.Email(user.Email).Message("電子郵件格式無效")
        c.Validation.Required(user.Nickname).Message("用戶昵稱不能為空")
        c.Validation.Required(user.Password).Message("密碼不能為空")
        c.Validation.Required(user.ConfirmPassword == user.Password).Message("兩次輸入的密碼不一致")

        if c.Validation.HasErrors() {
          c.FlashParams()
          return c.Redirect((*Account).Register)
        }

        return c.Render()
      }

      Validation提供了好幾個常用的驗證方法,大家可以自己看看,應該是簡單易懂的。

      繼續,當所有參數檢查都通過之后,就調用dal.RegisterUser方法將用戶信息存入數據庫。

      func (c *Account) PostRegister(user *models.MockUser) revel.Result {
        c.Validation.Email(user.Email).Message("電子郵件格式無效")
        c.Validation.Required(user.Nickname).Message("用戶昵稱不能為空")
        c.Validation.Required(user.Password).Message("密碼不能為空")
        c.Validation.Required(user.ConfirmPassword == user.Password).Message("兩次輸入的密碼不一致")

        if c.Validation.HasErrors() {
          c.FlashParams()
          return c.Redirect((*Account).Register)
        }

        dal, err := models.NewDal()
        if err != nil {
          c.Response.Status = 500
          return c.RenderError(err)
        }
        defer dal.Close()

        err = dal.RegisterUser(user)
        if err != nil {
          c.Flash.Error(err.Error())
          return c.Redirect((*Account).Register)
        }

        return c.Redirect((*Account).RegisterSuccessful)
      }

      func (c *Account) RegisterSuccessful() revel.Result {
        return c.Render()
      }

      我增加了一個方法RegisterSuccessful,用于顯示注冊成功,大家別忘了在routes和view中添加相應的東西。

      至此,用戶注冊已經完成。不知道大家注意到沒有,就算修改go代碼,依然不需要重新啟動revel,直接刷新瀏覽器頁面就會發現新的代碼已經自動編譯并且啟用了。

      這就是revel.exe存在的一個意義,它會監視整個工程的文件修改情況,然后自動編譯和運行。開發的時候感覺就像在使用python和ruby一樣舒服。

      今天已經提到了revel的不少知識點了,希望對大家有用,歡迎任何問題!

      最后提一句,我們的創業產品 山坡網 就是完全用revel寫的,這是一個經得住考驗的框架。

      posted @ 2013-07-02 12:25  AllenDang  閱讀(7338)  評論(37)    收藏  舉報
      主站蜘蛛池模板: 吉川爱美一区二区三区视频| 成年黄页网站大全免费无码| 少妇被躁爽到高潮| 日韩精品一区二区三区vr| 中文文字幕文字幕亚洲色| 亚洲色大成网站www永久一区| 国产综合精品一区二区三区| 亚洲欧洲日韩国内高清| 亚洲熟妇av一区二区三区宅男| 国产精品一区二区国产馆| 国产成人综合色就色综合| 亚洲精品乱码久久久久久| 免费国产精品黄色一区二区| 亚洲成色精品一二三区| 不卡av电影在线| 国产在线午夜不卡精品影院| 玩弄漂亮少妇高潮白浆| 亚洲天堂在线观看完整版| 国产乱妇无乱码大黄aa片| aaa少妇高潮大片免费看| 国产av一区二区三区综合| 中文字幕在线不卡一区二区| 日韩中文字幕高清有码| 国产AV影片麻豆精品传媒| 99精品国产高清一区二区麻豆| 亚洲线精品一区二区三八戒| 最新午夜男女福利片视频| 囯产精品一区二区三区线| 亚洲VA中文字幕无码久久不卡| 亚洲人妻精品一区二区| 国产AV国片精品有毛| 免费人成在线观看网站| 国产午夜福利小视频在线| 亚洲最大的熟女水蜜桃AV网站| 人妻系列无码专区免费| 国产精品成人午夜久久| 亚洲狠狠婷婷综合久久久久图片| 国产福利永久在线视频无毒不卡 | 免费国产精品黄色一区二区| 日本无遮挡吸乳视频| 亚洲精品一区二区三区小|