2011-03-23 64 views
2

我正在使用django-storages来保存上传到S3的图像,并且我想创建一个自定义表单域,以便在编辑时显示图像以及更改它的选项。在自定义Django ImageField表单字段中访问实例值的DRY方法?

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

Settings.py:

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

models.py:

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

我没有看到我怎么可以访问mymod.my_image:

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

访问完整的URL的示例.url()从一个自定义的Widget中(我将render()'如下所示:

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) 

更新:
我正在寻找一个DRY的办法处理这一问题。我很抱歉没有从一开始就澄清这一点

+0

我仍然在寻找干这个问题的方法。 Django存储和/或Django不是一个小改动来支持我想要做的事情吗? – 2011-04-02 21:10:14

回答

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) 
+0

这种方法的问题是它需要使用小部件来传递这些信息的所有形式。我希望Django有一些魔术挂钩来做到这一点,但显然不是 – 2011-03-30 06:06:39

+0

对不起,当我第一次看到你的评论我认为你的意思是所有的表单类将需要必须覆盖小部件。我不知道你只关心实例级别。编辑应该给你你正在寻找的东西。 – DTing 2011-04-09 10:17:25

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) 

self.instance应该提供访问模型,只要创建的ModelForm时,它已经被设置。

+0

抱歉,因为答复滞后;我试过你的上面的代码,但得到消息,'自我'没有定义。如果像这样的东西可以工作,这正是我所需要的 – 2011-04-09 02:35:23

+0

@dolan这会教我不测试我的答案...... Kriegar先到达那里,他的编辑使用init来访问实例 – Chris 2011-04-09 11:43:11

相关问题