问题描述
我正在Django中创建一个动态表单(使用JSON格式),该表单需要使用Django Storage保存多个图像,并将对该文件的引用保存在JSON字段中。
这是我现在拥有的东西,它可以工作,但是确实很丑陋,Django已经做到了,我不知道如何重用相同的功能。
Stream valueStream = (Stream)value;
这实际上有效,它将数据保存到JSONField(结果),并将图像保存到本地文件系统存储。
如何改进使用Django Storage并使它变得简单?使用Django Class SomeModel(models.ModelForm):
results = JSONField()
class DynamicJsonForm(forms.ModelForm):
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
# ... Add dynamic fields to the form
self.extra = [] # Save the reference for the fields
class Meta:
model = SomeModel
exclude = ("results",)
def save(self,commit=True):
results = {}
for extra in self.extra:
value = self.cleaned_data.get(extra)
question = some_query.question
if "photo" in extra and value: # value = photo
filename,ext = value.name.split(".")
filename = "media/the/path/to/photos/{}_{}.{}".format(filename,uuid4().hex,ext)
uploaded_file = SimpleUploadedFile(filename,value.read(),value.content_type)
image = Image.open(uploaded_file)
if image.mode in ("RGBA","P"):
image = image.convert("RGB")
image.save(fp=filename)
results[question][extra] = filename
else:
results[question][extra] = value
self.instance.results = results
return super().save(commit)
似乎容易得多,但是我不能使用普通的Model.save()
,因为它需要动态
解决方法
我将FileSystemStorage
与forms.ImageField
混合在一起,虽然不是一个完美的解决方案,但是看起来更好。
fields.py
import os
from django import forms
from django.conf import settings
from django.core.files.storage import FileSystemStorage
class FormFileSystemStorageImageField(forms.ImageField,FileSystemStorage):
def __init__(self,location=None,*args,**kwargs):
super().__init__(*args,**kwargs) # Call ImageField __init__,I wonder how to call second parent's __init__
self._orig_location = location
self._location = os.path.join(settings.MEDIA_ROOT,location)
def storage_path(self,name):
return os.path.join(self._orig_location,name)
forms.py
from .fields import FormFileSystemStorageImageField
# ... Same as question code
def save(self,commit=True):
results = {}
for extra in self.extra:
value = self.cleaned_data.get(extra)
question = some_query.question
if "photo" in extra and value: # value = photo
image_field = self.fields.get(extra)
image_field.save(value.name,value)
results[question][extra] = image_field.storage_path(value.name)
else:
results[question][extra] = value
self.instance.results = results
return super().save(commit)