How to Add Choices to database field using GORM

huangapple go评论91阅读模式
英文:

How to Add Choices to database field using GORM

问题

我对Golang非常陌生,因为我主要使用Python进行编码,所以遇到了一个我无法解决的问题。我想通过GORM或其他任何方法向Golang结构的字段添加选择项。

我的模型如下所示:

type User struct{
   FirstName string  `gorm:"size:100" json:"first_name"`
   LastName  string  `gorm:"size:100" json:"last_name"`
   Email     *string `gorm:"size:250;index;not null;index:email;unique" json:"email"`
   Role      string  `gorm:"default:User;not null" json:"is_active"` // TODO Add Choice
}

我想在User模型的Role字段中添加选择项['Admin', 'User', 'Guest']。是否有一种方法可以使用GORM或其他方法来实现这一目标?如果没有直接的方法,我可以将其作为外键处理。我正在使用PostgreSQL来存储表。提前感谢!

英文:

I'm very new to Golang as I mostly code in Python, so came across one problem that I'm not able to solve. I want to add choices to a field in Golang Struct via GORM or any other way if I can achieve that.

My model looks like this

type User struct{
   FirstName string  `gorm:"size:100" json:"first_name"`
   LastName  string  `gorm:"size:100" json:"last_name"`
   Email     *string `gorm:"size:250;index;not null;index:email;unique" json:"email"`
   Role      string  `gorm:"default:User;not null" json:"is_active"` // TODO Add Choice
}

I want to add choices to my Role Field in User Models from ['Admin', 'User', 'Guest']. Is there a way to achieve it using GORM or any other method that will solve my problem? I can make it a Foreign key if there is no direct way to do it. I'm using PostgreSQL to store tables. Thanks in Advance!

答案1

得分: 2

假设rolesusers之间存在一对一的关系,使用外键的一种方法如下所示:

type User struct{
   ID        int64 `json:"id"`
   FirstName string  `gorm:"size:100" json:"first_name"`
   LastName  string  `gorm:"size:100" json:"last_name"`
   Email     *string `gorm:"size:250;index;not null;index:email;unique" json:"email"`
   RoleID    int64  `json:"role_id"` 
   Role      *Role `json:"role"`
}

type Role struct {
   ID   int64 `json:"id"`
   Name string `json:"name"`
}

// 加载数据
var users []User
err := db.Preload("Role").Find(&users).Error

编辑:处理多对多关系的解决方案

假设你有一个名为users_roles的表,用于连接usersroles表,解决方案可能如下所示:

type User struct{
   ID        int64 `json:"id"`
   FirstName string  `gorm:"size:100" json:"first_name"`
   LastName  string  `gorm:"size:100" json:"last_name"`
   Email     *string `gorm:"size:250;index;not null;index:email;unique" json:"email"`
   Roles      []*Role `gorm:"many2many:users_roles;" json:"roles"`
}

type Role struct {
   ID   int64 `json:"id"`
   Name string `json:"name"`
}

// 加载数据
var users []User
err := db.Preload("Roles").Find(&users).Error
英文:

Assuming you have a one-to-one relation between roles and users, one approach with the foreign keys would be something like this:

type User struct{
   ID        int64 `json:"id"`
   FirstName string  `gorm:"size:100" json:"first_name"`
   LastName  string  `gorm:"size:100" json:"last_name"`
   Email     *string `gorm:"size:250;index;not null;index:email;unique" json:"email"`
   RoleID    int64  `json:"role_id"` 
   Role      *Role `json:"role"`
}

type Role struct {
   ID   int64 `json:"id"`
   Name string `json:"name"`
}

//load data
var users []User
err := db.Preload("Role").Find(&users).Error

EDIT: solution for many-to-many
relationship

Assuming that you would have a table like users_roles that links the users and roles tables, one solution might look like this:

type User struct{
   ID        int64 `json:"id"`
   FirstName string  `gorm:"size:100" json:"first_name"`
   LastName  string  `gorm:"size:100" json:"last_name"`
   Email     *string `gorm:"size:250;index;not null;index:email;unique" json:"email"`
   Roles      []*Role `gorm:"many2many:users_roles;" json:"roles"`
}

type Role struct {
   ID   int64 `json:"id"`
   Name string `json:"name"`
}

//load data
var users []User
err := db.Preload("Roles").Find(&users).Error

答案2

得分: 2

首先,在你的数据库中手动创建一个枚举类型(enum):

CREATE TYPE user_access AS ENUM (
	'admin',
	'user'
);

然后,在Go代码中定义一个Role类型,并实现ScanValue方法:

type Role string

const (
	Admin Role = "admin"
	User  Role = "user"
)

func (r *Role) Scan(value interface{}) error {
	*r = Role(value.([]byte))
	return nil
}

func (r Role) Value() (driver.Value, error) {
	return string(r), nil
}

最后,在User结构体中使用Role类型来表示用户的角色:

type User struct {
	ID        int64    `json:"id"`
	FirstName string   `gorm:"size:100" json:"first_name"`
	LastName  string   `gorm:"size:100" json:"last_name"`
	Email     *string  `gorm:"size:250;index;not null;index:email;unique" json:"email"`
	Role      Role     `sql:"type:user_access"` // 适用于 PostGreSQL
	Role      Role     `json:"role" sql:"type:ENUM('admin', 'user')"` // 适用于 MySQL
}

如果需要更多信息,你可以查看以下资源:GitHub问题文档

英文:

For PostGreSQL First create enum manually in your database

CREATE TYPE user_access AS ENUM (
	'admin',
	'user'
);

Then

type Role string

const (
	Admin  Role = "admin"
	User   Role = "user"
)

func (r *Role) Scan(value interface{}) error {
	*r = Role(value.([]byte))
	return nil
}

func (r Role) Value() (driver.Value, error) {
	return string(r), nil
}

type User struct{
   ID        int64   `json:"id"`
   FirstName string  `gorm:"size:100" json:"first_name"`
   LastName  string  `gorm:"size:100" json:"last_name"`
   Email     *string `gorm:"size:250;index;not null;index:email;unique" json:"email"`
   Role      Role    `sql:"type:user_access"` // PostGreSQL
   Role      Role    `json:"role" sql:"type:ENUM('admin', 'user')"` // MySQL
}

For more info you can check github issue and doc

huangapple
  • 本文由 发表于 2021年5月28日 19:22:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/67737908.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定