প্রোগ্রামালিভাবে জ্যাঙ্গো ইমেজফিল্ডে চিত্র সংরক্ষণ করা হচ্ছে


203

ঠিক আছে, আমি প্রায় সব কিছুর চেষ্টা করেছি এবং আমি এটি কাজ করতে পারি না।

  • আমার কাছে একটি ইমেজফিল্ড সহ একটি জ্যাঙ্গো মডেল রয়েছে
  • আমার কাছে এমন কোড রয়েছে যা এইচটিটিপি এর মাধ্যমে একটি চিত্র ডাউনলোড করে (পরীক্ষিত এবং কাজ করে)
  • চিত্রটি সরাসরি 'আপলোড_ টু' ফোল্ডারে সংরক্ষিত হয় (চিত্র আপলোডে আপলোড_ যা সেটাকে সেট করা থাকে)
  • আমাকে যা করতে হবে তা হ'ল ইমেজফিল্ডের সাথে ইতিমধ্যে বিদ্যমান চিত্র ফাইলের পথটি সংযুক্ত করা

আমি এই কোডটি প্রায় 6 টি বিভিন্ন উপায়ে লিখেছি।

আমি যে সমস্যাটি নিয়ে চলছি সেগুলি হ'ল আমি নিম্নলিখিত আচরণের ফলাফল লিখছি: (1) জাঙ্গো একটি 2 য় ফাইল তৈরি করবে, (2) নতুন ফাইলটির নাম পরিবর্তন করে, ফাইলের শেষে একটি _ যুক্ত করবে নাম, তারপরে (3) মূলত একটি খালি পুনরায় নামকরণ করা ফাইল রেখে কোনও ডেটা স্থানান্তর করবেন না। 'আপলোড_পথ' পাথের মধ্যে যা আছে তা 2 টি ফাইল যা প্রকৃত চিত্র এবং একটি যা চিত্রটির নাম, তবে খালি, এবং অবশ্যই ইমেজফিল্ড পথটি ফাঁকা ফাইলটিতে সেট করা আছে যা জাঙ্গো তৈরি করতে চেষ্টা করে ।

যদি বিষয়টি অস্পষ্ট ছিল, আমি উদাহরণ দেওয়ার চেষ্টা করব:

## Image generation code runs.... 
/Upload
     generated_image.jpg     4kb

## Attempt to set the ImageField path...
/Upload
     generated_image.jpg     4kb
     generated_image_.jpg    0kb

ImageField.Path = /Upload/generated_image_.jpg

জ্যাঙ্গো ফাইলটি পুনরায় সঞ্চয় করার চেষ্টা না করে আমি কীভাবে এটি করতে পারি? আমি আসলে যা চাই তা হ'ল এই প্রভাবটির ...

model.ImageField.path = generated_image_path

... তবে অবশ্যই এটি কাজ করে না।

এবং হ্যাঁ আমি অন্য কোন প্রশ্ন এখানে মাধ্যমে সর্বস্বান্ত করেছি এই এক সেইসাথে উপর জ্যাঙ্গো ডক ফাইল

আপডেট আরও পরীক্ষার পরে, উইন্ডোজ সার্ভারে অ্যাপাচের অধীনে চলার সময় এটি কেবল এই আচরণ করে। এক্সপি-তে 'চালক' এর অধীনে চলার সময় এটি এই আচরণটি চালায় না।

আমি স্ট্যাম্পড

এখানে কোড যা এক্সপিতে সাফল্যের সাথে চলে ...

f = open(thumb_path, 'r')
model.thumbnail = File(f)
model.save()

আর একটি দুর্দান্ত জ্যাঙ্গো প্রশ্ন। কোনও সমস্যা ছাড়াই এই সমস্যাটি সমাধান করার জন্য আমি বেশ কয়েকটি প্রচেষ্টা করেছি। আপলোড ডিরেক্টরিতে নির্মিত ফাইলগুলি ভাঙা হয়েছে এবং মূলগুলির তুলনায় আকারের একটি ভগ্নাংশ (অন্য কোথাও সঞ্চিত)।
ওয়েস্টমার্ক

আপনার আপডেট আপডেট হয় না
Amiadadimi

উত্তর:


166

আমার কিছু কোড রয়েছে যা ওয়েব থেকে একটি চিত্র আনবে এবং এটিকে একটি মডেলে সঞ্চয় করে। গুরুত্বপূর্ণ বিটগুলি হ'ল:

from django.core.files import File  # you need this somewhere
import urllib


# The following actually resides in a method of my model

result = urllib.urlretrieve(image_url) # image_url is a URL to an image

# self.photo is the ImageField
self.photo.save(
    os.path.basename(self.url),
    File(open(result[0], 'rb'))
    )

self.save()

এটি কিছুটা বিভ্রান্তিকর কারণ এটি আমার মডেল থেকে বেরিয়ে এসেছে এবং কিছুটা প্রসঙ্গের বাইরে, তবে গুরুত্বপূর্ণ অংশগুলি হ'ল:

  • ওয়েব থেকে টানা চিত্রটি আপলোড_ ফোল্ডারে সংরক্ষণ করা হয় না , এটি পরিবর্তে urllib.urlretrieve () দ্বারা একটি টেম্পাইল হিসাবে সংরক্ষণ করা হয় এবং পরে বাতিল করা হয়।
  • ইমেজফিল্ড.সেভ () পদ্ধতিতে একটি ফাইলের নাম (os.path.basename বিট) এবং একটি django.core.files.File বস্তু লাগে।

আপনার যদি প্রশ্ন থাকে বা আপনাকে স্পষ্টকরণের প্রয়োজন হয় তবে আমাকে জানান।

সম্পাদনা করুন: স্বচ্ছতার জন্য, এখানে মডেলটি দেওয়া হয়েছে (কোনও প্রয়োজনীয় আমদানির বিবরণ বিয়োগ):

class CachedImage(models.Model):
    url = models.CharField(max_length=255, unique=True)
    photo = models.ImageField(upload_to=photo_path, blank=True)

    def cache(self):
        """Store image locally if we have a URL"""

        if self.url and not self.photo:
            result = urllib.urlretrieve(self.url)
            self.photo.save(
                    os.path.basename(self.url),
                    File(open(result[0], 'rb'))
                    )
            self.save()

2
টিভিন - আমি এই প্রভাবটির জন্য কিছু চেষ্টা করেছি, তবে সম্ভবত আমি এটিকে আবারও দেব, আসলে আমার কোড ছিল যা এর সাথে খুব মিল ছিল। (এটি প্রসঙ্গের বাইরে থাকলেও আমি দেখতে পাচ্ছি এটি কীভাবে কাজ করে)।
টি। স্টোন

2
আমি চিত্রের সাথে ইউআরএল পরামিতার গানক এড়াতে url পার্স ব্যবহার করার পরামর্শ দিই suggest import urlparseos.path.basename(urlparse.urlparse(self.url).path)। পোস্টের জন্য ধন্যবাদ, সহায়ক ছিল।
dennmat

1
আমি django.core.exception.SuspiciousOperation পেয়েছি: '/images/10.jpg' এ প্রবেশ করার চেষ্টা করা অস্বীকার করেছে।
ডেটাগ্রিড

2
@ ডেটাগ্রিড আপনার মডেলটিতে আপলোড_-এর সংজ্ঞা থেকে ফরোয়ার্ড স্ল্যাশ '/' মুছে ফেলা উচিত। এটি এখানে সম্বোধন করা হয়েছিল ।
tsikov

আমি এর মতো ত্রুটি পাচ্ছি:prohibited to prevent data loss due to unsaved related object 'stream'.
দীপক

95

মডেলটি এখনও তৈরি না করা হলে খুব সহজ:

প্রথমে আপনার চিত্র ফাইলটি আপলোডের পথে অনুলিপি করুন ( নিম্নলিখিত স্নিপেটে ধরে নেওয়া = 'পাথ /' )।

দ্বিতীয়ত : এর মতো কিছু ব্যবহার করুন:

class Layout(models.Model):
    image = models.ImageField('img', upload_to='path/')

layout = Layout()
layout.image = "path/image.png"
layout.save()

পরীক্ষিত এবং django 1.4 এ কাজ করা, এটি কোনও বিদ্যমান মডেলের জন্যও কাজ করতে পারে।


10
এটি সঠিক উত্তর, আরও ভোট প্রয়োজন !!! এই সমাধানটি এখানেও পেয়েছি ।
অ্যান্ড্রু সুইহার্ট

ওহে. আমার একটা প্রশ্ন আছে. আমি অ্যামাজন এস 3 ব্যাকএন্ডের সাথে জাঙ্গো-স্টোরেজ ব্যবহার করছি। এটি কি নতুন আপলোড ট্রিগার করবে?
সালভাতোর Iovene

ওপিকে "জ্যাঙ্গো না করেই ফাইলটি পুনরায় সঞ্চয় করার চেষ্টা করুন" জিজ্ঞাসা করলেন, এবং এটিই তার উত্তর!
frnhr

2
ডিস্কে নকল ফাইলের নামগুলির জন্য অ্যাকাউন্টে জ্যাঙ্গোর কিছু বিদ্যমান যুক্তি রয়েছে। এই পদ্ধতিটি ক্লোবারগুলি যে যুক্তিযুক্ত কারণ ব্যবহারকারী ফাইলনাম সদৃশ পরীক্ষা করতে বাকি আছে।
ক্রিস কনলান

1
@ কনলান: ফাইলের নামের জন্য একটি নির্দেশিকা যুক্ত করুন।
রবিহ কোডেহ

41

শুধু একটু মন্তব্য। tvon উত্তর কাজ করে তবে, আপনি উইন্ডোতে কাজ করছেন, আপনি সম্ভবত open()ফাইলটি করতে চান 'rb'। এটার মত:

class CachedImage(models.Model):
    url = models.CharField(max_length=255, unique=True)
    photo = models.ImageField(upload_to=photo_path, blank=True)

    def cache(self):
        """Store image locally if we have a URL"""

        if self.url and not self.photo:
            result = urllib.urlretrieve(self.url)
            self.photo.save(
                    os.path.basename(self.url),
                    File(open(result[0], 'rb'))
                    )
            self.save()

অথবা আপনি প্রথম 0x1Aবাইটে আপনার ফাইলটি কেটে ফেলবেন।


1
ধন্যবাদ, আমি এ জাতীয় নিম্ন-স্তরের বিশদগুলি আমাদের ভুলে যাচ্ছি।
মাইক_কে

fml ... যখন প্যারামিটারটি একটি লিনাক্স মেশিনে প্রবেশ করা হয় তখন কী হয়?
ডিএমএকে সর্বনাশকারী

1
আমার নিজের প্রশ্নের উত্তর দিয়েছেন ... স্প্যামের জন্য দুঃখিত। এখানে এর জন্য কিছু ডকুমেন্টেশন পেয়েছি । "ইউনিক্সে, মোডে 'বি' যুক্ত করতে ক্ষতি হয় না, তাই আপনি সমস্ত বাইনারি ফাইলগুলির জন্য প্ল্যাটফর্ম-স্বতন্ত্রভাবে এটি ব্যবহার করতে পারেন।"
ডিএম্যাক ডেস্ট্রয়ার

16

এখানে একটি পদ্ধতি যা ভালভাবে কাজ করে এবং আপনাকে ফাইলটিকে একটি নির্দিষ্ট বিন্যাসেও রূপান্তর করতে দেয় ("JPEG হিসাবে মোড P লিখতে পারে না" এড়াতে):

import urllib2
from django.core.files.base import ContentFile
from PIL import Image
from StringIO import StringIO

def download_image(name, image, url):
    input_file = StringIO(urllib2.urlopen(url).read())
    output_file = StringIO()
    img = Image.open(input_file)
    if img.mode != "RGB":
        img = img.convert("RGB")
    img.save(output_file, "JPEG")
    image.save(name+".jpg", ContentFile(output_file.getvalue()), save=False)

যেখানে চিত্রটি জাঙ্গো ইমেজফিল্ড বা আপনার_মোডেল_ইনস্ট্যান্স। চিত্রটি এখানে ব্যবহারের উদাহরণ:

p = ProfilePhoto(user=user)
download_image(str(user.id), p.image, image_url)
p.save()

আশাকরি এটা সাহায্য করবে


12

ঠিক আছে, যদি আপনাকে যা করতে হবে তবে ইমেজফিল্ডের সাথে ইতিমধ্যে বিদ্যমান চিত্র ফাইলের পথটি সংযুক্ত করা হয়, তবে এই সমাধানটি সহায়ক হতে পারে:

from django.core.files.base import ContentFile

with open('/path/to/already/existing/file') as f:
  data = f.read()

# obj.image is the ImageField
obj.image.save('imgfilename.jpg', ContentFile(data))

ঠিক আছে, যদি আন্তরিক হয়ে থাকে তবে ইতিমধ্যে বিদ্যমান চিত্র ফাইলটি চিত্রফিল্ডের সাথে সম্পর্কিত হবে না, তবে এই ফাইলটির অনুলিপি 'imgfilename.jpg' হিসাবে upload_to dir এ তৈরি হবে এবং চিত্রফিল্ডের সাথে যুক্ত হবে।


2
আপনি কি বাইনারি ফাইল হিসাবে এটি খুলছেন না?
মারিউজ জামরো

ঠিক যেমন @ মারিউসজামরো বলেছিলেন, এটি এর মতো হওয়া উচিত:with open('/path/to/already/existing/file', 'rb') as f:
রাহমটনেস

এছাড়াও অবজেক্টটি সংরক্ষণ করতে ভুলবেন না:obj.save()
রাহমটনেস

11

আমি যা করেছি তা হ'ল আমার নিজের স্টোরেজ তৈরি করা যা কেবল ফাইলটি ডিস্কে সংরক্ষণ করবে না:

from django.core.files.storage import FileSystemStorage

class CustomStorage(FileSystemStorage):

    def _open(self, name, mode='rb'):
        return File(open(self.path(name), mode))

    def _save(self, name, content):
        # here, you should implement how the file is to be saved
        # like on other machines or something, and return the name of the file.
        # In our case, we just return the name, and disable any kind of save
        return name

    def get_available_name(self, name):
        return name

তারপরে, আমার মডেলগুলিতে, আমার ইমেজফিল্ডের জন্য, আমি নতুন কাস্টম স্টোরেজটি ব্যবহার করেছি:

from custom_storage import CustomStorage

custom_store = CustomStorage()

class Image(models.Model):
    thumb = models.ImageField(storage=custom_store, upload_to='/some/path')

7

আপনি যদি লোডিংয়ের ওভারহেড ব্যয় না করে ফাইলটি (!!) পুনরায় সংরক্ষণ না করে, বা চার্ফিল্ড (!!!) ব্যবহার করে অবলম্বন না করেই প্রকৃত ফাইলের নামটি "সেট" করতে চান, আপনি এই জাতীয় কিছু চেষ্টা করতে চাইতে পারেন - -

model_instance.myfile = model_instance.myfile.field.attr_class(model_instance, model_instance.myfile.field, 'my-filename.jpg')

এটি আপনার Model_instance.myfile.url এবং তাদের সমস্তকে ঠিক ঠিক এমনভাবে আলোকিত করবে যে আপনি আসলে ফাইলটি আপলোড করেছেন।

@ টি-স্টোনর মতো, যা আমরা সত্যই চাই, তা উদাহরণস্বরূপ সেট করতে সক্ষম হ'ল।


মডেল_ইনস্ট্যান্স যদি সেই মডেলের উদাহরণ থাকে যা এতে ফাইল থাকে .. অন্য "দৃষ্টান্ত" কী দাঁড়ায় ??
এইচ 3।

7

আমার মতে এটির সহজ সমাধান:

from django.core.files import File

with open('path_to_file', 'r') as f:   # use 'rb' mode for python3
    data = File(f)
    model.image.save('filename', data, True)

3

এই উত্তরগুলির অনেকগুলি পুরানো ছিল, এবং হতাশায় আমি বেশ কয়েক ঘন্টা কাটিয়েছি (আমি জাজানো এবং সাধারণভাবে ওয়েব দেবের পক্ষে মোটামুটি নতুন)। যাইহোক, আমি এই চমত্কার সূচনাটি পেয়ে গেছি @iambibhas দ্বারা: https://gist.github.com/iambibhas/5051911

import requests

from django.core.files import File
from django.core.files.temp import NamedTemporaryFile


def save_image_from_url(model, url):
    r = requests.get(url)

    img_temp = NamedTemporaryFile(delete=True)
    img_temp.write(r.content)
    img_temp.flush()

    model.image.save("image.jpg", File(img_temp), save=True)

2

আপনি যে উত্তরটি খুঁজছেন তা এটি নাও হতে পারে। তবে আপনি চিত্রফলকের পরিবর্তে ফাইলের পাথ সংরক্ষণ করতে চারফিল্ডটি ব্যবহার করতে পারেন। এই পদ্ধতিতে আপনি ফাইলটি পুনরায় তৈরি না করে প্রোগ্রামযুক্তভাবে আপলোড করা চিত্র ফিল্ডের সাথে যুক্ত করতে পারেন।


হ্যাঁ, আমি এটি ছেড়ে দিতে প্রলুব্ধ হয়েছিলাম, এবং হয় সরাসরি মাইএসকিউএল-এ লিখি, বা কেবল একটি চারফিল্ড () ব্যবহার করুন।
টি। স্টোন


1
class tweet_photos(models.Model):
upload_path='absolute path'
image=models.ImageField(upload_to=upload_path)
image_url = models.URLField(null=True, blank=True)
def save(self, *args, **kwargs):
    if self.image_url:
        import urllib, os
        from urlparse import urlparse
        file_save_dir = self.upload_path
        filename = urlparse(self.image_url).path.split('/')[-1]
        urllib.urlretrieve(self.image_url, os.path.join(file_save_dir, filename))
        self.image = os.path.join(file_save_dir, filename)
        self.image_url = ''
    super(tweet_photos, self).save()

1
class Pin(models.Model):
    """Pin Class"""
    image_link = models.CharField(max_length=255, null=True, blank=True)
    image = models.ImageField(upload_to='images/', blank=True)
    title = models.CharField(max_length=255, null=True, blank=True)
    source_name = models.CharField(max_length=255, null=True, blank=True)
    source_link = models.CharField(max_length=255, null=True, blank=True)
    description = models.TextField(null=True, blank=True)
    tags = models.ForeignKey(Tag, blank=True, null=True)

    def __unicode__(self):
        """Unicode class."""
        return unicode(self.image_link)

    def save(self, *args, **kwargs):
        """Store image locally if we have a URL"""
        if self.image_link and not self.image:
            result = urllib.urlretrieve(self.image_link)
            self.image.save(os.path.basename(self.image_link), File(open(result[0], 'r')))
            self.save()
            super(Pin, self).save()

1

কাজ! আপনি ফাইলসিসটেম স্টোরেজ ব্যবহার করে চিত্রটি সংরক্ষণ করতে পারেন। নীচের উদাহরণ পরীক্ষা করুন

def upload_pic(request):
if request.method == 'POST' and request.FILES['photo']:
    photo = request.FILES['photo']
    name = request.FILES['photo'].name
    fs = FileSystemStorage()
##### you can update file saving location too by adding line below #####
    fs.base_location = fs.base_location+'/company_coverphotos'
##################
    filename = fs.save(name, photo)
    uploaded_file_url = fs.url(filename)+'/company_coverphotos'
    Profile.objects.filter(user=request.user).update(photo=photo)

আপনাকে নিডস ধন্যবাদ, একেবারে এই সমাধান কাজ করে! আপনি আমার অনেক সময় বাঁচিয়েছেন :)
মেহমেট বুড়াক ইবিস

0

তোমার ব্যবহার করতে পারেন জ্যাঙ্গো বিশ্রাম ফ্রেমওয়ার্ক এবং পাইথন অনুরোধ জ্যাঙ্গো ImageField ছবিতে সংরক্ষণ প্রোগ্রামেটিক্যালি করার গ্রন্থাগার

এখানে একটি উদাহরণ:

import requests


def upload_image():
    # PATH TO DJANGO REST API
    url = "http://127.0.0.1:8080/api/gallery/"

    # MODEL FIELDS DATA
    data = {'first_name': "Rajiv", 'last_name': "Sharma"}

    #  UPLOAD FILES THROUGH REST API
    photo = open('/path/to/photo'), 'rb')
    resume = open('/path/to/resume'), 'rb')
    files = {'photo': photo, 'resume': resume}

    request = requests.post(url, data=data, files=files)
    print(request.status_code, request.reason) 

0

জ্যাঙ্গো 3 এর সাথে মডেল যেমন:

class Item(models.Model):
   name = models.CharField(max_length=255, unique=True)
   photo= models.ImageField(upload_to='image_folder/', blank=True)

ছবিটি ইতিমধ্যে আপলোড করা থাকলে, আমরা সরাসরি করতে পারি:

Item.objects.filter(...).update(photo='image_folder/sample_photo.png')

অথবা

my_item = Item.objects.get(id=5)
my_item.photo='image_folder/sample_photo.png'
my_item.save()
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.