Django中用Celery生成缩放图片遇JSON序列化错误求助
Hey there, let's sort out this error you're hitting. You nailed the root cause already—passing the full InMemoryUploadedFile object from your form to the Celery task won't work because Celery relies on JSON serialization for task arguments, and that file object can't be converted to JSON.
Here's how to fix it step by step:
1. Pass the Saved File's Path Instead of the Form File Object
Since you're already saving the CompanyLogo instance to the database, you can use the relative path of the saved logo file (which is a plain string, fully JSON-serializable) instead of the temporary form upload object. Update your save_model method like this:
def save_model(self, request, obj, form, change): updated = change super().save_model(request, obj, form, change) if not updated: logo = CompanyLogo(logo=form.cleaned_data['logo'], company=obj) logo.save() # Use the saved logo's relative path (not the form's file object) task_company_logo.delay(logo.logo.name)
2. Verify Your Crop Function Works with the Path
Your existing crop_image function already joins settings.MEDIA_ROOT with the input path, which pairs perfectly with logo.logo.name (this gives the relative path under your media directory). If you haven't already, replace the placeholder image.show() with your actual resizing logic:
def crop_image(path): image_path = os.path.join(settings.MEDIA_ROOT, path) image = Image.open(image_path) # Example: Generate multiple scaled copies # Small size (200x200) small_size = (200, 200) small_image = image.resize(small_size) small_path = f"{os.path.splitext(path)[0]}_small{os.path.splitext(path)[1]}" small_image.save(os.path.join(settings.MEDIA_ROOT, small_path)) # Medium size (400x400) medium_size = (400, 400) medium_image = image.resize(medium_size) medium_path = f"{os.path.splitext(path)[0]}_medium{os.path.splitext(path)[1]}" medium_image.save(os.path.join(settings.MEDIA_ROOT, medium_path))
Quick Notes to Keep in Mind
- When you call
logo.save(), Django automatically writes the uploaded file to yourMEDIA_ROOTdirectory, so the path will exist when the Celery task runs. - If you're using a cloud storage backend (like AWS S3) instead of local files, adjust the logic to fetch the file via its storage key (still a serializable string) rather than a local filesystem path.
内容的提问来源于stack exchange,提问作者user3541631

