From 0336b745935277ee4774bb6c2d6f5b93dd4c655c Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Mon, 20 Oct 2025 05:08:25 +0000 Subject: [PATCH] feat: Add SHA1 hash calculation for Django ImageField Co-authored-by: 309vslexus <309vslexus@gmail.com> --- README.md | 173 +++++++++++++++++++++++++++- __pycache__/models.cpython-313.pyc | Bin 0 -> 6835 bytes models.py | 139 +++++++++++++++++++++++ sha1_utils.py | 113 +++++++++++++++++++ test_sha1_hash.py | 171 ++++++++++++++++++++++++++++ usage_examples.py | 174 +++++++++++++++++++++++++++++ 6 files changed, 769 insertions(+), 1 deletion(-) create mode 100644 __pycache__/models.cpython-313.pyc create mode 100644 models.py create mode 100644 sha1_utils.py create mode 100644 test_sha1_hash.py create mode 100644 usage_examples.py diff --git a/README.md b/README.md index 63ace0e..c30f67e 100644 --- a/README.md +++ b/README.md @@ -1 +1,172 @@ -Hello word +# SHA1 хеш для Django ImageField + +Этот проект содержит решения для получения SHA1 хеша содержимого файлов изображений из Django ImageField. + +## Файлы проекта + +- `models.py` - Полная Django модель с ImageField и методами для вычисления SHA1 +- `sha1_utils.py` - Утилиты без зависимости от Django для вычисления SHA1 +- `usage_examples.py` - Примеры использования в различных сценариях Django +- `test_sha1_hash.py` - Тесты для проверки функциональности + +## Основные способы получения SHA1 хеша + +### 1. Метод модели Django + +```python +class ImageModel(models.Model): + image = models.ImageField(upload_to='images/') + + def get_image_sha1_hash(self): + """Получить SHA1 хеш содержимого изображения.""" + if not self.image: + return None + + try: + with self.image.open('rb') as image_file: + sha1_hash = hashlib.sha1() + for chunk in iter(lambda: image_file.read(4096), b""): + sha1_hash.update(chunk) + return sha1_hash.hexdigest() + except (IOError, OSError) as e: + print(f"Ошибка при чтении файла: {e}") + return None + +# Использование: +image_obj = ImageModel.objects.get(id=1) +sha1_hash = image_obj.get_image_sha1_hash() +``` + +### 2. Утилитарная функция для ImageField + +```python +def get_image_field_sha1_hash(image_field): + """Утилитарная функция для получения SHA1 хеша любого ImageField.""" + if not image_field: + return None + + try: + with image_field.open('rb') as image_file: + sha1_hash = hashlib.sha1() + for chunk in iter(lambda: image_file.read(4096), b""): + sha1_hash.update(chunk) + return sha1_hash.hexdigest() + except (IOError, OSError) as e: + print(f"Ошибка при чтении файла: {e}") + return None + +# Использование: +sha1_hash = get_image_field_sha1_hash(some_model.image) +``` + +### 3. Функция для файла по пути + +```python +def get_image_file_sha1_hash(file_path): + """Получить SHA1 хеш файла по его пути.""" + try: + if not os.path.exists(file_path): + return None + + with open(file_path, 'rb') as image_file: + sha1_hash = hashlib.sha1() + for chunk in iter(lambda: image_file.read(4096), b""): + sha1_hash.update(chunk) + return sha1_hash.hexdigest() + except (IOError, OSError) as e: + print(f"Ошибка при чтении файла: {e}") + return None + +# Использование: +sha1_hash = get_image_file_sha1_hash('/path/to/image.jpg') +``` + +## Примеры использования + +### В Django View + +```python +def get_image_hash_view(request, image_id): + image_obj = get_object_or_404(ImageModel, id=image_id) + + if not image_obj.image: + return JsonResponse({'error': 'У объекта нет изображения'}, status=400) + + sha1_hash = image_obj.get_image_sha1_hash() + + return JsonResponse({ + 'id': image_obj.id, + 'sha1_hash': sha1_hash, + 'image_url': image_obj.image.url + }) +``` + +### В Django REST Framework Serializer + +```python +class ImageModelSerializer(serializers.ModelSerializer): + sha1_hash = serializers.SerializerMethodField() + + class Meta: + model = ImageModel + fields = ['id', 'name', 'image', 'sha1_hash'] + + def get_sha1_hash(self, obj): + if obj.image: + return obj.get_image_sha1_hash() + return None +``` + +### Массовое вычисление хешей + +```python +def calculate_all_hashes(): + images = ImageModel.objects.filter(image__isnull=False) + + for image_obj in images: + sha1_hash = image_obj.get_image_sha1_hash() + print(f"ID: {image_obj.id}, SHA1: {sha1_hash}") +``` + +### Сравнение изображений + +```python +def compare_images(image1, image2): + hash1 = image1.get_image_sha1_hash() + hash2 = image2.get_image_sha1_hash() + + return hash1 == hash2 # True если изображения идентичны +``` + +## Особенности реализации + +1. **Эффективность памяти**: Файлы читаются блоками по 4096 байт, что позволяет обрабатывать большие изображения без загрузки всего файла в память. + +2. **Обработка ошибок**: Все функции корректно обрабатывают ошибки ввода-вывода и возвращают `None` в случае проблем. + +3. **Совместимость с Django Storage**: Используется `image_field.open()` для работы с различными storage backend'ами Django. + +4. **Альтернативный метод**: Предоставлен альтернативный метод через `image.path` для случаев, когда нужен прямой доступ к файлу. + +## Тестирование + +Запустите тесты: + +```bash +python3 sha1_utils.py # Базовое тестирование без Django +python3 test_sha1_hash.py # Полные тесты (требует Django) +``` + +## Требования + +- Python 3.6+ +- Django 2.0+ (для полной функциональности) +- Pillow (для работы с ImageField) + +## Применение + +Эти функции полезны для: +- Проверки дублирующихся изображений +- Верификации целостности файлов +- Кеширования на основе содержимого +- Создания уникальных идентификаторов изображений \ No newline at end of file diff --git a/__pycache__/models.cpython-313.pyc b/__pycache__/models.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c0f2ac7be75106fafa03899983ff139a02ff690b GIT binary patch literal 6835 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 literal 0 HcmV?d00001 diff --git a/models.py b/models.py new file mode 100644 index 0000000..a914dbe --- /dev/null +++ b/models.py @@ -0,0 +1,139 @@ +""" +Пример Django модели с ImageField и функцией для получения SHA1 хеша содержимого изображения. +""" +import hashlib +import os +from django.db import models +from django.core.files.storage import default_storage + + +class ImageModel(models.Model): + """ + Модель с полем изображения. + """ + name = models.CharField(max_length=255, verbose_name="Название") + image = models.ImageField(upload_to='images/', verbose_name="Изображение") + created_at = models.DateTimeField(auto_now_add=True, verbose_name="Дата создания") + + class Meta: + verbose_name = "Изображение" + verbose_name_plural = "Изображения" + + def __str__(self): + return self.name + + def get_image_sha1_hash(self): + """ + Получить SHA1 хеш содержимого файла изображения. + + Returns: + str: SHA1 хеш в шестнадцатеричном формате или None если файл не существует + """ + if not self.image: + return None + + try: + # Открываем файл через Django storage + with self.image.open('rb') as image_file: + # Создаем объект SHA1 + sha1_hash = hashlib.sha1() + + # Читаем файл блоками для эффективности памяти + for chunk in iter(lambda: image_file.read(4096), b""): + sha1_hash.update(chunk) + + # Возвращаем хеш в шестнадцатеричном формате + return sha1_hash.hexdigest() + + except (IOError, OSError) as e: + print(f"Ошибка при чтении файла: {e}") + return None + + def get_image_sha1_hash_alternative(self): + """ + Альтернативный способ получения SHA1 хеша через путь к файлу. + + Returns: + str: SHA1 хеш в шестнадцатеричном формате или None если файл не существует + """ + if not self.image: + return None + + try: + # Получаем полный путь к файлу + file_path = self.image.path + + # Проверяем, существует ли файл + if not os.path.exists(file_path): + return None + + # Читаем файл и вычисляем хеш + with open(file_path, 'rb') as image_file: + sha1_hash = hashlib.sha1() + + # Читаем файл блоками + for chunk in iter(lambda: image_file.read(4096), b""): + sha1_hash.update(chunk) + + return sha1_hash.hexdigest() + + except (IOError, OSError, AttributeError) as e: + print(f"Ошибка при чтении файла: {e}") + return None + + +def get_image_field_sha1_hash(image_field): + """ + Утилитарная функция для получения SHA1 хеша любого ImageField. + + Args: + image_field: Django ImageField объект + + Returns: + str: SHA1 хеш в шестнадцатеричном формате или None если файл не существует + """ + if not image_field: + return None + + try: + # Используем Django storage для открытия файла + with image_field.open('rb') as image_file: + sha1_hash = hashlib.sha1() + + # Читаем файл блоками для эффективности памяти + for chunk in iter(lambda: image_file.read(4096), b""): + sha1_hash.update(chunk) + + return sha1_hash.hexdigest() + + except (IOError, OSError) as e: + print(f"Ошибка при чтении файла: {e}") + return None + + +def get_image_file_sha1_hash(file_path): + """ + Получить SHA1 хеш файла по его пути. + + Args: + file_path (str): Путь к файлу изображения + + Returns: + str: SHA1 хеш в шестнадцатеричном формате или None если файл не существует + """ + try: + if not os.path.exists(file_path): + return None + + with open(file_path, 'rb') as image_file: + sha1_hash = hashlib.sha1() + + # Читаем файл блоками + for chunk in iter(lambda: image_file.read(4096), b""): + sha1_hash.update(chunk) + + return sha1_hash.hexdigest() + + except (IOError, OSError) as e: + print(f"Ошибка при чтении файла: {e}") + return None \ No newline at end of file diff --git a/sha1_utils.py b/sha1_utils.py new file mode 100644 index 0000000..6338692 --- /dev/null +++ b/sha1_utils.py @@ -0,0 +1,113 @@ +""" +Утилиты для вычисления SHA1 хеша файлов изображений (без зависимости от Django). +""" +import hashlib +import os + + +def get_image_file_sha1_hash(file_path): + """ + Получить SHA1 хеш файла по его пути. + + Args: + file_path (str): Путь к файлу изображения + + Returns: + str: SHA1 хеш в шестнадцатеричном формате или None если файл не существует + """ + try: + if not os.path.exists(file_path): + return None + + with open(file_path, 'rb') as image_file: + sha1_hash = hashlib.sha1() + + # Читаем файл блоками для эффективности памяти + for chunk in iter(lambda: image_file.read(4096), b""): + sha1_hash.update(chunk) + + return sha1_hash.hexdigest() + + except (IOError, OSError) as e: + print(f"Ошибка при чтении файла: {e}") + return None + + +def get_image_field_sha1_hash(image_field): + """ + Получить SHA1 хеш Django ImageField. + + Args: + image_field: Django ImageField объект + + Returns: + str: SHA1 хеш в шестнадцатеричном формате или None если файл не существует + """ + if not image_field: + return None + + try: + # Используем Django storage для открытия файла + with image_field.open('rb') as image_file: + sha1_hash = hashlib.sha1() + + # Читаем файл блоками для эффективности памяти + for chunk in iter(lambda: image_file.read(4096), b""): + sha1_hash.update(chunk) + + return sha1_hash.hexdigest() + + except (IOError, OSError) as e: + print(f"Ошибка при чтении файла: {e}") + return None + + +def calculate_sha1_from_bytes(data): + """ + Вычислить SHA1 хеш из байтовых данных. + + Args: + data (bytes): Байтовые данные + + Returns: + str: SHA1 хеш в шестнадцатеричном формате + """ + return hashlib.sha1(data).hexdigest() + + +if __name__ == "__main__": + # Пример использования + import tempfile + + # Создаем тестовые данные + test_data = b"Test image data for SHA1 hashing" + expected_hash = calculate_sha1_from_bytes(test_data) + + print("=== Демонстрация вычисления SHA1 хеша ===") + print(f"Тестовые данные: {test_data}") + print(f"Ожидаемый SHA1: {expected_hash}") + + # Создаем временный файл + with tempfile.NamedTemporaryFile(delete=False) as temp_file: + temp_file.write(test_data) + temp_file_path = temp_file.name + + try: + # Вычисляем хеш файла + file_hash = get_image_file_sha1_hash(temp_file_path) + print(f"SHA1 файла: {file_hash}") + + # Проверяем совпадение + if file_hash == expected_hash: + print("✅ Хеши совпадают!") + else: + print("❌ Хеши не совпадают!") + + finally: + # Удаляем временный файл + os.unlink(temp_file_path) + + # Тест с несуществующим файлом + print(f"\nТест с несуществующим файлом:") + result = get_image_file_sha1_hash("/nonexistent/file.jpg") + print(f"Результат: {result}") # Должно быть None \ No newline at end of file diff --git a/test_sha1_hash.py b/test_sha1_hash.py new file mode 100644 index 0000000..887443c --- /dev/null +++ b/test_sha1_hash.py @@ -0,0 +1,171 @@ +""" +Тесты для функций вычисления SHA1 хеша изображений. +""" +import hashlib +import os +import tempfile +from unittest.mock import Mock, patch, mock_open +import unittest + +# Импортируем функции для тестирования +from models import get_image_field_sha1_hash, get_image_file_sha1_hash + + +class TestSHA1HashFunctions(unittest.TestCase): + """ + Тесты для функций вычисления SHA1 хеша. + """ + + def setUp(self): + """ + Настройка тестовых данных. + """ + # Создаем тестовые данные + self.test_data = b"Test image data for SHA1 hashing" + self.expected_hash = hashlib.sha1(self.test_data).hexdigest() + + def test_get_image_file_sha1_hash_success(self): + """ + Тест успешного вычисления SHA1 хеша файла. + """ + # Создаем временный файл + with tempfile.NamedTemporaryFile(delete=False) as temp_file: + temp_file.write(self.test_data) + temp_file_path = temp_file.name + + try: + # Вычисляем хеш + result_hash = get_image_file_sha1_hash(temp_file_path) + + # Проверяем результат + self.assertEqual(result_hash, self.expected_hash) + + finally: + # Удаляем временный файл + os.unlink(temp_file_path) + + def test_get_image_file_sha1_hash_nonexistent_file(self): + """ + Тест обработки несуществующего файла. + """ + result = get_image_file_sha1_hash("/nonexistent/path/image.jpg") + self.assertIsNone(result) + + def test_get_image_field_sha1_hash_success(self): + """ + Тест успешного вычисления SHA1 хеша ImageField. + """ + # Создаем мок ImageField + mock_image_field = Mock() + mock_file = mock_open(read_data=self.test_data) + mock_image_field.open.return_value.__enter__ = mock_file + mock_image_field.open.return_value.__exit__ = Mock(return_value=None) + + # Настраиваем мок для чтения данных блоками + mock_file.return_value.read.side_effect = [ + self.test_data[:16], # Первый блок + self.test_data[16:], # Второй блок + b"" # Конец файла + ] + + # Вычисляем хеш + result_hash = get_image_field_sha1_hash(mock_image_field) + + # Проверяем результат + self.assertEqual(result_hash, self.expected_hash) + + def test_get_image_field_sha1_hash_empty_field(self): + """ + Тест обработки пустого ImageField. + """ + result = get_image_field_sha1_hash(None) + self.assertIsNone(result) + + result = get_image_field_sha1_hash("") + self.assertIsNone(result) + + def test_get_image_field_sha1_hash_io_error(self): + """ + Тест обработки ошибки ввода-вывода. + """ + # Создаем мок ImageField с ошибкой + mock_image_field = Mock() + mock_image_field.open.side_effect = IOError("File not found") + + # Вычисляем хеш + result_hash = get_image_field_sha1_hash(mock_image_field) + + # Проверяем, что возвращается None при ошибке + self.assertIsNone(result_hash) + + def test_large_file_hash(self): + """ + Тест вычисления хеша большого файла (проверка чтения блоками). + """ + # Создаем большие тестовые данные + large_data = b"x" * 10000 # 10KB данных + expected_hash = hashlib.sha1(large_data).hexdigest() + + # Создаем временный файл + with tempfile.NamedTemporaryFile(delete=False) as temp_file: + temp_file.write(large_data) + temp_file_path = temp_file.name + + try: + # Вычисляем хеш + result_hash = get_image_file_sha1_hash(temp_file_path) + + # Проверяем результат + self.assertEqual(result_hash, expected_hash) + + finally: + # Удаляем временный файл + os.unlink(temp_file_path) + + +def create_test_image_file(): + """ + Создает тестовый файл изображения для демонстрации. + """ + # Простые данные PNG (1x1 пиксель, прозрачный) + png_data = b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01\x00\x00\x00\x01\x08\x06\x00\x00\x00\x1f\x15\xc4\x89\x00\x00\x00\rIDATx\x9cc\xf8\x0f\x00\x00\x01\x00\x01\x00\x18\xdd\x8d\xb4\x00\x00\x00\x00IEND\xaeB`\x82' + + with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as temp_file: + temp_file.write(png_data) + return temp_file.name + + +def demo_sha1_calculation(): + """ + Демонстрация вычисления SHA1 хеша. + """ + print("=== Демонстрация вычисления SHA1 хеша ===") + + # Создаем тестовый файл изображения + test_image_path = create_test_image_file() + + try: + # Вычисляем хеш + sha1_hash = get_image_file_sha1_hash(test_image_path) + + print(f"Путь к файлу: {test_image_path}") + print(f"SHA1 хеш: {sha1_hash}") + + # Проверяем размер файла + file_size = os.path.getsize(test_image_path) + print(f"Размер файла: {file_size} байт") + + finally: + # Удаляем тестовый файл + os.unlink(test_image_path) + + +if __name__ == "__main__": + # Запуск демонстрации + demo_sha1_calculation() + + print("\n" + "="*50) + print("Запуск тестов...") + + # Запуск тестов + unittest.main(verbosity=2) \ No newline at end of file diff --git a/usage_examples.py b/usage_examples.py new file mode 100644 index 0000000..64c53e2 --- /dev/null +++ b/usage_examples.py @@ -0,0 +1,174 @@ +""" +Примеры использования функций для получения SHA1 хеша изображений в Django. +""" + +# Импорты (предполагается, что Django настроен) +from models import ImageModel, get_image_field_sha1_hash, get_image_file_sha1_hash + + +def example_usage(): + """ + Примеры использования различных способов получения SHA1 хеша изображения. + """ + + # Пример 1: Использование метода модели + print("=== Пример 1: Метод модели ===") + + # Получаем объект модели (предполагается, что он существует) + try: + image_obj = ImageModel.objects.first() + if image_obj and image_obj.image: + sha1_hash = image_obj.get_image_sha1_hash() + print(f"SHA1 хеш изображения '{image_obj.name}': {sha1_hash}") + else: + print("Нет объектов с изображениями в базе данных") + except Exception as e: + print(f"Ошибка при получении объекта: {e}") + + + # Пример 2: Использование альтернативного метода модели + print("\n=== Пример 2: Альтернативный метод модели ===") + + try: + image_obj = ImageModel.objects.first() + if image_obj and image_obj.image: + sha1_hash = image_obj.get_image_sha1_hash_alternative() + print(f"SHA1 хеш (альтернативный способ): {sha1_hash}") + except Exception as e: + print(f"Ошибка: {e}") + + + # Пример 3: Использование утилитарной функции + print("\n=== Пример 3: Утилитарная функция ===") + + try: + image_obj = ImageModel.objects.first() + if image_obj and image_obj.image: + sha1_hash = get_image_field_sha1_hash(image_obj.image) + print(f"SHA1 хеш (утилитарная функция): {sha1_hash}") + except Exception as e: + print(f"Ошибка: {e}") + + + # Пример 4: Использование функции для файла по пути + print("\n=== Пример 4: Хеш файла по пути ===") + + # Пример с конкретным путем к файлу + file_path = "/path/to/your/image.jpg" # Замените на реальный путь + sha1_hash = get_image_file_sha1_hash(file_path) + if sha1_hash: + print(f"SHA1 хеш файла '{file_path}': {sha1_hash}") + else: + print(f"Не удалось получить хеш для файла '{file_path}'") + + +def example_in_view(): + """ + Пример использования в Django view. + """ + from django.http import JsonResponse + from django.shortcuts import get_object_or_404 + + def get_image_hash_view(request, image_id): + """ + View для получения SHA1 хеша изображения по ID. + """ + try: + image_obj = get_object_or_404(ImageModel, id=image_id) + + if not image_obj.image: + return JsonResponse({ + 'error': 'У объекта нет изображения' + }, status=400) + + sha1_hash = image_obj.get_image_sha1_hash() + + if sha1_hash: + return JsonResponse({ + 'id': image_obj.id, + 'name': image_obj.name, + 'sha1_hash': sha1_hash, + 'image_url': image_obj.image.url + }) + else: + return JsonResponse({ + 'error': 'Не удалось вычислить хеш изображения' + }, status=500) + + except Exception as e: + return JsonResponse({ + 'error': f'Ошибка: {str(e)}' + }, status=500) + + +def example_in_serializer(): + """ + Пример использования в Django REST Framework serializer. + """ + from rest_framework import serializers + + class ImageModelSerializer(serializers.ModelSerializer): + sha1_hash = serializers.SerializerMethodField() + + class Meta: + model = ImageModel + fields = ['id', 'name', 'image', 'created_at', 'sha1_hash'] + + def get_sha1_hash(self, obj): + """ + Получить SHA1 хеш изображения для сериализатора. + """ + if obj.image: + return obj.get_image_sha1_hash() + return None + + +def example_bulk_hash_calculation(): + """ + Пример массового вычисления хешей для всех изображений. + """ + print("=== Массовое вычисление SHA1 хешей ===") + + try: + images = ImageModel.objects.filter(image__isnull=False) + + for image_obj in images: + sha1_hash = image_obj.get_image_sha1_hash() + print(f"ID: {image_obj.id}, Название: {image_obj.name}, SHA1: {sha1_hash}") + + except Exception as e: + print(f"Ошибка при массовом вычислении: {e}") + + +def example_compare_images(): + """ + Пример сравнения изображений по их SHA1 хешам. + """ + print("=== Сравнение изображений по SHA1 хешам ===") + + try: + images = ImageModel.objects.filter(image__isnull=False)[:2] + + if len(images) >= 2: + hash1 = images[0].get_image_sha1_hash() + hash2 = images[1].get_image_sha1_hash() + + print(f"Изображение 1 ({images[0].name}): {hash1}") + print(f"Изображение 2 ({images[1].name}): {hash2}") + + if hash1 == hash2: + print("Изображения идентичны!") + else: + print("Изображения различны.") + else: + print("Недостаточно изображений для сравнения") + + except Exception as e: + print(f"Ошибка при сравнении: {e}") + + +if __name__ == "__main__": + # Запуск примеров (требует настроенного Django окружения) + example_usage() + example_bulk_hash_calculation() + example_compare_images() \ No newline at end of file