如何使用graphene-django v2.0上传下载文件?求相关示例
Graphene-Django v2.0 图片上传与下载完整示例
我当年刚上手graphene-django v2.0时,也在文件上传下载这块卡了好久,特意整理了能直接跑通的示例,你跟着一步步来就行:
一、图片下载查询实现
首先得有个存储图片的Django模型,然后把它映射成GraphQL类型,再写查询字段。
1. 定义Django模型
在你的app的models.py里:
from django.db import models class ImageModel(models.Model): title = models.CharField(max_length=100) image = models.ImageField(upload_to='uploads/images/') # 图片会存在MEDIA_ROOT/uploads/images/下 created_at = models.DateTimeField(auto_now_add=True) def __str__(self): return self.title
2. 创建GraphQL类型
在schema.py里定义对应的ObjectType:
import graphene from graphene_django import DjangoObjectType from .models import ImageModel class ImageType(DjangoObjectType): class Meta: model = ImageModel fields = ("id", "title", "image", "created_at") # image字段会自动返回相对访问URL # 若需要自定义完整绝对URL,可额外添加字段 image_url = graphene.String() def resolve_image_url(self, info): # 拼接带域名的完整访问链接 return info.context.build_absolute_uri(self.image.url)
3. 添加查询字段
在根查询里添加获取图片的字段:
class Query(graphene.ObjectType): all_images = graphene.List(ImageType) image_by_id = graphene.Field(ImageType, id=graphene.Int(required=True)) def resolve_all_images(self, info, **kwargs): return ImageModel.objects.all() def resolve_image_by_id(self, info, id): try: return ImageModel.objects.get(id=id) except ImageModel.DoesNotExist: return None schema = graphene.Schema(query=Query)
4. 查询使用示例
在GraphQL Playground里执行查询:
query { allImages { id title image # 返回相对URL imageUrl # 返回完整绝对URL createdAt } imageById(id: 1) { title imageUrl } }
二、图片上传突变实现
graphene-django v2.0的文件上传需要用到Upload类型,还要确保Django的媒体配置正确。
1. 先配置Django媒体设置
在settings.py里添加:
import os BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) MEDIA_ROOT = os.path.join(BASE_DIR, 'media') MEDIA_URL = '/media/'
然后在项目的urls.py里添加媒体路由:
from django.conf import settings from django.conf.urls.static import static urlpatterns = [ # 你的其他路由 ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
2. 定义上传突变
在schema.py里添加:
class UploadImageMutation(graphene.Mutation): class Arguments: title = graphene.String(required=True) image = graphene.Upload(required=True) # 用Upload类型接收文件 # 突变返回的结果类型 image = graphene.Field(ImageType) def mutate(self, info, title, image): # 处理上传文件,创建ImageModel实例 image_instance = ImageModel( title=title, image=image # 直接把Upload对象赋值给ImageField ) image_instance.save() return UploadImageMutation(image=image_instance) # 根突变类 class Mutation(graphene.ObjectType): upload_image = UploadImageMutation.Field() # 更新schema,包含突变 schema = graphene.Schema(query=Query, mutation=Mutation)
3. 上传使用示例
方式1:用GraphQL Playground上传
在Playground里选择Mutation,然后用文件选择器上传:
mutation($title: String!, $image: Upload!) { uploadImage(title: $title, image: $image) { image { id title imageUrl } } }
在Variables里填写:
{ "title": "我的测试图片" }
再在下方的“Map”区域把$image映射到你选择的本地图片文件。
方式2:用curl命令上传
curl -X POST \ http://localhost:8000/graphql/ \ -F operations='{"query": "mutation($title: String!, $image: Upload!) { uploadImage(title: $title, image: $image) { image { id title imageUrl } } }", "variables": {"title": "测试图片", "image": null}}' \ -F map='{"0": ["variables.image"]}' \ -F 0=@/path/to/your/image.jpg
几个关键注意事项
- 确保安装了
pillow库(Django处理图片依赖它):pip install pillow - 生产环境不要用
static路由,要用Nginx等服务器处理媒体文件访问 - 如果遇到权限问题,检查
MEDIA_ROOT目录的读写权限
内容的提问来源于stack exchange,提问作者sgaseretto
相关产品推荐
相关产品推荐

