You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用aiohttp实现带文件的POST请求及Django测试适配?

Let's break this down into two parts to fix your file upload issues with aiohttp and Django testing.

Fixing the initial aiohttp file upload error

The TypeError you're hitting happens because aiohttp's request() method doesn't accept a files keyword argument — that's a common gotcha! To mimic the multipart/form-data submission from your HTML form (which lets Django populate request.FILES), you need to structure your upload data correctly using the data parameter instead.

Here's the corrected code:

import aiohttp

async def upload_file(url):
    # Use a context manager to guarantee the file gets closed properly
    with open('file/path', 'rb') as file:
        # Structure for file uploads: a dict where values are tuples
        # Format: (filename, file_object, content_type)
        form_payload = {
            'key': ('your_file_name.txt', file, 'text/plain')  # Adjust content type to match your file
        }
        async with aiohttp.request('post', url, data=form_payload) as response:
            return await response.text()

This structure tells aiohttp to build a valid multipart/form-data request, just like your HTML form. Django will now pick up the file in request.FILES['key'] as expected.

Adjusting pytest test code with Django's InMemoryUploadedFile

Your test code is creating an InMemoryUploadedFile, but you're passing the raw file object f instead of the uploaded file instance. Plus, you still need to follow the same tuple structure for aiohttp to recognize it as a file upload.

Here's the revised test code:

from django.core.files.uploadedfile import InMemoryUploadedFile
from django.core.files.base import DjangoFile
import aiohttp

def get_uploaded_file(file_path):
    with open(file_path, "rb") as f:
        file = DjangoFile(f)
        # Extract just the filename (instead of using the full path) for realism
        filename = file_path.split('/')[-1]
        uploaded_file = InMemoryUploadedFile(
            file, 
            None, 
            filename, 
            "text/plain", 
            file.size, 
            None, 
            None
        )
        return uploaded_file

async def test_file_upload(url, path):
    uploaded_file = get_uploaded_file(path)
    # Use the uploaded file instance in the required tuple structure
    test_form_data = {
        'key': (uploaded_file.name, uploaded_file, uploaded_file.content_type)
    }
    async with aiohttp.request('post', url, data=test_form_data) as response:
        return await response.text()

Key notes for the test code:

  • We're using the InMemoryUploadedFile instance directly in the tuple, along with its built-in name and content_type attributes.
  • We extract a clean filename from the path instead of passing the full path, which matches real-world upload behavior.
  • Make sure your pytest setup uses pytest-asyncio to handle async test functions properly.

内容的提问来源于stack exchange,提问作者lee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:05:24