# 向目录项序列化器添加用户属性

**URL:** https://meta.discourse.org/t/adding-user-attributes-to-the-directory-item-serializer/130927
**Category:** Development
**Created:** [2019年十月14日 06:45 UTC](https://meta.discourse.org/t/adding-user-attributes-to-the-directory-item-serializer/130927 "2019-10-14T06:45:10Z")
**Posts on this page:** 18
**Page:** 1

<div class="post-metadata">

### Author: ![angus](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/angus/32/341715_2.png) [@angus](https://meta.discourse.org/u/angus)
#### Post date: [2019年十月14日 06:45 UTC](https://meta.discourse.org/t/adding-user-attributes-to-the-directory-item-serializer/130927/1 "2019-10-14T06:45:11Z")

</div>

一位客户联系我，希望创建一个基于卡片式布局的用户目录。

由于他托管在 [discourse.org](http://discourse.org) 上，我最初表示这无法实现（除了可能存在的性能问题），因为填充用户卡片所需的属性并未包含在与目录项一起序列化的用户对象中。

不过，在进一步讨论后，我认为一种可行的方案是向核心代码提交一个 PR，通过站点设置将用户属性添加到目录项序列化器中。这样做的目的是，该功能将适用于各种需要不同用户属性组合的用户目录样式（示例如下）。

经过实验，我提出了一种相对简单的实现方案，具体可参考以下差异对比：

[https://github.com/discourse/discourse/compare/master...angusmcleod:directory\_user\_attribute\_whitelist](https://github.com/discourse/discourse/compare/master...angusmcleod:directory_user_attribute_whitelist)

具体步骤如下：

1. 创建一个专用的 `DirectoryItemUserSerializer`（目前 `DirectoryItemSerializer` 内部使用的“UserSerializer”一直让我觉得有些别扭）。

2. 如果站点管理员选择了要添加的用户属性：

这样做的目标包括：

1. 不影响现有的任何行为。

2. 仅序列化所请求的属性。

如果各位认可这一方案/请求，我将完成以下工作：

1. 为站点设置添加验证（即确保输入的字符串是有效的用户属性）。

2. 添加相应的测试。

不过，我认为最好先征求大家的意见。

### 示例

以下是该功能所能实现的效果示例：截图来自我的本地环境，仅使用了上述对核心代码的修改，并配合一个覆盖现有目录的主题组件，该组件使用了自定义的用户卡片组件：

 ![52%20PM](https://global.discourse-cdn.com/meta/original/3X/f/4/f44c7d44dfe6ae94a69a8f0cc483df64953a4cc7.jpeg)

---

<div class="post-metadata">

### Author: ![angus](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/angus/32/341715_2.png) [@angus](https://meta.discourse.org/u/angus)
#### Post date: [2019年十月16日 06:50 UTC](https://meta.discourse.org/t/adding-user-attributes-to-the-directory-item-serializer/130927/2 "2019-10-16T06:50:41Z")

</div>

@sam 你觉得这个方案能在 PR 中实现吗？

---

<div class="post-metadata">

### Author: ![sam](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/sam/32/102149_2.png) [@sam](https://meta.discourse.org/u/sam)
#### Post date: [2019年十月17日 06:10 UTC](https://meta.discourse.org/t/adding-user-attributes-to-the-directory-item-serializer/130927/3 "2019-10-17T06:10:48Z")

</div>

> [@angus](#):
>
> 不过，在进一步讨论后，我确定了一种方法：通过站点设置，将用户属性添加到目录项序列化器中，从而向核心提交一个 PR。

我认为 @blake 和 @awesomerobot 正在与另一位有类似需求的客户合作。我对引入一个类似 `always_include_topic_excerpts` 的站点设置持开放态度。

不过有个前提：我希望该功能经过测试，并且该站点设置应设为隐藏。

我知道 @david 也对这个问题很感兴趣。我目前有些犹豫，但也许这里有一个更干净、更长期的解决方案：

1. 添加隐藏的站点设置，用于“允许插件和主题选择获取额外的序列化信息”，默认关闭。
2. 然后为主题/插件定义一种协议，用于“请求”这些额外信息。

这样做的好处是，某些主题可以获得额外的序列化信息，而其他主题则不会。

在给予你明确许可之前，我想先再等一等 David 的意见。

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [2019年十月17日 07:30 UTC](https://meta.discourse.org/t/adding-user-attributes-to-the-directory-item-serializer/130927/4 "2019-10-17T07:30:25Z")

</div>

是否可以让用户目录序列化器接受一个新参数，例如 `users.json?include_profile=true`？

这样我们就可以添加一个 JS 插件 API，允许主题添加此参数：

```js
api.userListIncludeProfile(true)

```

“Profile”将包含常规用户序列化器中的所有字段（同时注意避免引入 N+1 查询）。我认为指定单个字段对性能影响不大，因此依我之见，我们应该保持简单。

同样的方法也适用于主题列表，例如 `?include_excerpts=true`。

我也喜欢这一点，因为它意味着“每个主题的序列化器配置”不会被匿名缓存破坏！

你怎么看，@sam？

---

<div class="post-metadata">

### Author: ![sam](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/sam/32/102149_2.png) [@sam](https://meta.discourse.org/u/sam)
#### Post date: [2019年十月17日 07:33 UTC](https://meta.discourse.org/t/adding-user-attributes-to-the-directory-item-serializer/130927/5 "2019-10-17T07:33:26Z")

</div>

接近了，但这并不能完美解决，因为当你进入网站首页或 `/u` 路径时，无法在路径中添加参数，我们需要更改默认值：(

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [2019年十月17日 07:37 UTC](https://meta.discourse.org/t/adding-user-attributes-to-the-directory-item-serializer/130927/6 "2019-10-17T07:37:20Z")

</div>

哦，是的 😢

在这种情况下，我认为一个隐藏的站点设置是一个不错的起点。如果能按主题设置就更好了，但我们首先需要构建一些基础设施。我仍然认为，一个布尔值“用户列表包含个人资料”的设置更容易理解。

---

<div class="post-metadata">

### Author: ![angus](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/angus/32/341715_2.png) [@angus](https://meta.discourse.org/u/angus)
#### Post date: [2019年十月17日 09:49 UTC](https://meta.discourse.org/t/adding-user-attributes-to-the-directory-item-serializer/130927/7 "2019-10-17T09:49:32Z")

</div>

这是否包括用户卡片中使用的属性，例如 featured\_user\_badges？

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [2019年十月17日 09:50 UTC](https://meta.discourse.org/t/adding-user-attributes-to-the-directory-item-serializer/130927/8 "2019-10-17T09:50:50Z")

</div>

是的，我认为是这样——只要能在不引入 N+1 查询问题的前提下，将常规用户序列化器中包含的所有内容都包括进来。

---

<div class="post-metadata">

### Author: ![angus](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/angus/32/341715_2.png) [@angus](https://meta.discourse.org/u/angus)
#### Post date: [2019年十月18日 06:32 UTC](https://meta.discourse.org/t/adding-user-attributes-to-the-directory-item-serializer/130927/9 "2019-10-18T06:32:55Z")

</div>

太好了。如果你们考虑接受这个#pr-welcome 并告知具体形式，我们很乐意制作一个。后续将由 @fzngagan 负责处理。

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [2019年十月18日 07:15 UTC](https://meta.discourse.org/t/adding-user-attributes-to-the-directory-item-serializer/130927/12 "2019-10-18T07:15:56Z")

</div>

让我们采用一个单一的、布尔类型的隐藏站点设置，该设置将添加所有相关信息。

---

<div class="post-metadata">

### Author: ![fzngagan](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/fzngagan/32/259349_2.png) [@fzngagan](https://meta.discourse.org/u/fzngagan)
#### Post date: [2019年十月18日 19:36 UTC](https://meta.discourse.org/t/adding-user-attributes-to-the-directory-item-serializer/130927/13 "2019-10-18T19:36:31Z")

</div>

感谢提醒，@david。我将从下周一开始着手调查。

---

<div class="post-metadata">

### Author: ![fzngagan](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/fzngagan/32/259349_2.png) [@fzngagan](https://meta.discourse.org/u/fzngagan)
#### Post date: [2019年十月19日 05:30 UTC](https://meta.discourse.org/t/adding-user-attributes-to-the-directory-item-serializer/130927/14 "2019-10-19T05:30:00Z")

</div>

这里需要澄清的一点是请求额外数据的`protocol`。我们是应该依赖前端设置的站点配置来请求数据，还是按照你的建议，在 plugin-api 中添加另一个 API？

> [@david](#):
>
> api.userListIncludeProfile(true)

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [2019年十月19日 08:22 UTC](https://meta.discourse.org/t/adding-user-attributes-to-the-directory-item-serializer/130927/15 "2019-10-19T08:22:23Z")

</div>

让我们保持简单，忽略我之前关于参数和 JavaScript API 的帖子。

如果服务器上的站点设置已启用，则返回额外信息；如果未启用，则不返回。

因此，目前管理员需要手动启用该设置。未来我们可能会考虑允许主题自动切换此设置。

---

<div class="post-metadata">

### Author: ![fzngagan](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/fzngagan/32/259349_2.png) [@fzngagan](https://meta.discourse.org/u/fzngagan)
#### Post date: [2019年十月19日 13:50 UTC](https://meta.discourse.org/t/adding-user-attributes-to-the-directory-item-serializer/130927/16 "2019-10-19T13:50:38Z")

</div>

没问题。主题组件应该根据设置是否启用来条件性地使用这些额外字段，对吧？

此外，服务器也应在设置启用时才发送这些额外字段。

---

<div class="post-metadata">

### Author: ![angus](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/angus/32/341715_2.png) [@angus](https://meta.discourse.org/u/angus)
#### Post date: [2019年十月20日 23:47 UTC](https://meta.discourse.org/t/adding-user-attributes-to-the-directory-item-serializer/130927/18 "2019-10-20T23:47:01Z")

</div>

@david 谢谢 David。我们将着手准备 PR 并尽快回复您。

---

<div class="post-metadata">

### Author: ![fzngagan](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/fzngagan/32/259349_2.png) [@fzngagan](https://meta.discourse.org/u/fzngagan)
#### Post date: [2019年十一月20日 02:46 UTC](https://meta.discourse.org/t/adding-user-attributes-to-the-directory-item-serializer/130927/19 "2019-11-20T02:46:56Z")

</div>

@david 我在此处提交了一个 PR

> <https://github.com/discourse/discourse/pull/8376>
>
> Adds a hidden site setting \`user\_directory\_includes\_profile\`, which when enabled…, serializes all the attributes from \`UserSerializer\` to the \`DirectoryItem\`

cc @angus

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [2020年三月16日 14:26 UTC](https://meta.discourse.org/t/adding-user-attributes-to-the-directory-item-serializer/130927/20 "2020-03-16T14:26:37Z")

</div>

在此闭环。我们决定不再向目录序列化器添加任何属性。相反，我们对用户序列化的性能进行了大幅改进。我们将用户卡片拆分到独立的路线上，并新增了一条可一次性返回多个卡片的路线。

您可以在以下主题组件中找到使用此新路线的示例：

> [@User Card Directory](https://meta.discourse.org/t/user-card-directory/144479?u=david):
>
> discourse2Summary User Card Directory changes the /u user directory to display a grid of user cards instead of the stats table.eyeglassesPreview [Preview on Discourse Theme Creator](https://discourse.theme-creator.io/theme/Discourse/user-card-directory)hammer_and_wrenchRepository Link [https://github.com/discourse/discourse-user-card-directory](https://github.com/discourse/discourse-user-card-directory)open_bookNew to Discourse Themes? [Beginner’s guide to using Discourse Themes](https://meta.discourse.org/t/beginners-guide-to-using-discourse-themes/91966) Install this theme component Features Settings Name Description h…

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [2020年三月16日 18:00 UTC](https://meta.discourse.org/t/adding-user-attributes-to-the-directory-item-serializer/130927/21 "2020-03-16T18:00:00Z")

</div>

此主题在 3 小时后自动关闭。不再允许新回复。
