如何在Django表单中添加照片?

huangapple go评论72阅读模式
英文:

How can I resign Photo in Django Form

问题

我正在进行一个Django项目,我想要将图像大小减小到小于300KB,并将图像裁剪为1280px * 820px。目标是确保每上传的图像都是相同的,不管初始图像如何,任何最佳解决方案都将不胜感激。

下面是我尝试过的内容,但都没有起作用。

ALLOWED_EXTENSIONS = ('.gif', '.jpg', '.jpeg')

class PropertyForm(forms.ModelForm): 
    description = forms.CharField(label='Property Description:', max_length=60, widget=forms.TextInput(attrs={'placeholder': 'Briefly Describe your Property. E.g. Bedroom & Palour with Private Detached Bathroom'}))
    state = forms.ChoiceField(choices=Property.STATE_CHOICES, required=False)
    state_lga = forms.CharField(label='Local Govt. Area:', max_length=12, widget=forms.TextInput(attrs={'placeholder': 'Enter Local Govt. of Property.'}))
    address = forms.CharField(label='Property Address:', max_length=60, widget=forms.TextInput(attrs={'placeholder': 'Enter Street Name with Number and Town Name only.'}))

    class Meta:
        model = Property
        fields = ('description', 'address', 'country', 'state', 'state_lga', 'property_type', 'bedrooms', 'bathroom_type', 'price', 'is_available', 'image')

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['bedrooms'].required = False

    def clean_image(self):
        image = self.cleaned_data.get('image')

        if image:
            # Check if the image size exceeds 1MB
            if image.size > 1024 * 1024:  # 1MB in bytes
                # Open the image using Pillow
                with Image.open(image) as img:
                    # Reduce the image size while preserving the aspect ratio
                    max_width = 1920
                    max_height = 820
                    img.thumbnail((max_width, max_height), Image.ANTIALIAS)

                    # Save the modified image with reduced quality to achieve a smaller file size
                    buffer = BytesIO()
                    img.save(buffer, format='JPEG', optimize=True, quality=85)
                    while buffer.tell() > 1024 * 1024:  # Check if file size exceeds 1MB
                        quality -= 5
                        if quality < 5:
                            break
                        buffer.seek(0)
                        buffer.truncate(0)
                        img.save(buffer, format='JPEG', optimize=True, quality=quality)

                    buffer.seek(0)
                    image.file = buffer

            # Check file extension for allowed formats
            allowed_formats = ['gif', 'jpeg', 'jpg']
            ext = image.name.split('.')[-1].lower()
            if ext not in allowed_formats:
                raise forms.ValidationError("Only GIF, JPEG, and JPG images are allowed.")
        else:
            raise forms.ValidationError("Please upload an image before submitting the form.")

        return image

希望这能帮助你。

英文:

I am working a Django project where I want to reduce the image size to be less than 300kb and crop the images to be 1280px 820px. The aim is to make sure every image uploaded is the same irrespective of the initial so any best solution would be appreciated.
Below is what I have tried but nothing works.

ALLOWED_EXTENSIONS = (&#39;.gif&#39;, &#39;.jpg&#39;, &#39;.jpeg&#39;)
class PropertyForm(forms.ModelForm): 
description = forms.CharField(label=&#39;Property Description:&#39;, max_length=60, widget=forms.TextInput(attrs={&#39;placeholder&#39;: &#39;Briefly Describe your Property. E.g. Bedroom &amp; Palour with Private Detached Bathroom&#39;}))
state = forms.ChoiceField(choices=Property.STATE_CHOICES, required=False)
state_lga = forms.CharField(label = &#39;Local Govt. Area:&#39;, max_length=12, widget=forms.TextInput(attrs={&#39;placeholder&#39;: &#39;Enter Local Govt. of Property.&#39;}))
address = forms.CharField(label = &#39;Property Address:&#39;, max_length=60, widget=forms.TextInput(attrs={&#39;placeholder&#39;: &#39;Enter Street Name with Number and Town Name only.&#39;}))
class Meta:
model = Property
fields = (&#39;description&#39;, &#39;address&#39;, &#39;country&#39;, &#39;state&#39;, &#39;state_lga&#39;, &#39;property_type&#39;, &#39;bedrooms&#39;, &#39;bathroom_type&#39;, &#39;price&#39;, &#39;is_available&#39;, &#39;image&#39;)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields[&#39;bedrooms&#39;].required = False
def clean_image(self):
image = self.cleaned_data.get(&#39;image&#39;)
if image:
# Check if the image size exceeds 1MB
if image.size &gt; 1024 * 1024:  # 1MB in bytes
# Open the image using Pillow
with Image.open(image) as img:
# Reduce the image size while preserving the aspect ratio
max_width = 1920
max_height = 820
img.thumbnail((max_width, max_height), Image.ANTIALIAS)
# Save the modified image with reduced quality to achieve a smaller file size
buffer = BytesIO()
img.save(buffer, format=&#39;JPEG&#39;, optimize=True, quality=85)
while buffer.tell() &gt; 1024 * 1024:  # Check if file size exceeds 1MB
quality -= 5
if quality &lt; 5:
break
buffer.seek(0)
buffer.truncate(0)
img.save(buffer, format=&#39;JPEG&#39;, optimize=True, quality=quality)
buffer.seek(0)
image.file = buffer
# Check file extension for allowed formats
allowed_formats = [&#39;gif&#39;, &#39;jpeg&#39;, &#39;jpg&#39;]
ext = image.name.split(&#39;.&#39;)[-1].lower()
if ext not in allowed_formats:
raise forms.ValidationError(&quot;Only GIF, JPEG, and JPG images are allowed.&quot;)
else:
raise forms.ValidationError(&quot;Please upload an image before submitting the form.&quot;)
return image

答案1

得分: 0

你可以使用第三方库来处理你想要存档的所有图像相关工作,这样肯定可以使用pypi库。它非常直观和易于使用。

链接在这里

英文:

If you want to use third party library for handling all stuff of image which you want archive then definitely you can use pypi library. It's very straight forward and easy to use

Link here

答案2

得分: 0

#Models.py

从PIL导入Image

class Property(models.Model):
...
image = models.ImageField(upload_to='properties_image/')
...

def save(self, *args, **kwargs):
super().save(*args, **kwargs)
this_image = Image.open(self.image.path)
width, height = this_image.size
TARGET_WIDTH = 1280
new_height = 820
this_image = this_image.resize((TARGET_WIDTH, new_height), Image.ANTIALIAS)
this_image.save(self.image.path, quality=50)
英文:

One way I can think of is to use PIL. The Code snippet below makes use of Models instead of forms but should do the trick

#Models.py
from PIL import Image
class Property(models.Model):
...
image = models.ImageField(upload_to=&#39;properties_image/&#39;)
...
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
this_image = Image.open(self.image.path)
width, height = this_image.size
TARGET_WIDTH = 1280
new_height = 820
this_image = this_image.resize(TARGET_WIDTH,new_height),Image.ANTIALIAS)
this_image.save(self.image.path,quality=50)

huangapple
  • 本文由 发表于 2023年6月15日 18:59:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/76481803.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定