Frage

Wie kann ich leicht ein Bild Größe ändern, nachdem es in Django hochgeladen wurde? Ich verwende Django 1.0.2 und ich habe PIL installiert.

Ich dachte über das Überschreiben die save () Methode des Modells es um die Größe, aber ich weiß wirklich nicht, wie es zu starten und außer Kraft setzen.

Kann mir jemand in die richtige Richtung? Danke: -)

@ Guðmundur H: Das wird nicht funktionieren, weil das django-stdimage Paket unter Windows funktioniert nicht: - (

War es hilfreich?

Lösung

Sie sollten eine Methode verwenden, die hochgeladene Datei zu handhaben, wie sie in der

Andere Tipps

Ich empfehle, mit StdImageField von django-stdimage , sollte es alle die schmutzige Arbeit für Sie erledigen . Es ist einfach zu bedienen, einfach die Dimensionen des skalierte Bildes in der Felddefinition angeben:

class MyModel(models.Model):
    image = StdImageField(upload_to='path/to/img',  size=(640, 480))

Überprüfen Sie die Dokumentation - es auch Thumbnails tun können,

.

Ich benutze diesen Code hochgeladene Bilder zu handhaben, die Größe ändern auf Speicher (whithout sie dauerhaft auf der Festplatte zu speichern) und dann den Daumen auf einem Django Imagefield zu speichern. Hoffe, dass helfen kann.

    def handle_uploaded_image(i):
        import StringIO
        from PIL import Image, ImageOps
        import os
        from django.core.files import File
        # read image from InMemoryUploadedFile
        image_str = “”
        for c in i.chunks():
            image_str += c

        # create PIL Image instance
        imagefile  = StringIO.StringIO(image_str)
        image = Image.open(imagefile)

        # if not RGB, convert
        if image.mode not in (“L”, “RGB”):
            image = image.convert(“RGB”)

        #define file output dimensions (ex 60x60)
        x = 130
        y = 130

        #get orginal image ratio
        img_ratio = float(image.size[0]) / image.size[1]

        # resize but constrain proportions?
        if x==0.0:
            x = y * img_ratio
        elif y==0.0:
            y = x / img_ratio

        # output file ratio
        resize_ratio = float(x) / y
        x = int(x); y = int(y)

        # get output with and height to do the first crop
        if(img_ratio > resize_ratio):
            output_width = x * image.size[1] / y
            output_height = image.size[1]
            originX = image.size[0] / 2 - output_width / 2
            originY = 0
        else:
            output_width = image.size[0]
            output_height = y * image.size[0] / x
            originX = 0
            originY = image.size[1] / 2 - output_height / 2

        #crop
        cropBox = (originX, originY, originX + output_width, originY + output_height)
        image = image.crop(cropBox)

        # resize (doing a thumb)
        image.thumbnail([x, y], Image.ANTIALIAS)

        # re-initialize imageFile and set a hash (unique filename)
        imagefile = StringIO.StringIO()
        filename = hashlib.md5(imagefile.getvalue()).hexdigest()+’.jpg’

        #save to disk
        imagefile = open(os.path.join(‘/tmp’,filename), ‘w’)
        image.save(imagefile,’JPEG’, quality=90)
        imagefile = open(os.path.join(‘/tmp’,filename), ‘r’)
        content = File(imagefile)

        return (filename, content)

#views.py

    form = YourModelForm(request.POST, request.FILES, instance=profile)
        if form.is_valid():
            ob = form.save(commit=False)
            try:
                t = handle_uploaded_image(request.FILES[‘icon’])
                ob.image.save(t[0],t[1])
            except KeyError:
                ob.save()

Ich empfehle den SORL-Thumbnail App für Bild Handhabung einfach und transparent Größe ändern. Es geht in jedem einzelnen Django Projekt, das ich starten.

Ich weiß, das ist alt, aber für jemand auf sie stolpern, es ist ein Paket, django-thumbs unter Django-Daumen - Easy leistungsstarke Thumbnails für Django integriert mit StorageBackend , die Sie Thumbnails in den Größen angeben, oder keine, wenn Sie nicht automatisch erzeugt. Anschließend rufen Sie das Miniaturbild, das Sie mit den Dimensionen wollen Sie wollen.

Zum Beispiel, wenn Sie ein Bild wollen Thumbnails von 64x64 haben und 128x128, importieren Sie einfach thumbs.models.ImageWithThumbsField, und es anstelle von ImageField verwenden. Fügen Sie einen Parameter sizes=((64,64),(128,128)) auf die Felddefinition, dann aus Ihrer Vorlage können Sie anrufen:

{{ ClassName.field_name.url_64x64 }}

und

{{ ClassName.field_name.url_128x128 }}

die Thumbnails angezeigt werden soll. Voila! Die ganze Arbeit ist für Sie in diesem Paket durchgeführt.

Hier ist eine komplette Lösung für ya ein Formular. Ich benutzte Admin-Ansichten für diese:

class MyInventoryItemForm(forms.ModelForm):

    class Meta:
        model = InventoryItem
        exclude = ['thumbnail', 'price', 'active']

    def clean_photo(self):
        import StringIO
        image_field = self.cleaned_data['photo']
        photo_new = StringIO.StringIO(image_field.read())

        try:
            from PIL import Image, ImageOps

        except ImportError:
            import Image
            import ImageOps

        image = Image.open(photo_new)

        # ImageOps compatible mode
        if image.mode not in ("L", "RGB"):
            image = image.convert("RGB")

        image.thumbnail((200, 200), Image.ANTIALIAS)

        image_file = StringIO.StringIO()
        image.save(image_file, 'png')

        image_field.file = image_file

        return image_field

Ihr Inventar Modell sieht wie folgt aus:

class InventoryItem(models.Model):

    class Meta:
        ordering = ['name']
        verbose_name_plural = "Items"

    def get_absolute_url(self):
        return "/products/{0}/".format(self.slug)

    def get_file_path(instance, filename):

        if InventoryItem.objects.filter(pk=instance.pk):
            cur_inventory = InventoryItem.objects.get(pk=instance.pk)
            if cur_inventory.photo:
                old_filename = str(cur_inventory.photo)
                os.remove(os.path.join(MEDIA_ROOT, old_filename))

        ext = filename.split('.')[-1]
        filename = "{0}.{1}".format(uuid.uuid4(), ext)
        return os.path.join('inventory', filename)
        #return os.path.join(filename)

    def admin_image(self):
        return '<img height="50px" src="{0}/{1}"/>'.format(MEDIA_URL, self.photo)
    admin_image.allow_tags = True

    photo = models.ImageField(_('Image'), upload_to=get_file_path, storage=fs, blank=False, null=False)
    thumbnail = models.ImageField(_('Thumbnail'), upload_to="thumbnails/", storage=fs,     blank=True, null=True)

....

I beendet die Funktion des Modells speichern überschrieben wird stattdessen das Foto und einen Daumen zu speichern, anstatt nur das Foto Größe ändern:

def save(self):

    # Save this photo instance first
    super(InventoryItem, self).save()

    from PIL import Image
    from cStringIO import StringIO
    from django.core.files.uploadedfile import SimpleUploadedFile

    # Set our max thumbnail size in a tuple (max width, max height)
    THUMBNAIL_SIZE = (200, 200)

    # Open original photo which we want to thumbnail using PIL's Image object
    image = Image.open(os.path.join(MEDIA_ROOT, self.photo.name))

    if image.mode not in ('L', 'RGB'):
        image = image.convert('RGB')

    image.thumbnail(THUMBNAIL_SIZE, Image.ANTIALIAS)

    # Save the thumbnail
    temp_handle = StringIO()
    image.save(temp_handle, 'png')  # image stored to stringIO

    temp_handle.seek(0)  # sets position of file to 0

     # Save to the thumbnail field
     suf = SimpleUploadedFile(os.path.split(self.photo.name)[-1],
        temp_handle.read(), content_type='image/png')  # reads in the file to save it

    self.thumbnail.save(suf.name+'.png', suf, save=False)

    #Save this photo instance again to save the thumbnail
    super(InventoryItem, self).save()

Beide arbeiten toll, aber je nachdem, was Sie tun möchten:)

Wenn Sie Django Ruhe Framework verwenden, könnte dies für die Verwendung:

Erste Funktion definieren, um Bild zu komprimieren und die Größe

def compress_image(photo):
# start compressing image
image_temporary = Image.open(photo)
output_io_stream = BytesIO()
image_temporary.thumbnail((1250, 1250), Image.ANTIALIAS)

# change orientation if necessary
for orientation in ExifTags.TAGS.keys():
    if ExifTags.TAGS[orientation] == 'Orientation':
        break
exif = dict(image_temporary._getexif().items())
# noinspection PyUnboundLocalVariable
if exif.get(orientation) == 3:
    image_temporary = image_temporary.rotate(180, expand=True)
elif exif.get(orientation) == 6:
    image_temporary = image_temporary.rotate(270, expand=True)
elif exif.get(orientation) == 8:
    image_temporary = image_temporary.rotate(90, expand=True)

# saving output
image_temporary.save(output_io_stream, format='JPEG', quality=75, optimize=True, progressive=True)
output_io_stream.seek(0)
photo = InMemoryUploadedFile(output_io_stream, 'ImageField', "%s.jpg" % photo.name.split('.')[0],
                             'image/jpeg', getsizeof(output_io_stream), None)
return photo

Zweitens, jetzt können Sie die Funktion in Serializer verwenden:

class SomeSerializer(serializers.ModelSerializer):
def update(self, instance, validated_data):
    # сжимаем рисунок
    if 'photo' in validated_data:           
        validated_data.update({'photo': compress_image(validated_data['photo'])})

    return super(SomeSerializer, self).update(instance, validated_data)

def create(self, validated_data):
    # сжимаем рисунок
    if 'photo' in validated_data:
        validated_data.update({'photo': compress_image(validated_data['photo'])})

    return super(SomeSerializer, self).create(validated_data)
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top