Skip to content

Commit

Permalink
Merge pull request #493 from ccnmtl/restore-imageblocks
Browse files Browse the repository at this point in the history
Re-introduce sorl and bring back ImageBlocks
  • Loading branch information
ndittren authored Jun 12, 2024
2 parents 062b37e + 75f3468 commit 215cb73
Show file tree
Hide file tree
Showing 11 changed files with 414 additions and 11 deletions.
13 changes: 8 additions & 5 deletions CHANGES.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
2.0.0 (2017-08-28)
1.3.0
==================
* Removed ImageBlock and ImagePullQuoteBlock. To use these models,
you can find them in the django-sorlimageblock package.
* Removed dependency on our outdated `sorl` package, which isn't present
on pypi.python.org.
* Added Django 4.2 compatibility

1.2.0 (2017-08-10)
==================
* Incorporated all commits up to head, except for the removal
of the ImageBlock
* Adds ImageBlock test for the lightbox "on" value

1.1.0 (2016-08-12)
==================
Expand Down
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ VE ?= ./ve
REQUIREMENTS ?= test_reqs.txt
SYS_PYTHON ?= python3
PY_SENTINAL ?= $(VE)/sentinal
WHEEL_VERSION ?= 0.33.6
PIP_VERSION ?= 20.0.2
WHEEL_VERSION ?= 0.43.0
PIP_VERSION ?= 24.0
MAX_COMPLEXITY ?= 8
PY_DIRS ?= $(APP)
DJANGO ?= "Django==2.2.13"
DJANGO ?= "Django==4.2.13"

FLAKE8 ?= $(VE)/bin/flake8
PIP ?= $(VE)/bin/pip
Expand Down
44 changes: 44 additions & 0 deletions pageblocks/exportimport.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from __future__ import print_function
import os
from django.core.files import File
from models import TextBlock, HTMLBlock, PullQuoteBlock, SimpleImageBlock
from models import ImageBlock, ImagePullQuoteBlock
from pagetree_export import register_class as register


Expand Down Expand Up @@ -73,3 +75,45 @@ def exporter(self, block, xmlfile, zipfile):
filename = "pageblocks/%s-%s" % (block.pk, filename)
zipfile.write(block.image.file.name, arcname=filename)
return {'img_src': '/' + filename.strip('/')}


@register
class Image(object):
block_class = ImageBlock
identifier = 'image'

def exporter(self, block, xmlfile, zipfile):
filename = os.path.basename(block.image.file.name)
filename = "pageblocks/%s-%s" % (block.pk, filename)
zipfile.write(block.image.file.name, arcname=filename)
return {'img_src': '/' + filename.strip('/')}

def importer(self, node, zipfile):
children = node.getchildren()
assert len(children) == 1 and children[0].tag == "img"
path = children[0].get("src")
caption = children[0].get("caption")
file = zipfile.open(path)
file.size = zipfile.getinfo(path).file_size
b = ImageBlock(caption=caption, image='')
b.save_image(File(file))
b.save()
return b


@register
class ImagePullQuote(Image):
block_class = ImagePullQuoteBlock
identifier = 'imagepullquote'

def importer(self, node, zipfile):
children = node.getchildren()
assert len(children) == 1 and children[0].tag == "img"
path = children[0].get("src")
caption = children[0].get("caption")
file = zipfile.open(path)
file.size = zipfile.getinfo(path).file_size
b = ImagePullQuoteBlock(caption=caption, image='')
b.save_image(File(file))
b.save()
return b
6 changes: 6 additions & 0 deletions pageblocks/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,9 @@ class AddSimpleImageBlockForm(forms.Form):
class AddHTMLBlockForm(forms.Form):
label = forms.CharField()
html = forms.CharField(widget=widgets.Textarea(attrs={'cols': 80}))


class AddImagePullQuoteBlockForm(forms.Form):
label = forms.CharField()
image = forms.ImageField()
caption = forms.CharField(widget=widgets.Textarea(attrs={'cols': 80}))
26 changes: 26 additions & 0 deletions pageblocks/migrations/0001_initial.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from __future__ import unicode_literals

from django.db import models, migrations
import sorl.thumbnail.fields


class Migration(migrations.Migration):
Expand Down Expand Up @@ -31,6 +32,31 @@ class Migration(migrations.Migration):
},
bases=(models.Model,),
),
migrations.CreateModel(
name='ImageBlock',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('image', sorl.thumbnail.fields.ImageWithThumbnailsField(upload_to=b'images/%Y/%m/%d')),
('caption', models.TextField(blank=True)),
('alt', models.CharField(max_length=100, null=True, blank=True)),
('lightbox', models.BooleanField(default=False)),
],
options={
},
bases=(models.Model,),
),
migrations.CreateModel(
name='ImagePullQuoteBlock',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('image', sorl.thumbnail.fields.ImageWithThumbnailsField(upload_to=b'images/%Y/%m/%d')),
('caption', models.TextField(blank=True)),
('alt', models.CharField(max_length=100, null=True, blank=True)),
],
options={
},
bases=(models.Model,),
),
migrations.CreateModel(
name='PullQuoteBlock',
fields=[
Expand Down
212 changes: 212 additions & 0 deletions pageblocks/models.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
from django.db import models
from django.conf import settings
from sorl.thumbnail.fields import ImageWithThumbnailsField
from django import forms
import os
from django.template.defaultfilters import slugify
from datetime import datetime
from pagetree.generic.models import BasePageBlock


Expand Down Expand Up @@ -125,6 +128,120 @@ def summary_render(self):
return self.body[:61] + "..."


class ImageBlock(BasePageBlock):
"""
ImageBlock allows the user to upload an image to
the block, and includes automatic thumbnailing.
"""
image = ImageWithThumbnailsField(
upload_to="images/%Y/%m/%d",
thumbnail={
'size': (65, 65)
},
extra_thumbnails={
'admin': {
'size': (70, 50),
'options': ('sharpen',),
}
})
caption = models.TextField(blank=True)
alt = models.CharField(max_length=100, null=True, blank=True)
lightbox = models.BooleanField(default=False)
template_file = "pageblocks/imageblock.html"
display_name = "Image Block"
summary_template_file = "pageblocks/imageblock_summary.html"

def edit_form(self):
class EditForm(forms.Form):
image = forms.FileField(label="replace image")
caption = forms.CharField(
initial=self.caption,
required=False,
widget=forms.widgets.Textarea(),
)
alt = forms.CharField(
initial=self.alt,
required=False,
)
lightbox = forms.BooleanField(
initial=self.lightbox, required=False)
return EditForm()

@classmethod
def add_form(cls):
class AddForm(forms.Form):
image = forms.FileField(label="select image")
caption = forms.CharField(widget=forms.widgets.Textarea(),
required=False)
alt = forms.CharField(required=False)
lightbox = forms.BooleanField(initial=False, required=False)
return AddForm()

@classmethod
def create(cls, request):
if 'image' in request.FILES:
lightbox = request.POST.get('lightbox', False)
ib = cls.objects.create(
alt=request.POST.get('alt', ''),
caption=request.POST.get('caption', ''),
lightbox=lightbox in ('True', True, 'on'),
image="")
ib.save_image(request.FILES['image'])
return ib
return None

@classmethod
def create_from_dict(cls, d):
# since it's coming from a dict, not a request
# we assume that some other part is handling the writing of
# the image file to disk and we just get a path to it
return cls.objects.create(
image=d.get('image', ''),
alt=d.get('alt', ''),
lightbox=d.get('lightbox', False),
caption=d.get('caption', ''))

def edit(self, vals, files):
self.caption = vals.get('caption', '')
self.alt = vals.get('alt', '')
self.lightbox = vals.get('lightbox', False)
if 'image' in files:
self.save_image(files['image'])
self.save()

def save_image(self, f):
ext = f.name.split(".")[-1].lower()
basename = slugify(f.name.split(".")[-2].lower())[:20]
if ext not in ['jpg', 'jpeg', 'gif', 'png']:
# unsupported image format
return None
now = datetime.now()
path = "images/%04d/%02d/%02d/" % (now.year, now.month, now.day)
full_filename = path + "%s.%s" % (basename, ext)

try:
os.makedirs(settings.MEDIA_ROOT + "/" + path)
fd = self.image.storage.open(
settings.MEDIA_ROOT + "/" + full_filename, 'wb')
except (FileNotFoundError, ValueError):
fd = self.image.storage.open(full_filename, 'wb')

for chunk in f.chunks():
fd.write(chunk)
fd.close()
self.image = full_filename
self.save()

def as_dict(self):
return dict(image=self.image.name,
alt=self.alt,
lightbox=self.lightbox,
caption=self.caption)

def list_resources(self):
return [self.image.url]


class SimpleImageBlock(BasePageBlock):
"""
SimpleImageBlock is ImageBlock without the automatic
Expand Down Expand Up @@ -205,6 +322,101 @@ def save_image(self, f):
self.save()


class ImagePullQuoteBlock(BasePageBlock):
image = ImageWithThumbnailsField(
upload_to="images/%Y/%m/%d",
thumbnail={
'size': (65, 65)
},
extra_thumbnails={
'admin': {
'size': (70, 50),
'options': ('sharpen', ),
}
})
caption = models.TextField(blank=True)
alt = models.CharField(max_length=100, null=True, blank=True)

template_file = "pageblocks/imagepullquoteblock.html"
summary_template_file = "pageblocks/imagepullquoteblock_summary.html"
display_name = "Image Pullquote"

def edit_form(self):
class EditForm(forms.Form):
image = forms.FileField(label="replace image")
caption = forms.CharField(initial=self.caption,
required=False,
widget=forms.widgets.Textarea())
alt = forms.CharField(initial=self.alt, required=False)
return EditForm()

@classmethod
def add_form(cls):
class AddForm(forms.Form):
image = forms.FileField(label="select image")
caption = forms.CharField(widget=forms.widgets.Textarea(),
required=False)
alt = forms.CharField(required=False)
return AddForm()

@classmethod
def create(cls, request):
if 'image' in request.FILES:
ib = cls.objects.create(
caption=request.POST.get('caption', ''),
image="",
alt=request.POST.get('alt', ''))
ib.save_image(request.FILES['image'])
return ib
else:
return None

@classmethod
def create_from_dict(cls, d):
# since it's coming from a dict, not a request
# we assume that some other part is handling the writing of
# the image file to disk and we just get a path to it
return cls.objects.create(
image=d.get('image', ''),
alt=d.get('alt', ''),
caption=d.get('caption', ''))

def edit(self, vals, files):
self.caption = vals.get('caption', '')
self.alt = vals.get('alt', '')
if 'image' in files:
self.save_image(files['image'])
self.save()

def save_image(self, f):
ext = f.name.split(".")[-1].lower()
basename = slugify(f.name.split(".")[-2].lower())[:20]
if ext not in ['jpg', 'jpeg', 'gif', 'png']:
# unsupported image format
return None
now = datetime.now()
path = "images/%04d/%02d/%02d/" % (now.year, now.month, now.day)
try:
os.makedirs(settings.MEDIA_ROOT + "/" + path)
except (FileNotFoundError, ValueError):
pass
full_filename = path + "%s.%s" % (basename, ext)
fd = open(settings.MEDIA_ROOT + "/" + full_filename, 'wb')
for chunk in f.chunks():
fd.write(chunk)
fd.close()
self.image = full_filename
self.save()

def as_dict(self):
return dict(image=self.image.name,
alt=self.alt,
caption=self.caption)

def list_resources(self):
return [self.image.url]


# Using the HTMLBlockWYSIWYG
# Install tinymce into your project: http://code.google.com/p/django-tinymce/
# Override the admin/base-site.html:
Expand Down
Loading

0 comments on commit 215cb73

Please sign in to comment.