如何从压缩档案库中制作图像库?

时间:2018-02-25 18:13:19

标签: python python-3.x wagtail

我有一个项目,我想让wagtail Page用户可以在管理部分上传zip图片存档。然后我想解压缩此存档并将每个解压缩的图像放到与此页面相连的图像库中:

import urllib.parse
import os
import zipfile

from django.db import models
from django.conf import settings

from wagtail.wagtailcore.models import Page, Orderable
from wagtail.wagtailcore.fields import RichTextField
from wagtail.wagtailadmin.edit_handlers import FieldPanel, InlinePanel
from wagtail.wagtailsearch import index
from wagtail.wagtailimages.edit_handlers import ImageChooserPanel
from wagtail.wagtailimages.models import Image
from taggit.models import TaggedItemBase

from modelcluster.fields import ParentalKey
from modelcluster.contrib.taggit import ClusterTaggableManager

from .forms import PhotoEventPageForm
from utils import get_paginated_pages, get_all_tags

...

class PhotoEventPage(Page):
    photos = models.FileField(upload_to=directory_path)
    photos_unpacked = models.BooleanField(default=False)    
    ...

    base_form_class = PhotoEventPageForm

    def main_image(self):
        gallery_item = self.gallery_images.first()
        if gallery_item:
            return gallery_item.image
        else:
            return None

    def save(self, *args, **kwargs):
        if os.path.isfile(self.photos.path) and not self.photos_unpacked:
            with zipfile.ZipFile(self.photos.path, "r") as zip_ref:
                for file_name in zip_ref.namelist():
                    zip_ref.extract(
                        file_name,
                        path=os.path.dirname(self.photos.path))
                    # now i have image file, this line prints True:
                    # print(os.path.isfile(os.path.join(os.path.dirname(self.photos.path), file_name)))
                    # so now I have saved image and i want to create Image gallery,
                    # I've tried this code:

                    # img = Image()
                    # img.save()
                    # gallery_img = PhotoEventPageGalleryImage(
                    #     image_id=img.id, page_id=self.id)
                    # gallery_img.save()

                    # but it's not working
            self.photos_unpacked = True
        return super().save(*args, **kwargs)

class PhotoEventPageGalleryImage(Orderable):
    page = ParentalKey(PhotoEventPage, related_name='gallery_images')
    image = models.ForeignKey(
        'wagtailimages.Image', on_delete=models.CASCADE, related_name='+'
    )
    caption = models.CharField(blank=True, max_length=250)

    panels = [
        ImageChooserPanel('image'),
        FieldPanel('caption'),
    ]

但它没有用,我不知道如何从解压缩的图片中创建wagtail.wagtailimages.models.Image实例,当我解开这段代码时:

img = Image()
img.save()
gallery_img = PhotoEventPageGalleryImage(
                image_id=img.id, page_id=self.id)
gallery_img.save()

我得到了NOT NULL constraint failed: wagtailimages_image.width。那么也许有办法做到这一点?

经过一些谷歌搜索,感谢Paulo Scardine,还检查了: this 我提出了以下代码:

from django.core.files.images import ImageFile

from wagtail.wagtailcore.models import Page, Orderable
from wagtail.wagtailcore.fields import RichTextField
from wagtail.wagtailadmin.edit_handlers import FieldPanel, InlinePanel
from wagtail.wagtailsearch import index
from wagtail.wagtailimages.edit_handlers import ImageChooserPanel
from wagtail.wagtailimages.models import Image
from taggit.models import TaggedItemBase

...

class PhotoEventPage(Page):
    ...

    def save(self, *args, **kwargs):
        if os.path.isfile(self.photos.path) and not self.photos_unpacked:
            with zipfile.ZipFile(self.photos.path, "r") as zip_ref:
                for file_name in zip_ref.namelist():
                    zip_ref.extract(
                        file_name,
                        path=os.path.dirname(self.photos.path))
                    # print(os.path.isfile(os.path.join(os.path.dirname(self.photos.path), file_name)))

                    image_file = open(
                        os.path.join(
                            os.path.dirname(
                                self.photos.path), file_name), "rb")

                    image = Image(
                        title="Image title",
                        file=ImageFile(image_file, name=file_name),
                    )

                    image.save()
                    image_file.close()

                    gallery_img = PhotoEventPageGalleryImage(
                        image_id=image.id, page_id=self.id)
                    gallery_img.save()

            self.photos_unpacked = True
        return super().save(*args, **kwargs)

这很奇怪,我的意思是它确实无误地工作,我可以保存PhotoEventPage而不会出现错误并提取图片,但self.gallery_images内没有任何项目保存后,不知道为什么。

1 个答案:

答案 0 :(得分:1)

我需要创建wagtail_hooks.py文件,并且如docs中所述,在那里定义钩子:

<强> models.py

from wagtail.images.models import Image
...

class ExtenedWagtailImage(Image):
    filepath = models.FilePathField()


class PhotoEventPageGalleryImage(Orderable):
    page = ParentalKey(PhotoEventPage, related_name='gallery_images')
    image = models.ForeignKey(
        ExtenedWagtailImage, on_delete=models.CASCADE, related_name='+'
    )
    caption = models.CharField(blank=True, max_length=250)

    panels = [
        ImageChooserPanel('image'),
        FieldPanel('caption')
    ]

<强> wagtail_hooks.py

import os
import zipfile

from django.core.files.images import ImageFile
from django.db import IntegrityError

from wagtail.core import hooks

from .models import PhotoEventPageGalleryImage, ExtenedWagtailImage as EWI


@hooks.register('after_edit_page')
@hooks.register('after_create_page')
def create_gallery(request, page):
    if page.__class__.__name__ == 'PhotoEventPage':
        with zipfile.ZipFile(page.photos.path, "r") as zip_ref:
            for file_name in zip_ref.namelist():

                image_file_path = os.path.join(
                    os.path.dirname(page.photos.path), file_name)

                if not os.path.isfile(image_file_path):
                    zip_ref.extract(
                        file_name,
                        path=os.path.dirname(page.photos.path))

                with open(image_file_path, "rb") as image_file:
                    try:
                        image_obj, created = EWI.objects.get_or_create(
                            filepath=image_file_path,
                            defaults={
                                'file': ImageFile(image_file, name=file_name),
                                'title': file_name}
                        )
                    # if it's not an image
                    except IntegrityError:
                        continue

                photo_event_amount = len(
                    PhotoEventPageGalleryImage.objects.filter(
                        page_id=page.id, image_id=image_obj.id))

                if created or photo_event_amount == 0:
                    PhotoEventPageGalleryImage(
                        image_id=image_obj.id, page_id=page.id).save()