सवाल आप एक पीआईएल `छवि` को Django` फ़ाइल` में कैसे परिवर्तित करते हैं?


मैं एक कन्वर्ट करने की कोशिश कर रहा हूँ UploadedFile एक पीआईएल के लिए Image इसे थंबनेल करने के लिए ऑब्जेक्ट करें, और उसके बाद पीआईएल को परिवर्तित करें Image ऑब्जेक्ट करें कि मेरा थंबनेल फ़ंक्शन वापस लौटाता है File वस्तु। मैं यह कैसे कर सकता हूँ?


44
2017-09-16 02:07


मूल


Django फ़ाइल के लिए छवि? - Ankit Jaiswal
@andand एक पीआईएल Image एक Django के लिए उदाहरण File उदाहरण। Django के File पायथन के उप-वर्ग है File कक्षा। - orokusaki
पाइथन 3 समाधान यहाँ stackoverflow.com/a/30435175/3033586 - madzohan


जवाब:


फ़ाइल सिस्टम पर वापस लिखने के बिना ऐसा करने का तरीका, और फिर फ़ाइल को खुले कॉल के माध्यम से स्मृति में वापस लाएं, स्ट्रिंगियो और Django InMemoryUploadedFile का उपयोग करना है। यहां एक त्वरित नमूना है कि आप यह कैसे कर सकते हैं। यह मानता है कि आपके पास पहले से ही 'थंब' नामक एक थंबनेल छवि है:

import StringIO

from django.core.files.uploadedfile import InMemoryUploadedFile

# Create a file-like object to write thumb data (thumb data previously created
# using PIL, and stored in variable 'thumb')
thumb_io = StringIO.StringIO()
thumb.save(thumb_io, format='JPEG')

# Create a new Django file-like object to be used in models as ImageField using
# InMemoryUploadedFile.  If you look at the source in Django, a
# SimpleUploadedFile is essentially instantiated similarly to what is shown here
thumb_file = InMemoryUploadedFile(thumb_io, None, 'foo.jpg', 'image/jpeg',
                                  thumb_io.len, None)

# Once you have a Django file-like object, you may assign it to your ImageField
# and save.
...

अगर आपको और स्पष्टीकरण की आवश्यकता है तो मुझे बताएं। मेरे पास यह अभी मेरी परियोजना में काम कर रहा है, django-storages का उपयोग कर S3 पर अपलोड कर रहा है। इसने समाधान को ठीक से ढूंढने के लिए मुझे एक दिन का बेहतर हिस्सा लिया।


91
2017-12-28 07:55



अच्छा और सरल Pre_save सिग्नल में बेकार ढंग से काम करना। - jmagnusson
मैंने पाया है कि आप इसके बजाय Django ContentFile क्लास का उपयोग कर काम की मात्रा को और भी कम कर सकते हैं। उस स्थिति में, django.core.files.base से ContentFile आयात करें और फिर आप करेंगे: thumb_file = ContentFile (thumb_io.getvalue ()) - Bialecki
@ बायालेकी ने कभी नहीं, मुझे जवाब मिला। मॉडल इमेजफील्ड को सहेजते समय हम नाम असाइन करते हैं: mymodel.myimagefield.save (myfilename, imagecontentfile, save = True) - Akseli Palén
@madzohan आप कैसे मिला StringIO पायथन 3 में काम करने के लिए? मुझे उपयोग करना पड़ा BytesIO (और चूंकि इसमें कोई नहीं है लेन () समारोह का उपयोग करना था कहना() इसकी लंबाई निर्धारित करने के लिए। - John C
@ जोहान सी आपको उपयोग करना चाहिए BytesIO यहां मेरा जवाब आज़माएं stackoverflow.com/a/30435175/3033586 बीटीडब्ल्यू पिछली टिप्पणी पुरानी और हटा दी गई थी - madzohan


मुझे इसे कुछ चरणों में करना पड़ा है, php में imagejpeg () को एक समान प्रक्रिया की आवश्यकता है। यह नहीं कहना है कि चीजों को स्मृति में रखने का कोई तरीका नहीं है, लेकिन यह विधि आपको मूल छवि और अंगूठे दोनों के लिए एक फ़ाइल संदर्भ देता है (आमतौर पर आपको वापस जाना होगा और अपना अंगूठा आकार बदलना होगा)।

  1. फ़ाइल सहेजें
  2. पीआईएल के साथ फाइल सिस्टम से इसे खोलें,
  3. पीआईएल के साथ एक अस्थायी निर्देशिका में सहेजें,
  4. फिर काम करने के लिए एक Django फ़ाइल के रूप में खोलें।

आदर्श:

class YourModel(Model):
    img = models.ImageField(upload_to='photos')
    thumb = models.ImageField(upload_to='thumbs')

उपयोग:

#in upload code
uploaded = request.FILES['photo']
from django.core.files.base import ContentFile
file_content = ContentFile(uploaded.read())
new_file = YourModel() 
#1 - get it into the DB and file system so we know the real path
new_file.img.save(str(new_file.id) + '.jpg', file_content)
new_file.save()

from PIL import Image
import os.path

#2, open it from the location django stuck it
thumb = Image.open(new_file.img.path)
thumb.thumbnail(100, 100)

#make tmp filename based on id of the model
filename = str(new_file.id)

#3. save the thumbnail to a temp dir

temp_image = open(os.path.join('/tmp',filename), 'w')
thumb.save(temp_image, 'JPEG')

#4. read the temp file back into a File
from django.core.files import File
thumb_data = open(os.path.join('/tmp',filename), 'r')
thumb_file = File(thumb_data)

new_file.thumb.save(str(new_file.id) + '.jpg', thumb_file)

12
2017-09-16 02:53



अत्यधिक अप्रत्याशित, आप चरण 1,2,3,4 में आईओ संचालन कर रहे हैं। - Srikar Appalaraju


यह वास्तविक कामकाजी उदाहरण है पायथन 3.5 तथा django 1.10

views में:

from io import BytesIO
from django.core.files.base import ContentFile
from django.core.files.uploadedfile import InMemoryUploadedFile

def pill(image_io):
    im = Image.open(image_io)
    ltrb_border = (0, 0, 0, 10)
    im_with_border = ImageOps.expand(im, border=ltrb_border, fill='white')

    buffer = BytesIO()
    im_with_border.save(fp=buffer, format='JPEG')
    buff_val = buffer.getvalue()
    return ContentFile(buff_val)

def save_img(request)
    if request.POST:
       new_record = AddNewRecordForm(request.POST, request.FILES)
       pillow_image = pill(request.FILES['image'])
       image_file = InMemoryUploadedFile(pillow_image, None, 'foo.jpg', 'image/jpeg', pillow_image.tell, None)
       request.FILES['image'] = image_file  # really need rewrite img in POST for success form validation
       new_record.image = request.FILES['image']
       new_record.save()
       return redirect(...)

3
2017-09-26 18:41





पायथन 3+ के लिए टिप्पणियां और अपडेट एकत्र करना

from io import BytesIO
from django.core.files.base import ContentFile
import requests

# Read a file in

r = request.get(image_url)
image = r.content
scr = Image.open(BytesIO(image))

# Perform an image operation like resize:

width, height = scr.size
new_width = 320
new_height = int(new_width * height / width)
img = scr.resize((new_width, new_height))

# Get the Django file object

thumb_io = BytesIO()
img.save(thumb_io, format='JPEG')
photo_smaller = ContentFile(thumb_io.getvalue())

2
2018-03-16 23:05





यहां एक ऐप है जो ऐसा कर सकता है: Django-smartfields

from django.db import models

from smartfields import fields
from smartfields.dependencies import FileDependency
from smartfields.processors import ImageProcessor

class ImageModel(models.Model):
    image = fields.ImageField(dependencies=[
        FileDependency(processor=ImageProcessor(
            scale={'max_width': 150, 'max_height': 150}))
    ])

पास करना सुनिश्चित करें keep_orphans=True क्षेत्र में, यदि आप पुरानी फाइलें रखना चाहते हैं, अन्यथा वे प्रतिस्थापन पर साफ हो जाते हैं।


1
2018-01-31 19:52



उत्कृष्ट धन्यवाद। यह वास्तव में महान है। - orokusaki


उपयोग करने वालों के लिए django-storages/-redux एस 3 पर छवि फ़ाइल को स्टोर करने के लिए, यहां मैंने जो रास्ता लिया है (नीचे दिया गया उदाहरण किसी मौजूदा छवि का थंबनेल बनाता है):

from PIL import Image
import StringIO
from django.core.files.storage import default_storage

try:
    # example 1: use a local file
    image = Image.open('my_image.jpg')
    # example 2: use a model's ImageField
    image = Image.open(my_model_instance.image_field)
    image.thumbnail((300, 200))
except IOError:
    pass  # handle exception

thumb_buffer = StringIO.StringIO()
image.save(thumb_buffer, format=image.format)
s3_thumb = default_storage.open('my_new_300x200_image.jpg', 'w')
s3_thumb.write(thumb_buffer.getvalue())
s3_thumb.close()

1
2018-03-05 03:30