我有一个自定义api端点,正在使用gatsby-source-apiserver访问。我的数据库中有无法转换为图像节点的图像-即允许childimagesharp
在我的graphql中,我具有以下结构:
######################################################
# Models
######################################################
class Project(models.Model):
name = models.CharField(max_length=250, null=False, blank=False,
verbose_name=_("name"))
slug = models.SlugField(max_length=250, unique=True, null=False, blank=True,
verbose_name=_("slug"))
description = models.TextField(null=False, blank=False,
verbose_name=_("description"))
logo = models.FileField(upload_to=get_project_logo_file_path,
max_length=500, null=True, blank=True,
verbose_name=_("logo"))
created_date = models.DateTimeField(null=False, blank=False,
verbose_name=_("created date"),
default=timezone.now)
modified_date = models.DateTimeField(null=False, blank=False,
verbose_name=_("modified date"))
owner = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True,
related_name="owned_projects", verbose_name=_("owner"), on_delete=models.CASCADE)
members = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name="projects",
through="Membership", verbose_name=_("members"),
through_fields=("project", "user"))
is_private = models.BooleanField(default=True, null=False, blank=True,
verbose_name=_("is private"))
anon_permissions = ChoiceArrayField(
models.TextField(null=False, blank=False, choices=ANON_PERMISSIONS),
null=True,
blank=True,
default=list,
verbose_name=_("anonymous permissions")
)
public_permissions = ChoiceArrayField(models.TextField(null=False, blank=False, choices=MEMBERS_PERMISSIONS),
null=True, blank=True, default=list, verbose_name=_("user permissions"))
is_featured = models.BooleanField(default=False, null=False, blank=True,
verbose_name=_("is featured"))
class Meta:
db_table = "projects"
verbose_name = "project"
verbose_name_plural = "projects"
ordering = ["name", "id"]
index_together = [
["name", "id"],
]
class Membership(models.Model):
# This model stores all project memberships. Also
# stores invitations to memberships that do not have
# assigned user.
user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True, default=None,
related_name="memberships", on_delete=models.CASCADE)
project = models.ForeignKey(Project, null=False, blank=False,
related_name="memberships", on_delete=models.CASCADE)
role = models.ForeignKey('core.Role', null=False, blank=False,
related_name="memberships", on_delete=models.CASCADE)
is_admin = models.BooleanField(default=False, null=False, blank=False)
user_order = models.BigIntegerField(default=timestamp_ms, null=False, blank=False,
verbose_name=_("user order"))
class Meta:
db_table = "memberships"
verbose_name = "membership"
verbose_name_plural = "memberships"
unique_together = ("user", "project",)
ordering = ["project", "user__full_name", "user__username", "user__email"]
def get_related_people(self):
related_people = get_user_model().objects.filter(id=self.user.id)
return related_people
def clean(self):
# TODO: Review and do it more robust
memberships = Membership.objects.filter(user=self.user, project=self.project)
if self.user and memberships.count() > 0 and memberships[0].id != self.id:
raise ValidationError(_('The user is already member of the project'))
sourceFilename是一个字符串,例如'thisisanimage.jpg'-如果我在URL上附加“ http://example.com/media”这样的图像,图像将正常工作。我不确定如何继续,我已经看过createResolvers,但不完全了解如何实现它。
这是我到目前为止一直在尝试的-似乎没有做很多(除了在终端中获得“正在发生的一切”注释,而在下一个注释中却没有...
query MyQuery {
allSubmissions {
edges {
node {
works {
mediaItems {
sourceFilename
}
}
}
}
}
}
值得一提的是,作品是一个mediaItems数组,它本身是一个字段数组,其中sourceFilename是一个。查看所附的屏幕截图
答案 0 :(得分:1)
因此,在对Spectrum Gatsby聊天提出了一些很好的建议之后,我有了一些解决方案: https://spectrum.chat/gatsby-js/general/getting-relative-images-to-work-with-a-custom-api-using-gatsby-source-apiserver~a0805b02-6e2b-4be6-ab1a-ae6d3cc53fab
执行此操作的一种方法是将代码放入gatsby-node.js。这可能不是最好的方法,但是可以。
第一个问题是以GraphQL看到字段的方式查找字段的名称。您可以使用文档资源管理器浏览查询,以查找包含图像URL的媒体项目的类型名称。这通常在Pascal案例中。就我而言,这不是由于我设置事物的奇怪方式造成的!
为我找到一个更简单的方法是使用CLI:键入gatsby repl
,然后发出schema
命令。
在我的情况下,类型名称为submissionsWorksMediaItems
然后我发现我可以使用它来下载图像并为我提供childImageSharp功能:
const { createRemoteFileNode } = require("gatsby-source-filesystem")
exports.createResolvers = ({
actions,
cache,
createNodeId,
createResolvers,
store,
reporter,
}) => {
const { createNode } = actions
createResolvers({
submissionsWorksMediaItems: {
imageFile: {
type: `File`,
resolve(source, args, context, info) {
return createRemoteFileNode({
url:
`https://example.com/media/${source.filename}`,
store,
cache,
createNode,
createNodeId,
reporter,
})
},
},
},
})
}
在我的情况下,我发现我遇到了一些文件不在服务器上的问题-这造成了404错误,导致构建失败(尽管它在开发模式下有效)。因此,我改为使用以下代码(再次从Spectrum.chat中读取线程以获取所有上下文:
const { createRemoteFileNode } = require("gatsby-source-filesystem")
const imageNodes = new Map()
const getImageUrl = source =>
`https://example.com/media/${source.filename}`
exports.sourceNodes = ({
actions,
cache,
createNodeId,
getNodesByType,
store,
reporter,
}) => {
const { createNode } = actions
const imageDownloads = []
const submissions = getNodesByType("submissions")
submissions.forEach(node => {
node.works &&
node.works.forEach(({ mediaItems }) => {
mediaItems &&
mediaItems.forEach(mediaSource => {
const imageUrl = getImageUrl(mediaSource)
imageDownloads.push(
createRemoteFileNode({
url: imageUrl,
store,
cache,
createNode,
createNodeId,
reporter,
})
.then(result => {
if (!result) {
return reporter.warn(`Could not download ${imageUrl}`)
}
imageNodes.set(imageUrl, result)
})
.catch(err => {
reporter.warn(err)
})
)
})
})
})
return Promise.all(imageDownloads)
}
exports.createResolvers = ({ createResolvers }) => {
createResolvers({
submissionsWorksMediaItems: {
imageFile: {
type: `File`,
resolve(source, args, context, info) {
const imageUrl = getImageUrl(source)
if (imageNodes.has(imageUrl)) {
return imageNodes.get(imageUrl)
}
return null
},
},
},
})
}