13.5. 总结和任务 之 『任务一』
主要内容:文章的分类设置; 用户创建编辑文章的时候可以选择分类、文章列表页以及详情页可以显示文章分类
【课程地址】
【主要步骤】
如何让文章详情页显示文章分类?
文章与分类的关联;在
Article
的模型里面,增加Category
字段,类似用户,都是一个文章对应一个用户和一个分类文章详情页是读取的
Article
模型里面的Get()
方法,同时我们要采用GORM
的Preload()
进行关联,这样在读取某篇文章信息的时候,也会带上分类;文章详情页;找到
_article_meta.gohtml
视图,增加分类,直接读取.Category.Name
如何让用户个人文章列表页,每个文章都显示分类?
用户的文章列表页是
User
控制器的Show
方法,定位到这个方法里面,找到article
模型的GetByUserID()
调用GetByUserID()
方法里面也是需要采用GORM
的Preload()
进行关联,这样在读取多篇文章信息的时候,也会带上分类;
如何让创建文章的时候可以选择分类?
控制器:获取变量;
articles
控制器中的Create()
方法,需要增加全部分类列表的获取,并且变量categories
追加到视图中视图:渲染变量;
_form_field.gohtml
视图中,增加分类的下拉选择框select,利用range
循环渲染categories
控制器:保存数据;
articles
控制器中的Store()
方法,接收字段category_id
, 一并存入进去即可
如何让编辑文章的时候可以选择分类?
控制器:获取变量;
articles
控制器中的Edit()
方法,需要增加全部分类列表的获取,并且变量categories
追加到视图中视图:渲染变量;
_form_field.gohtml
视图中,采用if eq
进行判断当前分类id等于文章id的时候,增加selected
,这样在编辑的时候就是选中状态了控制器;更新数据;
articles
控制器中的Update
方法
1. Article模型 【app/models/article/article.go
】
// Article 文章模型
type Article struct {
// 加载基类
models.BaseModel
Title string `gorm:"type:varchar(255);not null;" valid:"title"`
Body string `gorm:"type:longtext;not null;" valid:"body"`
// 关联用户
UserID uint64 `gorm:"not null;index"`
User user.User
// 关联分类
CategoryID uint64 `gorm:"not null;default:3;index"`
// 新增下面这一行
Category category.Category
}
2、Article模型的CRUD操作【app/models/article/crud.go
】
- 采用
GORM
的Preload()
进行关联
// Get 通过ID获取文章
func Get(idstr string) (Article, error) {
var article Article
id := types.StringToUint64(idstr)
// 增加 Preload("Category")
if err := model.DB.Debug().Preload("User").Preload("Category").First(&article, id).Error; err != nil {
return article, err
}
return article, nil
}
3、视图 【resources/views/articles/_article_meta.gohtml
】
- 增加分类一行
{{define "article-meta"}}
<p class="blog-post-meta text-secondary">
发布于 <a href="{{ .Link }}" class="font-weight-bold">{{ .CreatedAtDate }}</a>
by <a href="{{ .User.Link }}" class="font-weight-bold">{{ .User.Name }}</a>
分类 <a href="{{ .Category.Link }}" class="font-weight-bold">{{ .Category.Name }}</a>
</p>
{{ end }}
4、视图 【resources/views/articles/_form_field.gohtml
】
- 文章新增和编辑的时候分类的选择
...
<div class="form-group mt-3">
<label for="category">分类 </label>
{{ if .Categories }}
<select class="form-control" name="category_id">
{{ range $key, $category := .Categories }}
<option value="{{ $category.ID }}" {{if eq $category.ID $.Article.CategoryID }} selected {{end}} >{{ $category.Name }} </option>
{{ end }}
</select>
{{ end }}
</div>
...
5、控制器 【app/http/controllers/articles_controller.go
】
Create()
方法渲染视图的时候追加categories
...
// 读取分类
categories , _:= category.All()
view.Render(w, view.D{
"Categories" : categories,
}, "articles.create", "articles._form_field")
...
Store()
方法保存数据
...
_article := article.Article{
Title: r.PostFormValue("title"),
Body: r.PostFormValue("body"),
UserID: currentUser.ID,
// 获取分类ID
CategoryID: types.StringToUint64(r.PostFormValue("category_id")),
}
...
Edit()
方法编辑文章
// 读取分类 select
categories , _:= category.All()
// 4. 读取成功,显示编辑文章表单
view.Render(w, view.D{
"Article": _article,
"Categories": categories,
"Errors": view.D{},
}, "articles.edit", "articles._form_field")
Update()
方法更新文章
// 接收更换的分类ID
cid := r.PostFormValue("category_id")
_category , err := category.Get(cid)
if err != nil {
ac.ResponseForSQLError(w, err)
}
_article.CategoryID = types.StringToUint64(cid)
// 这个地方有一些疑惑 ???
_article.Category = _category
【我的疑惑】
- 文章的创建和更新中有个地方关于 article.CategoryID 的变更,为什么在新增的时候只需要把 CategoryID 分类id 赋值到 article里面,但是更新的时候,必须加上
_article.Category = _category
才能更新分类成功
GORM
还是挺好用的,关联模型的时候,感觉join
都不用写了
可以跟进一下这个方法
在view.go 文件中全局,可以不用再次查询
有个疑问,我希望修改表单验证(article_form.go),来确保表单提交时category_id的值有效。 但我不知道如何在规则中写这个字段名称,无论把该字段写作“category_id”还是“CategoryID”,都会报错。
楼上,直接参考not_exists规则
遇到了同样的问题, 谢谢各位楼主和大佬@wz8081633