2011-03-23 65 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

相關問題