diff --git a/boards/migrations/0017_auto__add_field_post_image_pre_width__add_field_post_image_pre_height.py b/boards/migrations/0017_auto__add_field_post_image_pre_width__add_field_post_image_pre_height.py new file mode 100644 --- /dev/null +++ b/boards/migrations/0017_auto__add_field_post_image_pre_width__add_field_post_image_pre_height.py @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- +from south.utils import datetime_utils as datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding field 'Post.image_pre_width' + db.add_column(u'boards_post', 'image_pre_width', + self.gf('django.db.models.fields.IntegerField')(default=0), + keep_default=False) + + # Adding field 'Post.image_pre_height' + db.add_column(u'boards_post', 'image_pre_height', + self.gf('django.db.models.fields.IntegerField')(default=0), + keep_default=False) + + + def backwards(self, orm): + # Deleting field 'Post.image_pre_width' + db.delete_column(u'boards_post', 'image_pre_width') + + # Deleting field 'Post.image_pre_height' + db.delete_column(u'boards_post', 'image_pre_height') + + + models = { + 'boards.ban': { + 'Meta': {'object_name': 'Ban'}, + 'can_read': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}), + 'reason': ('django.db.models.fields.CharField', [], {'default': "'Auto'", 'max_length': '200'}) + }, + 'boards.post': { + 'Meta': {'object_name': 'Post'}, + '_text_rendered': ('django.db.models.fields.TextField', [], {}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'image': ('boards.thumbs.ImageWithThumbsField', [], {'max_length': '100', 'blank': 'True'}), + 'image_height': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'image_pre_height': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'image_pre_width': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'image_width': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'last_edit_time': ('django.db.models.fields.DateTimeField', [], {}), + 'poster_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}), + 'poster_user_agent': ('django.db.models.fields.TextField', [], {}), + 'pub_time': ('django.db.models.fields.DateTimeField', [], {}), + 'referenced_posts': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'rfp+'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['boards.Post']"}), + 'text': ('markupfield.fields.MarkupField', [], {'rendered_field': 'True'}), + 'text_markup_type': ('django.db.models.fields.CharField', [], {'default': "'markdown'", 'max_length': '30'}), + 'thread': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['boards.Post']", 'null': 'True'}), + 'thread_new': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['boards.Thread']", 'null': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['boards.User']", 'null': 'True'}) + }, + 'boards.setting': { + 'Meta': {'object_name': 'Setting'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['boards.User']"}), + 'value': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'boards.tag': { + 'Meta': {'object_name': 'Tag'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'linked': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['boards.Tag']", 'null': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'threads': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'tag+'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['boards.Thread']"}) + }, + 'boards.thread': { + 'Meta': {'object_name': 'Thread'}, + 'bump_time': ('django.db.models.fields.DateTimeField', [], {}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_edit_time': ('django.db.models.fields.DateTimeField', [], {}), + 'replies': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'tre+'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['boards.Post']"}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['boards.Tag']", 'symmetrical': 'False'}) + }, + 'boards.user': { + 'Meta': {'object_name': 'User'}, + 'fav_tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['boards.Tag']", 'null': 'True', 'blank': 'True'}), + 'fav_threads': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['boards.Post']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'rank': ('django.db.models.fields.IntegerField', [], {}), + 'registration_time': ('django.db.models.fields.DateTimeField', [], {}), + 'user_id': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + } + } + + complete_apps = ['boards'] \ No newline at end of file diff --git a/boards/models/post.py b/boards/models/post.py --- a/boards/models/post.py +++ b/boards/models/post.py @@ -235,10 +235,15 @@ class Post(models.Model): image_width = models.IntegerField(default=0) image_height = models.IntegerField(default=0) + image_pre_width = models.IntegerField(default=0) + image_pre_height = models.IntegerField(default=0) + image = thumbs.ImageWithThumbsField(upload_to=_update_image_filename, blank=True, sizes=(IMAGE_THUMB_SIZE,), width_field='image_width', - height_field='image_height') + height_field='image_height', + preview_width_field='image_pre_width', + preview_height_field='image_pre_height') poster_ip = models.GenericIPAddressField() poster_user_agent = models.TextField() diff --git a/boards/static/css/md/base_page.css b/boards/static/css/md/base_page.css --- a/boards/static/css/md/base_page.css +++ b/boards/static/css/md/base_page.css @@ -173,8 +173,6 @@ blockquote { min-width: 1px; text-align: center; display: table-row; - - height: 150px; } .post > .metadata { diff --git a/boards/static/css/pg/base_page.css b/boards/static/css/pg/base_page.css --- a/boards/static/css/pg/base_page.css +++ b/boards/static/css/pg/base_page.css @@ -171,8 +171,6 @@ blockquote { min-width: 1px; text-align: center; display: table-row; - - height: 150px; } .post > .metadata { diff --git a/boards/templates/boards/posting_general.html b/boards/templates/boards/posting_general.html --- a/boards/templates/boards/posting_general.html +++ b/boards/templates/boards/posting_general.html @@ -79,6 +79,8 @@ href="{{ thread.op.image.url }}">{{ thread.op.id }} @@ -154,6 +156,8 @@ href="{{ post.image.url }}">{{ post.id }} @@ -227,7 +231,7 @@ {% block metapanel %} - Neboard 1.4.1 + Neboard 1.5 {% trans "Pages:" %} {% for page in pages %} [{{ post.id }} diff --git a/boards/thumbs.py b/boards/thumbs.py --- a/boards/thumbs.py +++ b/boards/thumbs.py @@ -3,6 +3,7 @@ django-thumbs by Antonio Melé http://django.es """ +from django.core.files.images import ImageFile from django.db.models import ImageField from django.db.models.fields.files import ImageFieldFile from PIL import Image @@ -13,13 +14,13 @@ import cStringIO def generate_thumb(img, thumb_size, format): """ Generates a thumbnail image and returns a ContentFile object with the thumbnail - + Parameters: =========== img File object - + thumb_size desired thumbnail size, ie: (200,120) - + format format of the original image ('jpeg','gif','png',...) (this format will be used for the generated thumbnail, too) """ @@ -41,7 +42,7 @@ def generate_thumb(img, thumb_size, form # crop it image2 = image.crop( (xnewsize, ynewsize, xsize - xnewsize, ysize - ynewsize)) - # load is necessary after crop + # load is necessary after crop image2.load() # thumbnail of the cropped image (with ANTIALIAS to make it look better) image2.thumbnail(thumb_size, Image.ANTIALIAS) @@ -160,7 +161,9 @@ class ImageWithThumbsField(ImageField): """ def __init__(self, verbose_name=None, name=None, width_field=None, - height_field=None, sizes=None, **kwargs): + height_field=None, sizes=None, + preview_width_field=None, preview_height_field=None, + **kwargs): self.verbose_name = verbose_name self.name = name self.width_field = width_field @@ -168,6 +171,46 @@ class ImageWithThumbsField(ImageField): self.sizes = sizes super(ImageField, self).__init__(**kwargs) + if sizes is not None and len(sizes) == 1: + self.preview_width_field = preview_width_field + self.preview_height_field = preview_height_field + + def update_dimension_fields(self, instance, force=False, *args, **kwargs): + """ + Update original image dimension fields and thumb dimension fields + (only if 1 thumb size is defined) + """ + + super(ImageWithThumbsField, self).update_dimension_fields(instance, + force, *args, + **kwargs) + thumb_width_field = self.preview_width_field + thumb_height_field = self.preview_height_field + + if thumb_width_field is None or thumb_height_field is None \ + or len(self.sizes) != 1: + return + + original_width = getattr(instance, self.width_field) + original_height = getattr(instance, self.height_field) + + if original_width > 0 and original_height > 0: + thumb_width, thumb_height = self.sizes[0] + + w_scale = float(thumb_width) / original_width + h_scale = float(thumb_height) / original_height + scale_ratio = min(w_scale, h_scale) + + if scale_ratio >= 1: + thumb_width_ratio = original_width + thumb_height_ratio = original_height + else: + thumb_width_ratio = int(original_width * scale_ratio) + thumb_height_ratio = int(original_height * scale_ratio) + + setattr(instance, thumb_width_field, thumb_width_ratio) + setattr(instance, thumb_height_field, thumb_height_ratio) + from south.modelsinspector import add_introspection_rules add_introspection_rules([], ["^boards\.thumbs\.ImageWithThumbsField"])