From 5db6a4987ce6ef95a7b3b8116e82918ae5106a62 Mon Sep 17 00:00:00 2001 From: Krystyna Date: Wed, 19 Sep 2018 20:18:59 +0200 Subject: [PATCH 1/2] models - added image to organization --- backend/apps/volontulo/models.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/backend/apps/volontulo/models.py b/backend/apps/volontulo/models.py index f4a85cf0..2a5910f8 100644 --- a/backend/apps/volontulo/models.py +++ b/backend/apps/volontulo/models.py @@ -36,6 +36,11 @@ class Organization(models.Model): name = models.CharField(max_length=150, db_index=True) address = models.CharField(max_length=150) description = models.TextField() + image = models.ImageField( + upload_to=upload_to_offers, + null=True, + blank=True + ) def __str__(self): """Organization model string reprezentation.""" From 0871855e535567eebe83eebf9a57f9fe9fc8d2c8 Mon Sep 17 00:00:00 2001 From: Krystyna Date: Wed, 31 Oct 2018 20:31:48 +0100 Subject: [PATCH 2/2] images for organizations --- backend/apps/volontulo/factories.py | 4 +++ .../management/commands/populate_database.py | 6 +++- .../migrations/0018_organization_image.py | 21 ++++++++++++ backend/apps/volontulo/models.py | 17 +++++++++- backend/apps/volontulo/serializers.py | 32 ++++++++++--------- backend/apps/volontulo/tests/common.py | 1 + .../views/api/organizations/test_list.py | 1 + .../views/api/organizations/test_read.py | 1 + 8 files changed, 66 insertions(+), 17 deletions(-) create mode 100644 backend/apps/volontulo/migrations/0018_organization_image.py diff --git a/backend/apps/volontulo/factories.py b/backend/apps/volontulo/factories.py index ac1d88b1..699b4579 100644 --- a/backend/apps/volontulo/factories.py +++ b/backend/apps/volontulo/factories.py @@ -134,6 +134,10 @@ class Meta: # pylint: disable=C0111 name = factory.fuzzy.FuzzyAttribute(_organization_name) address = factory.Faker("address", locale="pl_PL") description = factory.Faker("paragraph") + image = ImageField(from_path=os.path.join( + os.path.dirname(__file__), + 'static/volontulo/img/volontulo_baner.png' + )) def placeimg_com_download(width, height, category): diff --git a/backend/apps/volontulo/management/commands/populate_database.py b/backend/apps/volontulo/management/commands/populate_database.py index 8486fee4..23533a79 100644 --- a/backend/apps/volontulo/management/commands/populate_database.py +++ b/backend/apps/volontulo/management/commands/populate_database.py @@ -24,7 +24,11 @@ def handle(self, *args, **options): self.stdout.write(self.style.SUCCESS('Creating 15 organizations')) for _ in tqdm(range(15)): - organization = OrganizationFactory.create() + organization = OrganizationFactory.create( + image=ImageField( + from_func=placeimg_com_download(1000, 400, 'any') + ) + ) UserProfileFactory.create( organizations=(organization,), ) diff --git a/backend/apps/volontulo/migrations/0018_organization_image.py b/backend/apps/volontulo/migrations/0018_organization_image.py new file mode 100644 index 00000000..311314a0 --- /dev/null +++ b/backend/apps/volontulo/migrations/0018_organization_image.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.5 on 2018-10-31 18:45 +from __future__ import unicode_literals + +import apps.volontulo.models +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('volontulo', '0017_remove_offer_recruitment_status'), + ] + + operations = [ + migrations.AddField( + model_name='organization', + name='image', + field=models.ImageField(blank=True, null=True, upload_to=apps.volontulo.models.upload_to_organizations), + ), + ] diff --git a/backend/apps/volontulo/models.py b/backend/apps/volontulo/models.py index 2a5910f8..5acb4ce8 100644 --- a/backend/apps/volontulo/models.py +++ b/backend/apps/volontulo/models.py @@ -31,13 +31,28 @@ def upload_to_offers(_, filename): ) +def upload_to_organizations(_, filename): + """ + Upload to organizations path. + + This needs to be a full-body func because + migrations requires it to be serializable. + """ + _, file_extension = os.path.splitext(filename) + return os.path.join( + 'organizations', + '{}{}'.format(uuid.uuid4(), file_extension), + ) + + class Organization(models.Model): """Model that handles ogranizations/institutions.""" name = models.CharField(max_length=150, db_index=True) address = models.CharField(max_length=150) description = models.TextField() + image = models.ImageField( - upload_to=upload_to_offers, + upload_to=upload_to_organizations, null=True, blank=True ) diff --git a/backend/apps/volontulo/serializers.py b/backend/apps/volontulo/serializers.py index 31a8ea66..de29f1d6 100644 --- a/backend/apps/volontulo/serializers.py +++ b/backend/apps/volontulo/serializers.py @@ -31,9 +31,25 @@ def run_validation(self, data=empty): return data +class ImageField(serializers.Field): + + """Custom field for offer's image serialization.""" + + def to_representation(self, value): + """Transform internal value into serializer representation.""" + return self.context['request'].build_absolute_uri( + location=value.url + ) if value else None + + def to_internal_value(self, data): + """Transform serializer representation into internal value.""" + return io.BytesIO(base64.b64decode(data)) + + class OrganizationSerializer(serializers.HyperlinkedModelSerializer): """REST API organizations serializer.""" slug = serializers.SerializerMethodField() + image = ImageField(allow_null=True, required=False) class Meta: model = models.Organization @@ -41,6 +57,7 @@ class Meta: 'address', 'description', 'id', + 'image', 'name', 'slug', 'url', @@ -77,21 +94,6 @@ def to_internal_value(self, data): ) -class ImageField(serializers.Field): - - """Custom field for offer's image serialization.""" - - def to_representation(self, value): - """Transform internal value into serializer representation.""" - return self.context['request'].build_absolute_uri( - location=value.url - ) if value else None - - def to_internal_value(self, data): - """Transform serializer representation into internal value.""" - return io.BytesIO(base64.b64decode(data)) - - class OfferSerializer(serializers.HyperlinkedModelSerializer): """REST API offers serializer.""" diff --git a/backend/apps/volontulo/tests/common.py b/backend/apps/volontulo/tests/common.py index 060d8878..53cc2e56 100644 --- a/backend/apps/volontulo/tests/common.py +++ b/backend/apps/volontulo/tests/common.py @@ -101,6 +101,7 @@ def test_offer_list_fields(self, offer): self.assertIsInstance(offer['organization'].pop('address'), str) self.assertIsInstance(offer['organization'].pop('description'), str) self.assertIsInstance(offer['organization'].pop('id'), int) + self.assertIsInstance(offer['organization'].pop('image'), str) self.assertIsInstance(offer['organization'].pop('name'), str) self.assertIsInstance(offer['organization'].pop('slug'), str) self.assertIsInstance(offer['organization'].pop('url'), str) diff --git a/backend/apps/volontulo/tests/views/api/organizations/test_list.py b/backend/apps/volontulo/tests/views/api/organizations/test_list.py index 7ebaa606..0b72d968 100644 --- a/backend/apps/volontulo/tests/views/api/organizations/test_list.py +++ b/backend/apps/volontulo/tests/views/api/organizations/test_list.py @@ -22,6 +22,7 @@ def test_organization_list_fields(self): self.assertIsInstance(organization.pop('address'), str) self.assertIsInstance(organization.pop('description'), str) self.assertIsInstance(organization.pop('id'), int) + self.assertIsInstance(organization.pop('image'), str) self.assertIsInstance(organization.pop('name'), str) self.assertIsInstance(organization.pop('slug'), str) self.assertIsInstance(organization.pop('url'), str) diff --git a/backend/apps/volontulo/tests/views/api/organizations/test_read.py b/backend/apps/volontulo/tests/views/api/organizations/test_read.py index 541beb62..6cc85a73 100644 --- a/backend/apps/volontulo/tests/views/api/organizations/test_read.py +++ b/backend/apps/volontulo/tests/views/api/organizations/test_read.py @@ -20,6 +20,7 @@ def _test_organization_read_fields(self, organization): self.assertIsInstance(organization.pop('address'), str) self.assertIsInstance(organization.pop('description'), str) self.assertIsInstance(organization.pop('id'), int) + self.assertIsInstance(organization.pop('image'), str) self.assertIsInstance(organization.pop('name'), str) self.assertIsInstance(organization.pop('slug'), str) self.assertIsInstance(organization.pop('url'), str)