Strapi V4 填充动态区域媒体未填充

问题描述 投票:0回答:7

使用下面建议的补丁,数据字段似乎填充正常,但是,媒体字段未填充。

尝试了以下方法,但没有成功 -

* http://localhost:1337/api/pages?populate=*
* {{protocol}}://{{host}}:{{port}}/api/pages?populate[Content][populate]=images

参考 - https://docs.strapi.io/developer-docs/latest/developer-resources/database-apis-reference/rest/populated-fields.html#component-dynamic-zones

下面的示例来自 - 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
    }
  }
}
controller strapi
7个回答
12
投票

推荐

强烈建议您查看此 YouTube 视频 以获取本机解决方案。

简单快速的解决方案

您可以使用市场上的Populate Deep 插件

您只需安装该软件包即可:

yarn add strapi-plugin-populate-deep

然后使用带有

deep
值的填充参数,如下所示:

/api/articles/1?populate=deep

2
投票

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,
    };
  },
}));

1
投票

这似乎对我在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}`
  1. `${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;
  },
}));



0
投票

具有“填充”语法的 Nuxt Strapi 模块

深入研究文档并进行大量测试后,我找到了一个适合我的解决方案。我能够在动态内容中填充资源。

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


0
投票

这是内容类型的动态部分(块)的响应示例:

"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

您必须指定要填充的每个字段,如果您想更深入,只需添加更多字段即可。


-1
投票

同样的情况,但是对于 GraphQL... 是否有任何弹性方法可以通过 Graphql 请求动态区域,而无需在查询中显式定义每个动态区域? 例如,我不想做这样的事情:

`query Homepage {
  components {
... on SliderComponent {
      image
      text
    }
    ... on ParagraphComponent {
      title
      description
    }
    // and so on...
  }
}`

相反,我希望能够获取所有动态区域,而无需单独查询它们。 所以理想情况下应该是这样的:

查询主页{ 成分 } 这将返回所有可能的动态区域组件及其嵌套字段。

注意:我知道上面的查询不正确,但这只是查询形状的一个想法。

© www.soinside.com 2019 - 2024. All rights reserved.