Django - изменить размер изображения перед сохранением
Как изменить размер изображения перед сохранением? Никак. Но далее я опишу путь, на который указал пользователь StackOwerflow в своём ответе вот на этот вопрос.
Вкратце:
- Сохраняем объект
- Проверяем наличие данных в нужном поле типа
ImageField - Открываем сохранённое изображение и меняем его свойства, как нам нужно
Пример
from PIL import Image
from django import models
from os import path
# Максимальный размер изображения по большей стороне
_MAX_SIZE = 300
class CarManufacter(models.Model):
"""Производитель автомобилей, два поля
name - название, строка
logo - логотип, изображение
"""
name = models.CharField(
'Наименование',
max_length=100,
unique=True
)
logo = models.ImageField(
upload_to=path.join('car', 'manufacter', 'logo'),
null=True,
blank=True
)
def save(self, *args, **kwargs):
# Сначала - обычное сохранение
super(CarManufacter, self).save(*args, **kwargs)
# Проверяем, указан ли логотип
if self.logo:
filepath = self.logo.path
width = self.logo.width
height = self.logo.height
max_size = max(width, height)
# Может, и не надо ничего менять?
if max_size > _MAX_SIZE:
# Надо, Федя, надо
image = Image.open(filename)
# resize - безопасная функция, она создаёт новый объект, а не
# вносит изменения в исходный, поэтому так
image = image.resize(
(round(width / max_size * _MAX_SIZE), # Сохраняем пропорции
round(height / max_size * _MAX_SIZE)),
Image.ANTIALIAS
)
# И не забыть сохраниться
image.save(filename)
Django и $resource
Суть проблемы
Решил использовать для реализации RESTful API своего приложения такой модуль Angular, как angular-resource. Проблем с установной и подключением, как обычно, не было. Создал свой сервис:
(function (A, U) { //U === undefined
"use strict";
A.module('DesktopApplication').factory('Category', function ($resource) {
var instance = {
selectedRow: U, //Используется в моём проекте для обмена данными между контроллерами,
//не является обязательным элементом
resource: $resource('/category/rows/:id', {id: '@id'})
};
return instance;
});
}(this.angular));
Казалось бы, всё должно работать. И ведь правда, вот такое работает (GET-запрос на получение данных):
//Где-то в коде, использующем сервис Category
Category.resource.query(function (items){
$scope.rows = items;
});
А вот такое уже нет:
//Чуть ниже
Category.save({'id': 4, 'name': 'Username'}, function (result) {
$scope.success = result.success;
});
Проблема оказалась в том, что даже явно указав слэш в конце строки ресурса, я получил POST-запросы, идущие к адресам без слэша, и Django такие запросы тут же банит. Начался поиск и чтение StackOverflow.
Решение
Решение оказалось довольно простым. Нужно указать в настройках приложения, что удалять концевой слэш для URL в AJAX-запросах не надо (а по-умолчанию включено). Кроме того, для корректной работы запросов методом PUT и DELETE нужно дополнительно конфигурировать $http. Иначе декоратор @csrf_protect из комплекта Django будет резать такие запросы. С учётом вышесказанного, скрипт настройки приложения стал выглядеть так (для сокращения размера выброшены прочие модули, которые я на самом деле использую в своём проекте):
(function(A) {
"use strict";
A.module('DesktopApplication', [ 'ngCookies', 'ngResource')
.config(function ($interpolateProvider, $resourceProvider) {
$interpolateProvider.startSymbol('{$');
$interpolateProvider.endSymbol('$}');
$resourceProvider.defaults.stripTrailingSlashes = false;
})
.run(function ($http, $cookies) {
$http.defaults.headers.common['X-CSRFToken'] = $cookies.csrftoken;
$http.defaults.headers.post['X-CSRFToken'] = $cookies.csrftoken;
$http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
});
}(this.angular, this.jQuery));