使用下面建议的补丁,数据字段似乎填充正常,但是,媒体字段未填充。
尝试了以下方法,但没有成功 -
* http://localhost:1337/api/pages?populate=*
* {{protocol}}://{{host}}:{{port}}/api/pages?populate[Content][populate]=images
下面的示例来自 - https://forum.strapi.io/t/strapi-v4-populate-media-and-dynamiczones-from-components/12670/9
也尝试过这个插件(没有运气)-https://www.npmjs.com/package/strapi-plugin-populate-deep
下面带有动态区域的页面示例 -
/helpers/populate.js(这适用于除图像之外的所有数据)-
const { createCoreController } = require("@strapi/strapi/lib/factories");
function populateAttribute({ components }) {
if (components) {
const populate = components.reduce((currentValue, current) => {
return { ...currentValue, [current.split(".").pop()]: { populate: "*" } };
}, {});
return { populate };
}
return { populate: "*" };
}
const getPopulateFromSchema = function (schema) {
return Object.keys(schema.attributes).reduce((currentValue, current) => {
const attribute = schema.attributes[current];
if (!["dynamiczone", "component"].includes(attribute.type)) {
return currentValue;
}
return {
...currentValue,
[current]: populateAttribute(attribute),
};
}, {});
};
function createPopulatedController(uid, schema) {
return createCoreController(uid, () => {
console.log(schema.collectionName, JSON.stringify(getPopulateFromSchema(schema)));
return {
async find(ctx) {
ctx.query = {
...ctx.query,
populate: getPopulateFromSchema(schema),
// populate: '*',
};
return await super.find(ctx);
},
async findOne(ctx) {
ctx.query = {
...ctx.query,
populate: getPopulateFromSchema(schema),
// populate: '*',
};
return await super.findOne(ctx);
},
};
});
}
module.exports = createPopulatedController;
/src/api/page/controllers/pages.js -
"use strict";
const collectionType = 'page'
const schema = require(`../content-types/${collectionType}/schema.json`);
const createPopulatedController = require("../../../helpers/populate");
module.exports = createPopulatedController(`api::${collectionType}.${collectionType}`, schema);
以下图像的响应无法通过 -
{
"data": [
{
"id": 1,
"attributes": {
"title": "testing home page",
"slug": "/",
"publish_at": null,
"createdAt": "2022-04-12T12:08:32.002Z",
"updatedAt": "2022-04-12T15:07:11.990Z",
"publishedAt": "2022-04-12T12:42:55.682Z",
"locale": "en",
"seoComponent": null,
"block": [
{
"id": 1,
"__component": "image.image-copy-full",
"heading": "Delivering something amazing",
"subHeading": "test sadasdf",
"ctaButton": "test",
"miscValues": {
"testing": "object field"
},
"actionUrl": null,
"isInternal": true,
"isVisible": true
},
{
"id": 1,
"__component": "image.image-copy-chip",
"heading": "A platform",
"subHeading": "Allowing full integration",
"ctaButton": null,
"miscValues": null,
"actionUrl": null,
"isInternal": true,
"isVisible": false
},
{
"id": 1,
"__component": "image.image-copy",
"heading": "To transform our world",
"subHeading": "In order to reach that scale",
"ctaButton": null,
"miscValues": null,
"actionUrl": null,
"isInternal": true
}
]
}
}
],
"meta": {
"pagination": {
"page": 1,
"pageSize": 25,
"pageCount": 1,
"total": 1
}
}
}
屏幕截图中“ImageCopyFull”的架构示例 -
{
"collectionName": "components_image_image_copy_fulls",
"info": {
"displayName": "ImageCopyFull",
"icon": "file-image",
"description": ""
},
"options": {},
"attributes": {
"heading": {
"type": "string"
},
"subHeading": {
"type": "string"
},
"ctaButton": {
"type": "string"
},
"miscValues": {
"type": "json"
},
"actionUrl": {
"type": "string"
},
"isInternal": {
"type": "boolean",
"default": true
},
"image": {
"type": "media",
"multiple": false,
"required": true,
"allowedTypes": [
"images",
"videos",
"audios",
"files"
]
},
"isVisible": {
"type": "boolean",
"default": false
}
}
}
强烈建议您查看此 YouTube 视频 以获取本机解决方案。
您可以使用市场上的Populate Deep 插件。
您只需安装该软件包即可:
yarn add strapi-plugin-populate-deep
然后使用带有
deep
值的填充参数,如下所示:
/api/articles/1?populate=deep
在strapi github下找到答案,大声喊“Tomnovotny7”,谢谢你。
将以下代码复制到“page.js”下 -
const { isEmpty, merge } = require("lodash/fp");
const getModelPopulationAttributes = (model) => {
if (model.uid === "plugin::upload.file") {
const { related, ...attributes } = model.attributes;
return attributes;
}
return model.attributes;
};
const getFullPopulateObject = (modelUid, maxDepth = 20) => {
if (maxDepth <= 1) {
return true;
}
if (modelUid === "admin::user") {
return undefined;
}
const populate = {};
const model = strapi.getModel(modelUid);
for (const [key, value] of Object.entries(
getModelPopulationAttributes(model)
)) {
if (value) {
if (value.type === "component") {
populate[key] = getFullPopulateObject(value.component, maxDepth - 1);
} else if (value.type === "dynamiczone") {
const dynamicPopulate = value.components.reduce((prev, cur) => {
const curPopulate = getFullPopulateObject(cur, maxDepth - 1);
return curPopulate === true ? prev : merge(prev, curPopulate);
}, {});
populate[key] = isEmpty(dynamicPopulate) ? true : dynamicPopulate;
} else if (value.type === "relation") {
const relationPopulate = getFullPopulateObject(
value.target,
maxDepth - 1
);
if (relationPopulate) {
populate[key] = relationPopulate;
}
} else if (value.type === "media") {
populate[key] = true;
}
}
}
return isEmpty(populate) ? true : { populate };
};
const modelUid = "api::page.page";
module.exports = createCoreController(modelUid, ({ strapi }) => ({
async find(ctx) {
const { query } = ctx;
const { results, meta } = await strapi.service(modelUid).find({
...getFullPopulateObject(modelUid),
...query,
});
const sanitizedEntities = await this.sanitizeOutput(results, ctx);
return {
data: sanitizedEntities,
meta,
};
},
}));
这似乎对我在Strapi v4中获取动态组件和组件时有用,不确定是否是“推荐方式”,3种方式(1和2几乎相同)
1)
`${process.env.NEXT_PUBLIC_STRAPI_API}/pages?publicationState=live&populate[seo][populate]=%2A&populate[pageHeading][populate]=%2A&populate[socialMedia][populate]=%2A&populate[components][populate]=%2A&filters[slug]=${params.slug}`
与 1) 相同,只不过将“%2A”替换为“*”:
`${process.env.NEXT_PUBLIC_STRAPI_API}/pages?publicationState=live&populate[seo][populate]=*&populate[pageHeading][populate]=*&populate[socialMedia][populate]=*&populate[components][populate]=*&filters[slug]=${params.slug}`
`${process.env.NEXT_PUBLIC_STRAPI_API}/pages?publicationState=live&filters[slug]=${params.slug}`
控制器(src/api/page/controllers/page.js)
"use strict";
/**
* page controller
*/
const { createCoreController } = require("@strapi/strapi").factories;
module.exports = createCoreController("api::page.page", () => ({
async find(ctx) {
const populateList = [
"seo",
"pageHeading",
"socialMedia",
"components.image",
"components.types",
];
populateList.push(ctx.query.populate);
ctx.query.populate = populateList.join(",");
const content = await super.find(ctx);
return content;
},
}));
深入研究文档并进行大量测试后,我找到了一个适合我的解决方案。我能够在动态内容中填充资源。
const response = await find('posts', {
populate: {
project: true,
blocks: {
on: {
'shared.media': { populate: '*' },
'shared.quote': { populate: '*' },
},
},
},
});
结果是:
.../api/posts?populate[project]=true&populate[blocks][on][shared.media][populate]=%2A&populate[blocks][on][shared.quote][populate]=%2A
这是内容类型的动态部分(块)的响应示例:
"blocks": [
{
"id": 1,
"__component": "shared.media",
"file": {}
},
{
"id": 1,
"__component": "shared.slider",
"files": {}
},
{
"id": 1,
"__component": "shared.rich-text",
"body": "# Test"
}
]
如您所见,在shared.media和shared.slider中,附件分别位于file和files中,默认情况下不会填充。这是最终的要求:
http://localhost:1337/api/articles?populate[0]=cover.attributes.&populate[1]=categories&populate[2]=blocks.file&populate[3]=blocks.files
您必须指定要填充的每个字段,如果您想更深入,只需添加更多字段即可。
同样的情况,但是对于 GraphQL... 是否有任何弹性方法可以通过 Graphql 请求动态区域,而无需在查询中显式定义每个动态区域? 例如,我不想做这样的事情:
`query Homepage {
components {
... on SliderComponent {
image
text
}
... on ParagraphComponent {
title
description
}
// and so on...
}
}`
相反,我希望能够获取所有动态区域,而无需单独查询它们。 所以理想情况下应该是这样的:
查询主页{ 成分 } 这将返回所有可能的动态区域组件及其嵌套字段。
注意:我知道上面的查询不正确,但这只是查询形状的一个想法。