DRY方法访问自定义Django ImageField表单字段中的实例值?

时间:2011-03-23 00:38:32

标签: python django

我正在使用django-storages来保存上传到S3的图片,我想创建一个自定义表单字段,该字段将在编辑时显示图像,以及更改它的选项。

我遇到的问题是存储在我的数据库中的路径值不是图像的完整路径,因为django-storages会生成完整路径。

Settings.py:

DEFAULT_FILE_STORAGE = 'storages.backends.s3boto.S3BotoStorage'
AWS_STORAGE_BUCKET_NAME = 'myBucketName'
AWS_LOCATION = 'mySubBucketName'

models.py:

class MyModel(models.Model):
    my_image = ImageField(upload_to='upload/path')

访问完整网址的示例:

>>> 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

我没有看到我如何从一个自定义Widget中访问mymod.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)

更新
我正在寻找干这个问题的方法。对于从一开始就没有澄清这一点我表示歉意

2 个答案:

答案 0 :(得分:2)

我认为覆盖自定义小部件中的__init__并传入您的网址就可以了。

修改

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)

答案 1 :(得分:0)

如果您使用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}),
        }

所以在你的情况下可能是:

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)
只要在创建ModelForm时设置了模型,

self.instance就应该提供对模型的访问。