Photologue : DRF 통합으로 Django를 위한 멋진 이미지 관리

개념



Django 웹 프레임워크를 위한 강력한 이미지 관리 및 갤러리 애플리케이션입니다. 사진을 업로드하고 갤러리로 그룹화하고 워터마크와 같은 효과를 적용합니다.



종속성


  • 장고.
  • 베개.
  • Django-sortedm2m. (django-photologue로 자동 설치됨)

  • 설치



    Photologue를 설치하는 가장 쉬운 방법은 pip를 사용하는 것입니다. 이렇게 하면 PyPi에서 사용 가능한 최신 버전이 제공됩니다.

    pip install django-photologue
    


    시작하기



    전제 조건



    setting.py에서 MEDIA_URL 및 MEDIA_ROOT를 설정했는지 확인하십시오.

    #settings.py
    
    MEDIA_URL = /media/
    MEDIA_ROOT = /data/media/
    


    구성



    1) INSTALLED_APPS 및 SITE_ID=1에 photologue, sortedm2m, django.contrib.sites를 추가합니다.

    #settings.py
    SITE_ID = 1
    
    INSTALLED_APPS = [
         ...
    
        'django.contrib.sites',
    
        # Django Image Library - Photologue
        'photologue',
        'sortedm2m',
    ]
    


    2) 포토로그 마이그레이션 적용

    python manage.py migrate photologue
    


    3) urls.py에 포토로그 URL 등록

    urlpatterns = [
        ...
        # Photologue Urls
        path('photologue/', include('photologue.urls', namespace='photologue')),
    ]
    


    모델



    모델에 photologue Photo 필드를 추가합니다.

    image = models.ForeignKey(
        'photologue.Photo',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
    )
    


    그런 다음 마이그레이션을 적용합니다.

    python manage.py makemigrations
    python manage.py migrate
    


    모델의 예:

    class BlogPost(models.Model):
        uuid = models.UUIDField(
            primary_key=True,
            default=uuid.uuid4,
            help_text="The uuid4 primary key of the post",
        )
        title = models.CharField(
            max_length=255,
            help_text="The title of the post",
        )
        content = models.TextField(
            blank=True,
            help_text="The content of the post",
        )
        publishers = models.ManyToManyField(
            'auth.User',
            related_name='posts',
            help_text="The maintainers of the pods",
        )
        preview_image = models.ForeignKey(
            'photologue.Photo',
            null=True,
            blank=True,
            on_delete=models.SET_NULL,
            help_text="The preview image of the appx",
        )
    
        def __str__(self):
            return f'Appx: {self.name}'
    


    갤러리



    Photo 필드의 M2M인 Gallery 필드를 추가할 수 있습니다.

    gallery = models.ForeignKey(
        'photologue.Gallery',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
    )
    


    사진 크기



    Django 관리 인터페이스로 이동한 다음 새 PhotoSize 인스턴스를 생성할 수 있습니다.
    사진 인스턴스가 생성되면 자동 자르기 및 품질 압축을 통해 각 사진 크기에 대한 이미지가 생성됩니다.

    다음은 사진 크기의 예입니다.
  • 썸네일 (100 x 100)
  • 소(320×200)
  • 중형(640 x 400)
  • 대형(960×600)




  • 접근자



    Photologue의 기본은 Photo 모델입니다. 인스턴스가 생성되면 다양한 사진 크기의 사진을 검색하기 위해 메서드가 자동으로 추가됩니다. 예를 들어 image라는 Photo 인스턴스가 있는 경우 다음 메서드가 자동으로 추가됩니다.

    preview_image.get_small_url()
    preview_image.get_medium_url()
    preview_image.get_large_url()
    preview_image.get_raw_url()
    


    다음과 같이 썸네일을 표시하기 위해 사용자 정의 템플릿에서 사용할 수 있습니다.

    <a href="{{ preview_image.image.url }}">
        <img src="{{ preview_image.get_raw_url }}" alt="{{ preview_image.title }}">
    </a>
    


    유틸리티



    다음은 이미지를 가져와 Photo 인스턴스를 생성하는 함수입니다.

    from datetime import datetime
    from django.utils.text import slugify
    from photologue.models import Photo
    
    
    def create_photo(image):
        title = f'{datetime.now()}'
        slug = slugify(title)
        photo = Photo.objects.create(
            title=title,
            slug=slug,
            image=image,
        )
        return photo
    
    


    DRF 통합



    믹스인



    이미지 필드 이름을 기반으로 MixinSerializer를 생성하는 이 메서드 create_mixin_image_serializer()를 정의할 수 있습니다.

    from rest_framework import serializers
    from photologue.models import PhotoSize
    from collections import OrderedDict
    
    
    def _get_image_factory(image_field_name, photo_size):
        def get_image(self, obj):
            request = self.context['request']
            if request and hasattr(obj, image_field_name):
                image = getattr(obj, image_field_name)
                if image is not None:
                    get_url_method = getattr(image, f'get_{photo_size}_url')
                    url = get_url_method()
                    return request.build_absolute_uri(url)
            return None
        return get_image
    
    
    def create_mixin_image_serializer(image_field_name):
        photo_sizes = PhotoSize.objects\
            .filter(id__gte=3)\
            .values_list('name', flat=True)
    
        class ImageSerializerMixin(serializers.ModelSerializer):
            pass
    
        ImageSerializerMixin._declared_fields = OrderedDict([
            (f'{image_field_name}_{photo_size}', serializers.SerializerMethodField())
            for photo_size in photo_sizes
        ])
    
        for photo_size in photo_sizes:
            setattr(
                ImageSerializerMixin,
                f'get_{image_field_name}_{photo_size}',
                _get_image_factory(image_field_name, photo_size),
            )
        return ImageSerializerMixin
    
    


    직렬 변환기



    1) preview_image 필드를 사용하여 mixin 이미지 직렬 변환기를 인스턴스화할 수 있습니다.

    PreviewImageSerializerMixin = create_mixin_image_serializer('preview_image')
    


    그렇지 않으면 mixin 이미지 직렬 변환기를 수동으로 만들 수 있습니다.

    class PreviewImageSerializerMixin(serializers.ModelSerializer):
        preview_image_small = serializers.SerializerMethodField()
        preview_image_medium = serializers.SerializerMethodField()
        preview_image_large = serializers.SerializerMethodField()
        preview_image_raw = serializers.SerializerMethodField()
    
       def get_preview_image_small(self, obj):
           request = self.context['request']
           if request and hasattr(obj, 'preview_image'):
               image = getattr(obj, 'preview_image')
               if image is not None:
                   url = image.get_small_url()
                   return request.build_absolute_uri(url)
           return None
    
       def get_preview_image_medium(self, obj):
           request = self.context['request']
           if request and hasattr(obj, 'preview_image'):
               image = getattr(obj, 'preview_image')
               if image is not None:
                   url = image.get_medium_url()
                   return request.build_absolute_uri(url)
           return None
    
       def get_preview_image_large(self, obj):
           request = self.context['request']
           if request and hasattr(obj, 'preview_image'):
               image = getattr(obj, 'preview_image')
               if image is not None:
                   url = image.get_large_url()
                   return request.build_absolute_uri(url)
           return None
    
       def get_preview_image_raw(self, obj):
           request = self.context['request']
           if request and hasattr(obj, 'preview_image'):
               image = getattr(obj, 'preview_image')
               if image is not None:
                   url = image.get_raw_url()
                   return request.build_absolute_uri(url)
           return None
    
    


    2) 다음은 직렬 변환기의 예입니다.

    class BlogPostSerializer(PreviewImageSerializerMixin):
        """
        Serializer for BlogPost instance
        """
        class Meta:
            model = BlogPost
            fields = ('uuid', 'title', 'content',
                      'preview_image_small', 'preview_image_medium',
                      'preview_image_large', 'preview_image_raw')
    
    


    3) 이미지를 업로드하는 경우 create() 및 update()를 정의합니다.

        def create(self, validated_data):
            preview_image = validated_data.pop('preview_image', None)
            instance = super(BlogPostSerializer, self).create(validated_data)
    
            # Save image field
            if preview_image:
                instance.preview_image = create_photo(preview_image)
    
            instance.save()
            return instance
    
        def update(self, instance, validated_data):
              preview_image = validated_data.pop('preview_image', None)
            instance = super(BlogPostSerializer, self).update(instance, validated_data)
    
            # Update image field
            if preview_image:
                instance.preview_image = create_photo(preview_image)
    
            instance.save()
            return instance
    


    제작 참고 사항



    포토로그 라이브러리를 단계별로 통합해야 합니다.

    1) 패키지를 설치합니다.

    pip install django-photologue
    


    2) INSTALLED_APPS에 포토로그, sortedm2m, django.contrib.sites 추가

    INSTALLED_APPS = [
         ...
    
        'django.contrib.sites',
    
        # Django Image Library - Photologue
        'photologue',
        'sortedm2m',
    ]
    



    python manage.py migrate photologue
    


    3) 포토로그 마이그레이션 적용

    python manage.py migrate photologue
    


    4) models.py에서 ImageField를 사진으로 바꾸려면 다음 단계를 따라야 합니다.
  • models.py에서 ImageField를 제거합니다.
  • 마이그레이션 적용
  • models.py에 사진 추가
  • 마이그레이션 적용

  • 이미지를 유지하려면 다음 두 필드를 유지해야 합니다.
  • models.py에 사진 추가
  • 마이그레이션 적용
  • 인스턴스 사진
  • models.py에서 ImageField를 제거합니다.
  • 마이그레이션 적용

  • 연결


  • https://django-photologue.readthedocs.io/
  • https://www.django-photologue.net/
  • https://github.com/richardbarran/django-photologue/wiki/Examples-and-forks
  • 좋은 웹페이지 즐겨찾기