-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #247 from OpenUpSA/feature/save-person-images-to-s3
Feature/save person images to s3
- Loading branch information
Showing
23 changed files
with
314 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
from django.contrib import admin | ||
try: | ||
from django.contrib.contenttypes.admin import GenericTabularInline | ||
except ImportError: | ||
# This fallback import is the version that was deprecated in | ||
# Django 1.7 and is removed in 1.9: | ||
from django.contrib.contenttypes.generic import GenericTabularInline | ||
|
||
|
||
from sorl.thumbnail import get_thumbnail | ||
from sorl.thumbnail.admin import AdminImageMixin | ||
|
||
from pombola.core.images import models | ||
|
||
|
||
class ImageAdmin(AdminImageMixin, admin.ModelAdmin): | ||
list_display = [ 'thumbnail', 'content_object', 'is_primary', 'source', ] | ||
search_fields = ['person__legal_name', 'id', 'source'] | ||
|
||
def thumbnail(self, obj): | ||
if obj.image: | ||
im = get_thumbnail(obj.image, '100x100') | ||
return '<img src="%s" />' % ( im.url ) | ||
else: | ||
return "NO IMAGE FOUND" | ||
thumbnail.allow_tags = True | ||
|
||
|
||
class ImageAdminInline(AdminImageMixin, GenericTabularInline): | ||
model = models.Image | ||
extra = 0 | ||
can_delete = True | ||
|
||
admin.site.register( models.Image, ImageAdmin ) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
# -*- coding: utf-8 -*- | ||
from __future__ import unicode_literals | ||
|
||
from django.db import models, migrations | ||
import sorl.thumbnail.fields | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
('contenttypes', '0002_remove_content_type_name'), | ||
] | ||
|
||
operations = [ | ||
migrations.CreateModel( | ||
name='Image', | ||
fields=[ | ||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), | ||
('object_id', models.PositiveIntegerField()), | ||
('image', sorl.thumbnail.fields.ImageField(upload_to=b'images')), | ||
('source', models.CharField(max_length=400)), | ||
('is_primary', models.BooleanField(default=False)), | ||
('content_type', models.ForeignKey(to='contenttypes.ContentType')), | ||
], | ||
), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# -*- coding: utf-8 -*- | ||
from __future__ import unicode_literals | ||
|
||
from django.db import migrations, models | ||
import sorl.thumbnail.fields | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
('images', '0001_initial'), | ||
] | ||
|
||
operations = [ | ||
migrations.AlterField( | ||
model_name='image', | ||
name='image', | ||
field=sorl.thumbnail.fields.ImageField(max_length=512, upload_to=b'images'), | ||
), | ||
] |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
from django.db import models | ||
from django.contrib.contenttypes.models import ContentType | ||
try: | ||
from django.contrib.contenttypes.fields import GenericForeignKey | ||
except ImportError: | ||
# This fallback import is the version that was deprecated in | ||
# Django 1.7 and is removed in 1.9: | ||
from django.contrib.contenttypes.generic import GenericForeignKey | ||
|
||
from sorl.thumbnail import ImageField | ||
|
||
|
||
class Image(models.Model): | ||
|
||
class Meta: | ||
db_table = 'images_image' | ||
|
||
# link to other objects using the ContentType system | ||
content_type = models.ForeignKey(ContentType) | ||
object_id = models.PositiveIntegerField() | ||
content_object = GenericForeignKey('content_type', 'object_id') | ||
|
||
# store the actual image | ||
image = ImageField(upload_to="images", max_length=512) | ||
|
||
# added | ||
source = models.CharField(max_length=400) | ||
# user | ||
|
||
is_primary = models.BooleanField( default=False ) | ||
|
||
def save(self, *args, **kwargs): | ||
""" | ||
Only one image should be marked as is_primary for an object. | ||
""" | ||
|
||
# other images for this object | ||
siblings = Image.objects.filter( | ||
content_type = self.content_type, | ||
object_id = self.object_id, | ||
) | ||
|
||
# check that we are not first entry for content_object | ||
if not siblings.count(): | ||
self.is_primary = True | ||
|
||
super(Image, self).save(*args, **kwargs) | ||
|
||
# If we are true then make sure all others are false | ||
if self.is_primary is True: | ||
|
||
primary_siblings = siblings.exclude( is_primary = False ).exclude( id = self.id ) | ||
|
||
for sibling in primary_siblings: | ||
sibling.is_primary = False | ||
sibling.save() | ||
|
||
|
||
class HasImageMixin(object): | ||
|
||
def primary_image(self): | ||
primary_image_model = self.primary_image_model() | ||
if primary_image_model: | ||
return primary_image_model.image | ||
return None | ||
|
||
def primary_image_model(self): | ||
primary_images = [i for i in self.images.all() if i.is_primary] | ||
if primary_images: | ||
return primary_images[0] | ||
return None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
import os | ||
|
||
from django.test import TestCase | ||
from django.core.files import File | ||
from django.contrib.sites.models import Site | ||
from django.contrib.contenttypes.models import ContentType | ||
|
||
from .models import Image | ||
|
||
from sorl.thumbnail import get_thumbnail | ||
|
||
class ImageTest(TestCase): | ||
|
||
def get_example_file_content(self, filename): | ||
""" | ||
Open the given file and return it | ||
""" | ||
full_path = os.path.join( | ||
os.path.abspath( os.path.dirname(__file__) ), | ||
'tests', | ||
filename, | ||
) | ||
|
||
return File(open(full_path, 'rb')) | ||
|
||
def reload_image(self, image): | ||
"""because there is no reload in Django models (silly really)""" | ||
return Image.objects.get(id=image.id) | ||
|
||
def test_uploading(self): | ||
""" | ||
Test that uploading an image works | ||
""" | ||
|
||
test_site = Site.objects.all()[0] | ||
test_site_ct = ContentType.objects.get_for_model(test_site) | ||
test_site_id = test_site.id | ||
|
||
# check that there are no images | ||
self.assertEqual( Image.objects.all().count(), 0 ) | ||
|
||
# create an image | ||
first = Image( | ||
content_type = test_site_ct, | ||
object_id = test_site_id, | ||
source = 'test directory', | ||
) | ||
first.image.save( | ||
name = 'foo.png', | ||
content = self.get_example_file_content('foo.png'), | ||
) | ||
|
||
# check that the is_primary is true | ||
self.assertTrue( first.is_primary ) | ||
|
||
# create another image | ||
second = Image( | ||
content_type = test_site_ct, | ||
object_id = test_site_id, | ||
source = 'test directory', | ||
) | ||
second.image.save( | ||
name = 'bar.png', | ||
content = self.get_example_file_content('bar.png'), | ||
) | ||
|
||
# check that is_primary is false | ||
self.assertTrue( self.reload_image(first).is_primary ) | ||
self.assertFalse( self.reload_image(second).is_primary ) | ||
|
||
# change is_primary on second image | ||
second.is_primary = True | ||
second.save() | ||
|
||
# check that it changed on first too | ||
self.assertFalse( self.reload_image(first).is_primary ) | ||
self.assertTrue( self.reload_image(second).is_primary ) | ||
|
||
# create a third image with is_primary true at the start | ||
third = Image( | ||
content_type = test_site_ct, | ||
object_id = test_site_id, | ||
source = 'test directory', | ||
is_primary = True, | ||
) | ||
third.image.save( | ||
name = 'baz.png', | ||
content = self.get_example_file_content('baz.png'), | ||
) | ||
|
||
# check that is_primary is updated for all | ||
self.assertFalse( self.reload_image(first).is_primary ) | ||
self.assertFalse( self.reload_image(second).is_primary ) | ||
self.assertTrue( self.reload_image(third).is_primary ) | ||
|
||
# Now try to create an thumbnail with sorl. If this fails | ||
# with "IOError: decoder zip not available", then probably | ||
# this is a problem with an old version of PIL, or one that | ||
# wasn't installed when the right build dependencies were | ||
# present. The simplest solution in most solutions is: | ||
# pip uninstall PIL | ||
# pip install pillow | ||
|
||
get_thumbnail(third.image, '100x100', crop='center', quality=99) |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# This app doesn't provide any URLs |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# Create your views here. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# -*- coding: utf-8 -*- | ||
# Generated by Django 1.11.29 on 2024-12-11 14:11 | ||
from __future__ import unicode_literals | ||
|
||
from django.db import migrations, models | ||
import django.db.models.deletion | ||
import sorl.thumbnail.fields | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
('contenttypes', '0002_remove_content_type_name'), | ||
('core', '0016_auto_20201119_0713'), | ||
] | ||
|
||
operations = [ | ||
migrations.AlterModelOptions( | ||
name='organisationhistory', | ||
options={'ordering': ['date_changed'], 'verbose_name_plural': 'organisation histories'}, | ||
), | ||
migrations.AlterField( | ||
model_name='organisationhistory', | ||
name='new_organisation', | ||
field=models.ForeignKey(default=0, on_delete=django.db.models.deletion.CASCADE, related_name='org_history_new', to='core.Organisation'), | ||
) | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.