First, correct the documentation of beego
rel_table
Set the name of the automatically generated m2m relation table
rel_through
If you want to use a custom m2m relationship table in an m2m relationship
Set its name in the format of pkg.path.ModelName through this
eg: app.models.PostTagRel
PostTagRel table needs to have a relationship to Post and Tag
In fact, the format of rel'through is not pkg.path.ModelName. The correct posture is:
// Don't copy. It's just how to use eg learnBeego/myApp/models.RoleUser
I got stuck here for a day, and then I found the problem with the help of google. There are too few things bd can search for about go
For instance
Requirements: users, roles.
We want to realize that a user can have multiple roles and a role can have multiple users
Data sheet design
user table
id | username | passwrod | created_at | updated_at |
---|---|---|---|---|
1 | testa | 123456 | 2018-01-01 12:36:47 | 2018-01-01 12:36:47 |
2 | testb | 654321 | 2018-01-01 12:36:47 | 2018-01-01 12:36:47 |
role table
id | name | created_at | updated_at |
---|---|---|---|
1 | Test role A | 2018-01-01 12:36:47 | 2018-01-01 12:36:47 |
2 | Test role B | 2018-01-01 12:36:47 | 2018-01-01 12:36:47 |
Role user relationship table
id | user_id | role_id | created_at | updated_at |
---|---|---|---|---|
1 | 1 | 1 | 2018-01-01 12:36:47 | 2018-01-01 12:36:47 |
2 | 1 | 2 | 2018-01-01 12:36:47 | 2018-01-01 12:36:47 |
3 | 2 | 1 | 2018-01-01 12:36:47 | 2018-01-01 12:36:47 |
Model
User model
Be careful! When many to many is used, it needs to be done manually to get the relation fields. orm will not automatically complete these query operations for you. Don't think that setting rel_through is complete!
type User struct { Id int64 Username string `orm:"size(128);unique" valid:"Required"` password string `orm:"size(128);" json:"-" valid:"Required"` CreatedAt time.Time `orm:"auto_now_add;type(datetime)"` UpdatedAt time.Time `orm:"auto_now;type(datetime)"` Roles []*Role `orm:"rel(m2m);rel_through(learnBeego/myApp/models.RoleUser)"` } func init() { orm.RegisterModel(new(User)) } func (m *User) TableName() string { return "user" } // Get user information and user role through user ID func GetUserById(id int64) (v *User, err error) { o := orm.NewOrm() v = &User{Id: id} if err = o.QueryTable(new(User)).Filter("Id",id).RelatedSel().One(v); err == nil { // To get the relation field, o.LoadRelated(v, "Roles") is the key // Find the role the user belongs to if _, err = o.LoadRelated(v, "Roles");err!=nil{ return nil, err } return v, nil } return nil, err }
Role model
type Role struct { Id int64 Name string CreatedAt time.Time `orm:"auto_now_add;type(datetime)"` UpdatedAt time.Time `orm:"auto_now;type(datetime)"` Users []*User `orm:"reverse(many)"` } func init() { orm.RegisterModel(new(Role)) } func (m *Role) TableName() string { return "role" }
User role relationship model
type RoleUser struct { Id int64 User *User `orm:"rel(fk)"` Role *Role `orm:"rel(fk)"` CreatedAt time.Time `orm:"type(datetime)"` UpdatedAt time.Time `orm:"type(datetime)"` } func init() { orm.RegisterModel(new(RoleUser)) } func (m *RoleUser) TableName() string { return "role_user" }
Finally in the controller
... func (c *UserController) GetOne() { idStr := c.Ctx.Input.Param(":id") id, _ := strconv.ParseInt(idStr, 0, 64) v, err := models.GetUserById(id) if err != nil { c.Data["json"] = "No matching data found" } else { c.Data["json"] = v } c.ServeJSON() } ...
Finally, test
If the URL corresponding to GetOne() is localhost:8080/v1/user/:id
Data returned when http://localhost"8080/v1/user/1 is requested
{ "Id": 1, "Username": "testa", "CreatedAt": "2018-01-01T12:36:47+08:00", "UpdatedAt": "2018-01-01T12:36:47+08:00", "Roles":[ { "Id": 1, "Name": "Test roles A", "CreatedAt": "2018-01-01T12:36:47+08:00", "UpdatedAt": "2018-01-01T12:36:47+08:00", }, { "Id": 2, "Name": "Test roles B", "CreatedAt": "2018-01-01T12:36:47+08:00", "UpdatedAt": "2018-01-01T12:36:47+08:00", }, ] }