diff --git a/app/photos/api/image_edit.py b/app/photos/api/image_edit.py index cc04da6..d1ea481 100644 --- a/app/photos/api/image_edit.py +++ b/app/photos/api/image_edit.py @@ -1,5 +1,12 @@ -from PIL import Image, ImageFilter, ImageOps, ImageStat, ImageEnhance, ImageDraw, ImageFont -import base64, cStringIO, os +from PIL import ( + Image, ImageFilter, + ImageOps, ImageStat, + ImageEnhance, ImageDraw, + ImageFont +) +import base64 +import cStringIO +import os class ImageEdit: @@ -53,23 +60,30 @@ def filter(self, filter_type): self.output = self.output.filter(self.filters[filter_type]) def enhance(self, enhance_type, value): - """ Used to enhance image brightness, color, contrast and sharpness. """ - method = getattr(ImageEnhance,enhance_type) + """ + Used to enhance image brightness, + color, contrast and sharpness. + """ + method = getattr(ImageEnhance, enhance_type) if method: actual_value = (value/100) * self.max_enhance enhancement = method(self.output) self.output = enhancement.enhance(actual_value) def quantize(self, value=256): - """ Convert the image to 'P' mode with the specified number of colors. """ - actual_value = float(value)/100 * 256; + """ + Convert the image to 'P' mode with the + specified number of colors. + """ + actual_value = float(value)/100 * 256 self.output = self.output.quantize(int(actual_value)) self.output = self.output.convert('RGB') def gaussian_blur(self, radius): """ Gaussian blur filter. """ actual_value = float(radius)/100 * 20 - self.output = self.output.filter(ImageFilter.GaussianBlur(int(actual_value))) + self.output = self.output.filter( + ImageFilter.GaussianBlur(int(actual_value))) def auto_contrast(self, cutoff=0): """ Normalize image contrast. """ @@ -95,7 +109,7 @@ def solarize(self, threshold=128): def remove_border(self, border_size=0): """ Remove border from image. """ - actual_value = float(border_size)/100 * 200; + actual_value = float(border_size)/100 * 200 self.output = ImageOps.crop(self.output, int(actual_value)) def rotate(self, value): @@ -122,22 +136,26 @@ def mirror(self): self.output = ImageOps.mirror(self.output) def set_font(self, font='Honey-I-spilt-Verdana.ttf', font_size=100): - fonts_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'static/fonts') + fonts_path = os.path.join( + os.path.dirname(os.path.dirname( + os.path.dirname(__file__))), 'static/fonts') self.font = ImageFont.truetype(fonts_path + '/' + font, font_size) - def text(self, text, x, y, fill=(255,255,255)): + def text(self, text, x, y, fill=(255, 255, 255)): draw = ImageDraw.Draw(self.output) if not self.font: self.set_font() - draw.text((x,y), text, font=self.font, fill=fill) + draw.text((x, y), text, font=self.font, fill=fill) del draw - def line(self, start_x=0, end_x=100, start_y=0, end_y=100, fill="#fff", width=50): + def line(self, start_x=0, end_x=100, start_y=0, + end_y=100, fill="#fff", width=50): draw = ImageDraw.Draw(self.output) draw.line((start_x, start_y, end_x, end_y), fill=fill, width=width) del draw - def rectangle(self, start_x=0, end_x=100, start_y=0, end_y=100, fill="#fff"): + def rectangle(self, start_x=0, end_x=100, + start_y=0, end_y=100, fill="#fff"): draw = ImageDraw.Draw(self.output) draw.rectangle((start_x, start_y, end_x, end_y), fill=fill) del draw @@ -149,7 +167,9 @@ def preview(self): def save(self): path = self.path.replace('main', 'edited') - edit_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'media_cdn/edited') + edit_path = os.path.join( + os.path.dirname(os.path.dirname( + os.path.dirname(__file__))), 'media_cdn/edited') if not os.path.exists(edit_path): os.makedirs(edit_path) self.output.save(path, format=self.image_format) diff --git a/app/photos/api/image_processor.py b/app/photos/api/image_processor.py index 6b8ade5..bee0532 100644 --- a/app/photos/api/image_processor.py +++ b/app/photos/api/image_processor.py @@ -1,6 +1,8 @@ from image_edit import * + class ImageProcessor: + def __init__(self, photo): self.image = photo.image self.image_editor = ImageEdit(photo.image.path) @@ -22,7 +24,8 @@ def save(self): def enhance(self, effect_data): for effect_data_type in effect_data: - self.image_editor.enhance(effect_data_type, float(effect_data[effect_data_type])) + self.image_editor.enhance( + effect_data_type, float(effect_data[effect_data_type])) def filter(self, effect_data): for effect_data_type in effect_data: @@ -39,4 +42,3 @@ def effect(self, effect_data): method = getattr(self.image_editor, effect_data_type) if method: method(effect_data[effect_data_type]) - diff --git a/app/photos/api/serializers.py b/app/photos/api/serializers.py index 3c2d320..bcd5848 100644 --- a/app/photos/api/serializers.py +++ b/app/photos/api/serializers.py @@ -7,7 +7,6 @@ ) from photos.models import * -import cloudinary class UserSerializer(ModelSerializer): @@ -36,6 +35,7 @@ def create(self, validated_data): class FolderSerializer(ModelSerializer): photos = SerializerMethodField() + class Meta: model = Folder fields = [ @@ -49,7 +49,6 @@ class Meta: extra_kwargs = {'date_created': {'read_only': True}, 'date_modified': {'read_only': True}} - def get_photos(self, obj): serialized_photos = [] photos = obj.photo_set.all() @@ -98,7 +97,6 @@ class Meta: extra_kwargs = {'date_created': {'read_only': True}, 'date_modified': {'read_only': True}} - def get_folder_name(self, obj): try: return obj.folder.name @@ -114,6 +112,6 @@ def get_file_size(self, obj): def get_detail(self, obj): detail = PhotoDetail.objects.filter(photo=obj).first() if(not detail): - return {}; + return {} serializer = PhotoDetailSerializer(detail) return serializer.data diff --git a/app/photos/api/views.py b/app/photos/api/views.py index be34dc3..4c8ce55 100644 --- a/app/photos/api/views.py +++ b/app/photos/api/views.py @@ -1,8 +1,9 @@ from django.contrib.auth.models import User -import json, cloudinary from django.shortcuts import get_object_or_404 from django.views.generic import View from django.http import HttpResponse, HttpResponseNotFound +import json +import time from rest_framework.generics import ( ListCreateAPIView, RetrieveUpdateDestroyAPIView, @@ -19,7 +20,7 @@ from .serializers import * from .permissions import IsOwner from image_processor import * -import time + class RegistrationApiView(CreateAPIView): queryset = User.objects.all() @@ -28,6 +29,7 @@ class RegistrationApiView(CreateAPIView): class LoginApiView(View): + def post(self, request, *args, **kwargs): username = request.POST.get('username', '') password = request.POST.get('password', '') @@ -37,15 +39,15 @@ def post(self, request, *args, **kwargs): if user.is_active: login(request, user) response_data.update( - {'login':True, 'user': user.username} + {'login': True, 'user': user.username} ) else: response_data.update( - {'login':False, 'message': 'User inactive'} + {'login': False, 'message': 'User inactive'} ) else: response_data.update( - {'login':False, 'message': 'Invalid credentials'} + {'login': False, 'message': 'Invalid credentials'} ) response_json = json.dumps(response_data) @@ -53,20 +55,23 @@ def post(self, request, *args, **kwargs): class PhotoPreview(View): + def post(self, request, *args, **kwargs): photo_id = request.POST.get('photo_id', 0) effects = request.POST.get('effects', '') effect_obj = json.loads(effects) photo = Photo.objects.filter(id=photo_id).first() - response_data = {'image':''} + response_data = {'image': ''} if photo: image_processor = ImageProcessor(photo) image_processor.process(effect_obj) - response_data = {'image':image_processor.preview()} + response_data = {'image': image_processor.preview()} response_json = json.dumps(response_data) return HttpResponse(response_json, content_type="application/json") + class PhotoShare(View): + def get(self, request, *args, **kwargs): share_id = request.GET.get('share_id', None) response_data = {} @@ -109,6 +114,7 @@ def get_queryset(self): queryset = Folder.objects.filter(user=self.request.user) return queryset + class PhotoApiView(ListCreateAPIView): """ @@ -133,25 +139,26 @@ class PhotoApiView(ListCreateAPIView): # before create def perform_create(self, serializer): folder_id = self.request.POST.get('folder_id', 0) - folder = Folder.objects.filter(user=self.request.user, id=folder_id).first() + folder = Folder.objects.filter( + user=self.request.user, id=folder_id).first() code = int(time.time()) if folder is not None: - instance = serializer.save(user=self.request.user, folder=folder, share_code=code) + instance = serializer.save( + user=self.request.user, folder=folder, share_code=code) else: instance = serializer.save(user=self.request.user, share_code=code) detail = PhotoDetail(photo=instance) detail.save() - - def get_queryset(self): folder_id = self.kwargs.get('id', -1) if int(folder_id) == 0: return Photo.objects.filter(user=self.request.user, folder=0) folder = Folder.objects.filter(id=folder_id) if(folder): - queryset = Photo.objects.filter(user=self.request.user, folder=folder) + queryset = Photo.objects.filter( + user=self.request.user, folder=folder) else: queryset = Photo.objects.filter(user=self.request.user) return queryset @@ -182,7 +189,6 @@ class SingleFolderAPIView(RetrieveUpdateDestroyAPIView): lookup_field = 'id' - class SinglePhotoAPIView(RetrieveUpdateDestroyAPIView): """ @@ -238,11 +244,9 @@ def perform_update(self, serializer): effect_obj = json.loads(instance.effects) image_processor.process(effect_obj) edited_path = image_processor.save() - photo.edited_image = edited_path; + photo.edited_image = edited_path photo.save() - - def get_queryset(self): photo = Photo.objects.filter(id=self.kwargs.get('id', 0)).first() return PhotoDetail.objects.filter(photo=photo) diff --git a/app/photos/migrations/0001_initial.py b/app/photos/migrations/0001_initial.py index 71de49e..8ac8c74 100644 --- a/app/photos/migrations/0001_initial.py +++ b/app/photos/migrations/0001_initial.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Generated by Django 1.9.2 on 2016-07-01 09:13 +# Generated by Django 1.9.2 on 2016-07-15 12:05 from __future__ import unicode_literals from django.conf import settings @@ -30,4 +30,34 @@ class Migration(migrations.Migration): 'ordering': ['-date_created'], }, ), + migrations.CreateModel( + name='Photo', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('image', models.ImageField(blank=True, null=True, upload_to='main')), + ('edited_image', models.CharField(default='', max_length=255)), + ('share_code', models.CharField(default='', max_length=50)), + ('date_modified', models.DateTimeField(auto_now=True)), + ('date_created', models.DateTimeField(auto_now_add=True)), + ('folder', models.ForeignKey(default=0, on_delete=django.db.models.deletion.CASCADE, to='photos.Folder')), + ('user', models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + options={ + 'ordering': ['-date_created'], + }, + ), + migrations.CreateModel( + name='PhotoDetail', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(default='', max_length=100)), + ('effects', models.TextField(default='')), + ('date_modified', models.DateTimeField(auto_now=True)), + ('date_created', models.DateTimeField(auto_now_add=True)), + ('photo', models.ForeignKey(default=0, on_delete=django.db.models.deletion.CASCADE, to='photos.Photo')), + ], + options={ + 'ordering': ['-date_created'], + }, + ), ] diff --git a/app/photos/migrations/0002_photo.py b/app/photos/migrations/0002_photo.py deleted file mode 100644 index d14ea6e..0000000 --- a/app/photos/migrations/0002_photo.py +++ /dev/null @@ -1,32 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.9.2 on 2016-07-05 15:13 -from __future__ import unicode_literals - -import cloudinary.models -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('photos', '0001_initial'), - ] - - operations = [ - migrations.CreateModel( - name='Photo', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('image', cloudinary.models.CloudinaryField(max_length=255, verbose_name='image')), - ('date_modified', models.DateTimeField(auto_now=True)), - ('date_created', models.DateTimeField(auto_now_add=True)), - ('user', models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), - ], - options={ - 'ordering': ['-date_created'], - }, - ), - ] diff --git a/app/photos/migrations/0003_photo_title.py b/app/photos/migrations/0003_photo_title.py deleted file mode 100644 index c626422..0000000 --- a/app/photos/migrations/0003_photo_title.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.9.2 on 2016-07-06 15:58 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('photos', '0002_photo'), - ] - - operations = [ - migrations.AddField( - model_name='photo', - name='title', - field=models.CharField(default='', max_length=120), - ), - ] diff --git a/app/photos/migrations/0004_auto_20160707_1343.py b/app/photos/migrations/0004_auto_20160707_1343.py deleted file mode 100644 index a1ff1b3..0000000 --- a/app/photos/migrations/0004_auto_20160707_1343.py +++ /dev/null @@ -1,37 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.9.2 on 2016-07-07 13:43 -from __future__ import unicode_literals - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('photos', '0003_photo_title'), - ] - - operations = [ - migrations.CreateModel( - name='PhotoDetail', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('title', models.CharField(max_length=100)), - ('date_modified', models.DateTimeField(auto_now=True)), - ('date_created', models.DateTimeField(auto_now_add=True)), - ], - options={ - 'ordering': ['-date_created'], - }, - ), - migrations.RemoveField( - model_name='photo', - name='title', - ), - migrations.AddField( - model_name='photodetail', - name='photo', - field=models.ForeignKey(default=0, on_delete=django.db.models.deletion.CASCADE, to='photos.Photo'), - ), - ] diff --git a/app/photos/migrations/0005_auto_20160707_2007.py b/app/photos/migrations/0005_auto_20160707_2007.py deleted file mode 100644 index aeb37c5..0000000 --- a/app/photos/migrations/0005_auto_20160707_2007.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.9.2 on 2016-07-07 20:07 -from __future__ import unicode_literals - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('photos', '0004_auto_20160707_1343'), - ] - - operations = [ - migrations.AddField( - model_name='photo', - name='folder', - field=models.ForeignKey(default=0, on_delete=django.db.models.deletion.CASCADE, to='photos.Folder'), - ), - migrations.AddField( - model_name='photodetail', - name='effects', - field=models.TextField(default=''), - ), - ] diff --git a/app/photos/migrations/0006_auto_20160708_1326.py b/app/photos/migrations/0006_auto_20160708_1326.py deleted file mode 100644 index 1bf8ca4..0000000 --- a/app/photos/migrations/0006_auto_20160708_1326.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.9.2 on 2016-07-08 13:26 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('photos', '0005_auto_20160707_2007'), - ] - - operations = [ - migrations.AlterField( - model_name='photo', - name='image', - field=models.FileField(upload_to='files/%Y/%m/%d'), - ), - migrations.AlterField( - model_name='photodetail', - name='title', - field=models.CharField(default='', max_length=100), - ), - ] diff --git a/app/photos/migrations/0007_auto_20160708_1356.py b/app/photos/migrations/0007_auto_20160708_1356.py deleted file mode 100644 index 3a90999..0000000 --- a/app/photos/migrations/0007_auto_20160708_1356.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.9.2 on 2016-07-08 13:56 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('photos', '0006_auto_20160708_1326'), - ] - - operations = [ - migrations.AlterField( - model_name='photo', - name='image', - field=models.ImageField(blank=True, null=True, upload_to='%Y/%m/%d'), - ), - ] diff --git a/app/photos/migrations/0008_auto_20160713_1348.py b/app/photos/migrations/0008_auto_20160713_1348.py deleted file mode 100644 index 625465b..0000000 --- a/app/photos/migrations/0008_auto_20160713_1348.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.9.2 on 2016-07-13 13:48 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('photos', '0007_auto_20160708_1356'), - ] - - operations = [ - migrations.AddField( - model_name='photo', - name='edited_image', - field=models.CharField(default='', max_length=255), - ), - migrations.AlterField( - model_name='photo', - name='image', - field=models.ImageField(blank=True, null=True, upload_to='main'), - ), - ] diff --git a/app/photos/migrations/0009_photo_share_code.py b/app/photos/migrations/0009_photo_share_code.py deleted file mode 100644 index 31313b7..0000000 --- a/app/photos/migrations/0009_photo_share_code.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.9.2 on 2016-07-13 20:55 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('photos', '0008_auto_20160713_1348'), - ] - - operations = [ - migrations.AddField( - model_name='photo', - name='share_code', - field=models.CharField(default='', max_length=50), - ), - ] diff --git a/app/photos/models.py b/app/photos/models.py index 3ebc20c..0a61857 100644 --- a/app/photos/models.py +++ b/app/photos/models.py @@ -1,7 +1,6 @@ from __future__ import unicode_literals from django.db import models from django.conf import settings -from cloudinary.models import CloudinaryField class Folder(models.Model): diff --git a/app/static/build/client.min.js b/app/static/build/client.min.js index 89ce4a7..ceb49fd 100644 --- a/app/static/build/client.min.js +++ b/app/static/build/client.min.js @@ -52567,7 +52567,7 @@ { className: 'row' }, _react2.default.createElement( 'ul', - { className: 'nav nav-tabs' }, + { className: 'nav nav-tabs row' }, _react2.default.createElement( 'li', { className: 'active' }, diff --git a/app/static/components/Effects.jsx b/app/static/components/Effects.jsx index 0c2462e..38a6311 100644 --- a/app/static/components/Effects.jsx +++ b/app/static/components/Effects.jsx @@ -7,7 +7,7 @@ export default class extends React.Component { const {change, check, effects} = this.props; return (
-