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

时间:2022-04-17 15:55:17

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.

自我。实例应该提供对模型的访问,只要在创建模型表单时设置了模型。