I'm using django-storages to save images uploaded to S3, and I want to create a custom form field that will display the image when editing, along with an option to change it.
我正在使用django存储保存上传至S3的图像,我想创建一个自定义表单字段,在编辑时显示图像,并提供一个选项来更改它。
The problem I'm running into is the path's value that is stored in my database is not the full path to the image, as django-storages does the generating of the full path.
我遇到的问题是,存储在我的数据库中的路径的值并不是图像的完整路径,因为django-storages可以生成完整的路径。
Settings.py:
Settings.py:
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto.S3BotoStorage'
AWS_STORAGE_BUCKET_NAME = 'myBucketName'
AWS_LOCATION = 'mySubBucketName'
models.py:
models.py:
class MyModel(models.Model):
my_image = ImageField(upload_to='upload/path')
Example of accessing full url:
访问完整url的示例:
>>> mymod = MyModel.objects.get(id=1)
>>> print mymod.my_image
upload/path/somefile.jpg
>>> print mymod.my_image.url
https://s3.amazonaws.com/myBucketName/mySubBucketName/upload/path/somefile.jpg
I am not seeing how I can access mymod.my_image.url() from within a custom Widget (where I would be render()'ing something like this:
我没有看到如何从自定义小部件中访问mymode .my_image.url()。
class ImageViewWidget(forms.Widget):
markup = """
<img src="%(imagepath)"/>
<input type="file" name="%(name)s"/>
"""
def render(self, name, value, attrs=None):
output = self.markup % {
"name": name,
"imagepath": "<<<< MAGIC CODE GOES HERE >>>>"
}
return mark_safe(output)
Update:
I'm looking for a DRY approach to this problem. My apologies for not clarifying this from the beginning
更新:我正在寻找一个解决这个问题的方法。我很抱歉从一开始就没有澄清这一点
2 个解决方案
#1
2
I think overriding the __init__
in your custom widget and passing in your url would do the trick.
我认为在自定义小部件中覆盖__init__并传入url将起到作用。
edit:
编辑:
class ImageViewWidget(forms.Widget):
def __init__(self, *args, **kwargs):
self.path = kwargs.pop('path', '')
super(ImageViewWidget, self).__init__(*args, **kwargs)
markup = """
<img src="%(imagepath)"/>
<input type="file" name="%(name)s"/>
"""
def render(self, name, value, attrs=None):
output = self.markup % {
"name": name,
"imagepath": self.path
}
return mark_safe(output)
class MyModelForm(ModelForm):
class Meta:
model = MyModel
def __init__(self, *args, **kwargs):
image_url = ''
if self.instance:
image_url = self.instance.my_image.url
super(MyModelForm, self).__init__(*args, **kwargs)
self.fields['my_image'].widget=ImageViewWidget(path=image_url)
#2
0
If you use a ModelForm to generate the form that is rendered using the widget you can have that pass the value to the widget, requires the code to be written once.
如果您使用一个ModelForm来生成使用小部件呈现的表单,您可以将其传递给小部件,需要编写一次代码。
from django.forms import ModelForm, Textarea
class AuthorForm(ModelForm):
class Meta:
model = Author
fields = ('name', 'title', 'birth_date')
widgets = {
'name': Textarea(attrs={'cols': 80, 'rows': 20}),
}
So in your case it might be:
所以在你的例子中可能是:
class MyModelForm(ModelForm):
class Meta:
model = MyModel
def __init__(self, *args, **kwargs):
image_url = ''
if self.instance:
image_url = self.instance.my_image.url
super(MyModelForm, self).__init__(*args, **kwargs)
self.fields['my_image'].widget=ImageViewWidget(path=image_url)
self.instance should provide access to the model as long as it has been set when creating the ModelForm.
自我。实例应该提供对模型的访问,只要在创建模型表单时设置了模型。
#1
2
I think overriding the __init__
in your custom widget and passing in your url would do the trick.
我认为在自定义小部件中覆盖__init__并传入url将起到作用。
edit:
编辑:
class ImageViewWidget(forms.Widget):
def __init__(self, *args, **kwargs):
self.path = kwargs.pop('path', '')
super(ImageViewWidget, self).__init__(*args, **kwargs)
markup = """
<img src="%(imagepath)"/>
<input type="file" name="%(name)s"/>
"""
def render(self, name, value, attrs=None):
output = self.markup % {
"name": name,
"imagepath": self.path
}
return mark_safe(output)
class MyModelForm(ModelForm):
class Meta:
model = MyModel
def __init__(self, *args, **kwargs):
image_url = ''
if self.instance:
image_url = self.instance.my_image.url
super(MyModelForm, self).__init__(*args, **kwargs)
self.fields['my_image'].widget=ImageViewWidget(path=image_url)
#2
0
If you use a ModelForm to generate the form that is rendered using the widget you can have that pass the value to the widget, requires the code to be written once.
如果您使用一个ModelForm来生成使用小部件呈现的表单,您可以将其传递给小部件,需要编写一次代码。
from django.forms import ModelForm, Textarea
class AuthorForm(ModelForm):
class Meta:
model = Author
fields = ('name', 'title', 'birth_date')
widgets = {
'name': Textarea(attrs={'cols': 80, 'rows': 20}),
}
So in your case it might be:
所以在你的例子中可能是:
class MyModelForm(ModelForm):
class Meta:
model = MyModel
def __init__(self, *args, **kwargs):
image_url = ''
if self.instance:
image_url = self.instance.my_image.url
super(MyModelForm, self).__init__(*args, **kwargs)
self.fields['my_image'].widget=ImageViewWidget(path=image_url)
self.instance should provide access to the model as long as it has been set when creating the ModelForm.
自我。实例应该提供对模型的访问,只要在创建模型表单时设置了模型。