Golang模板中如何在同一HTML表格内遍历两个切片

Golang模板中如何在同一HTML表格内遍历两个切片

type User struct {
	Id               uint64 `json:"id" gorm:"primaryKey"`
	FullName  string `json:"full_name"`
	Moniker     string `json:"moniker"`
	Contact     string `json:"contact"`
	Email        string `json:"email"`
}

type UserAccount struct {
	Id                       uint64 `gorm:"primaryKey"`
	CompanyRank  string `json:"company_rank"`
	SystemLevel     string `json:"system_level"`
	Department       string `json:"department"`
	UserRefer         int    `json:"fkuser_id"`
	User                  User   `gorm:"foreignKey:UserRefer"`
}

这是从数据库的 UserAccount 表中获取所有记录列表的方法。

func (h handler) GetUserAccounts(ctx *gin.Context) {

userAccounts := []model.UserAccount{}
var users []model.User
links := model.BodyNLinks()
links.Title = "Roles List"
links.Heading = "Roles List"

if result := h.DB.Find(&userAccounts); result.Error != nil {
	ctx.AbortWithError(http.StatusNotFound, result.Error)
	return
}

for _, v := range userAccounts {
	user := model.User{}
	if result := h.DB.Find(&user, v.UserRefer); result.Error != nil {
		ctx.AbortWithError(http.StatusNotFound, result.Error)
		return
	}
	users = append(users, user)
}

ctx.HTML(200, "useraccount/list.html", gin.H{
	"userAccounts": userAccounts,
	"users":        users,
	"link":         links,
})
}

用于显示来自 user_accounts 数据库记录的 HTML 页面。

{{ define "useraccount/list.html" }}
{{ template "01Temps/header.html" . }}
<ul>
    {{range $xi := .users}}
    <li>{{$xi.FullName}} {{$xi.Contact}}</li>
    {{end}}
</ul> </br>
<table na border="1">
    <tr align="right">
        <th>USER</th>
        <th>FullName</th>
        <th>Email</th>
        <th>Department</th>
        <th>Level</th>
        <th>Role</th>
        <th>Action</th>
    </tr>
    <tbody id="myTbl">
        {{range $xi := .userAccounts}}
        <tr align="left">
            <td>
                <a href="/user/getrecord/{{$xi.UserRefer}}"
                    onclick=" return confirm('Redirect to USER:{{$xi.UserRefer}} ?')">
                    USR:{{$xi.UserRefer}}</a>
            </td>

            {{range $xu := .users}}
            <td>{{$xu.FullName}}</td>
            <td>{{$xu.Email}}</td>
            {{end}}

            <td>{{$xi.Department}}</td>
            <td>{{$xi.SystemLevel}}</td>
            <td>{{$xi.CompanyRank}}</td>
            <td><a href="/useraccount/updaterecord/{{$xi.Id}}"
                    onclick="return confirm('Update USER:{{$xi.UserRefer}} ?')">Update</a>
                <label>||</label>
                <a href="/useraccount/deleterecord/{{$xi.Id}}"
                    onclick="return confirm('Delete USER:{{$xi.UserRefer}} ?')">Del</a>
                <label>||</label>
                <a href="/useraccount/getrecord/{{$xi.Id}}"
                    onclick="return confirm('Display USER:{{$xi.UserRefer}} ?')">Display</a>
            </td>
        </tr>
        {{end}}
    </tbody>
</table>
</br>
{{ template "01Temps/footer.html" . }}
{{end}}

为什么我无法将控制器中的 users 和 userAccounts 数据显示在同一个模板表格行中? 在 UserAccount 结构体中,如果我这样做:

UserRefer int json:"fkuser_id"
UserFullNameRefer string json:"fkuser_full_name"
User User gorm:"foreignKey:UserRefer"

我该如何将 UserFullNameRefer 作为来自 User 结构体的外键列添加进去?


更多关于Golang模板中如何在同一HTML表格内遍历两个切片的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang模板中如何在同一HTML表格内遍历两个切片的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Golang模板中同时遍历两个切片需要使用索引来对齐数据。你的代码问题在于内层循环会遍历所有users,而不是匹配当前userAccount的user。以下是解决方案:

{{ define "useraccount/list.html" }}
{{ template "01Temps/header.html" . }}
<table border="1">
    <tr align="right">
        <th>USER</th>
        <th>FullName</th>
        <th>Email</th>
        <th>Department</th>
        <th>Level</th>
        <th>Role</th>
        <th>Action</th>
    </tr>
    <tbody id="myTbl">
        {{range $index, $account := .userAccounts}}
        <tr align="left">
            <td>
                <a href="/user/getrecord/{{$account.UserRefer}}"
                    onclick="return confirm('Redirect to USER:{{$account.UserRefer}} ?')">
                    USR:{{$account.UserRefer}}</a>
            </td>
            
            {{if lt $index (len $.users)}}
            {{$user := index $.users $index}}
            <td>{{$user.FullName}}</td>
            <td>{{$user.Email}}</td>
            {{else}}
            <td>N/A</td>
            <td>N/A</td>
            {{end}}
            
            <td>{{$account.Department}}</td>
            <td>{{$account.SystemLevel}}</td>
            <td>{{$account.CompanyRank}}</td>
            <td>
                <a href="/useraccount/updaterecord/{{$account.Id}}"
                    onclick="return confirm('Update USER:{{$account.UserRefer}} ?')">Update</a>
                <label>||</label>
                <a href="/useraccount/deleterecord/{{$account.Id}}"
                    onclick="return confirm('Delete USER:{{$account.UserRefer}} ?')">Del</a>
                <label>||</label>
                <a href="/useraccount/getrecord/{{$account.Id}}"
                    onclick="return confirm('Display USER:{{$account.UserRefer}} ?')">Display</a>
            </td>
        </tr>
        {{end}}
    </tbody>
</table>
{{ template "01Temps/footer.html" . }}
{{end}}

对于外键问题,如果你需要存储用户全名的冗余字段,可以这样修改结构体:

type UserAccount struct {
    Id              uint64 `gorm:"primaryKey"`
    CompanyRank     string `json:"company_rank"`
    SystemLevel     string `json:"system_level"`
    Department      string `json:"department"`
    UserRefer       int    `json:"fkuser_id"`
    UserFullName    string `json:"fkuser_full_name"` // 冗余字段
    User            User   `gorm:"foreignKey:UserRefer"`
}

然后在查询时填充这个字段:

func (h handler) GetUserAccounts(ctx *gin.Context) {
    userAccounts := []model.UserAccount{}
    links := model.BodyNLinks()
    links.Title = "Roles List"
    links.Heading = "Roles List"

    if result := h.DB.Preload("User").Find(&userAccounts); result.Error != nil {
        ctx.AbortWithError(http.StatusNotFound, result.Error)
        return
    }

    // 填充冗余字段
    for i := range userAccounts {
        userAccounts[i].UserFullName = userAccounts[i].User.FullName
    }

    ctx.HTML(200, "useraccount/list.html", gin.H{
        "userAccounts": userAccounts,
        "link":         links,
    })
}

这样在模板中可以直接使用:

<td>{{$account.UserFullName}}</td>

更好的做法是使用GORM的Preload预加载关联数据,这样就不需要单独查询users切片:

func (h handler) GetUserAccounts(ctx *gin.Context) {
    userAccounts := []model.UserAccount{}
    links := model.BodyNLinks()
    links.Title = "Roles List"
    links.Heading = "Roles List"

    if result := h.DB.Preload("User").Find(&userAccounts); result.Error != nil {
        ctx.AbortWithError(http.StatusNotFound, result.Error)
        return
    }

    ctx.HTML(200, "useraccount/list.html", gin.H{
        "userAccounts": userAccounts,
        "link":         links,
    })
}

然后在模板中通过关联访问:

{{range $account := .userAccounts}}
<tr align="left">
    <td>
        <a href="/user/getrecord/{{$account.UserRefer}}"
            onclick="return confirm('Redirect to USER:{{$account.UserRefer}} ?')">
            USR:{{$account.UserRefer}}</a>
    </td>
    
    <td>{{$account.User.FullName}}</td>
    <td>{{$account.User.Email}}</td>
    
    <td>{{$account.Department}}</td>
    <td>{{$account.SystemLevel}}</td>
    <td>{{$account.CompanyRank}}</td>
    <td>
        <a href="/useraccount/updaterecord/{{$account.Id}}"
            onclick="return confirm('Update USER:{{$account.UserRefer}} ?')">Update</a>
        <label>||</label>
        <a href="/useraccount/deleterecord/{{$account.Id}}"
            onclick="return confirm('Delete USER:{{$account.UserRefer}} ?')">Del</a>
        <label>||</label>
        <a href="/useraccount/getrecord/{{$account.Id}}"
            onclick="return confirm('Display USER:{{$account.UserRefer}} ?')">Display</a>
    </td>
</tr>
{{end}}
回到顶部