Show More
@@ -1,110 +1,120 b'' | |||
|
1 | 1 | import hashlib |
|
2 | 2 | import os |
|
3 | 3 | from random import random |
|
4 | 4 | import time |
|
5 | ||
|
5 | 6 | from django.db import models |
|
6 | 7 | from django.template.defaultfilters import filesizeformat |
|
8 | ||
|
7 | 9 | from boards import thumbs |
|
10 | import boards | |
|
8 | 11 | from boards.models.base import Viewable |
|
9 | 12 | |
|
10 | 13 | __author__ = 'neko259' |
|
11 | 14 | |
|
12 | 15 | |
|
13 | 16 | IMAGE_THUMB_SIZE = (200, 150) |
|
14 | 17 | IMAGES_DIRECTORY = 'images/' |
|
15 | 18 | FILE_EXTENSION_DELIMITER = '.' |
|
16 | 19 | HASH_LENGTH = 36 |
|
17 | 20 | |
|
18 | 21 | CSS_CLASS_IMAGE = 'image' |
|
19 | 22 | CSS_CLASS_THUMB = 'thumb' |
|
20 | 23 | |
|
21 | 24 | |
|
22 | 25 | class PostImageManager(models.Manager): |
|
23 | 26 | def create_with_hash(self, image): |
|
24 | 27 | image_hash = self.get_hash(image) |
|
25 | 28 | existing = self.filter(hash=image_hash) |
|
26 | 29 | if len(existing) > 0: |
|
27 | 30 | post_image = existing[0] |
|
28 | 31 | else: |
|
29 | 32 | post_image = PostImage.objects.create(image=image) |
|
30 | 33 | |
|
31 | 34 | return post_image |
|
32 | 35 | |
|
33 | 36 | def get_hash(self, image): |
|
34 | 37 | """ |
|
35 | 38 | Gets hash of an image. |
|
36 | 39 | """ |
|
37 | 40 | md5 = hashlib.md5() |
|
38 | 41 | for chunk in image.chunks(): |
|
39 | 42 | md5.update(chunk) |
|
40 | 43 | return md5.hexdigest() |
|
41 | 44 | |
|
45 | def get_random_images(self, count): | |
|
46 | return self.order_by('?')[:count] | |
|
47 | ||
|
42 | 48 | |
|
43 | 49 | class PostImage(models.Model, Viewable): |
|
44 | 50 | objects = PostImageManager() |
|
45 | 51 | |
|
46 | 52 | class Meta: |
|
47 | 53 | app_label = 'boards' |
|
48 | 54 | ordering = ('id',) |
|
49 | 55 | |
|
50 | 56 | def _update_image_filename(self, filename): |
|
51 | 57 | """ |
|
52 | 58 | Gets unique image filename |
|
53 | 59 | """ |
|
54 | 60 | |
|
55 | 61 | path = IMAGES_DIRECTORY |
|
56 | 62 | |
|
57 | 63 | # TODO Use something other than random number in file name |
|
58 | 64 | new_name = '{}{}.{}'.format( |
|
59 | 65 | str(int(time.mktime(time.gmtime()))), |
|
60 | 66 | str(int(random() * 1000)), |
|
61 | 67 | filename.split(FILE_EXTENSION_DELIMITER)[-1:][0]) |
|
62 | 68 | |
|
63 | 69 | return os.path.join(path, new_name) |
|
64 | 70 | |
|
65 | 71 | width = models.IntegerField(default=0) |
|
66 | 72 | height = models.IntegerField(default=0) |
|
67 | 73 | |
|
68 | 74 | pre_width = models.IntegerField(default=0) |
|
69 | 75 | pre_height = models.IntegerField(default=0) |
|
70 | 76 | |
|
71 | 77 | image = thumbs.ImageWithThumbsField(upload_to=_update_image_filename, |
|
72 | 78 | blank=True, sizes=(IMAGE_THUMB_SIZE,), |
|
73 | 79 | width_field='width', |
|
74 | 80 | height_field='height', |
|
75 | 81 | preview_width_field='pre_width', |
|
76 | 82 | preview_height_field='pre_height') |
|
77 | 83 | hash = models.CharField(max_length=HASH_LENGTH) |
|
78 | 84 | |
|
79 | 85 | def save(self, *args, **kwargs): |
|
80 | 86 | """ |
|
81 | 87 | Saves the model and computes the image hash for deduplication purposes. |
|
82 | 88 | """ |
|
83 | 89 | |
|
84 | 90 | if not self.pk and self.image: |
|
85 | 91 | self.hash = PostImage.objects.get_hash(self.image) |
|
86 | 92 | super(PostImage, self).save(*args, **kwargs) |
|
87 | 93 | |
|
88 | 94 | def __str__(self): |
|
89 | 95 | return self.image.url |
|
90 | 96 | |
|
91 | 97 | def get_view(self): |
|
92 | 98 | metadata = '{}, {}'.format(self.image.name.split('.')[-1], |
|
93 | 99 | filesizeformat(self.image.size)) |
|
94 | 100 | return '<div class="{}">' \ |
|
95 | 101 | '<a class="{}" href="{full}">' \ |
|
96 | 102 | '<img class="post-image-preview"' \ |
|
97 | 103 | ' src="{}"' \ |
|
98 | 104 | ' alt="{}"' \ |
|
99 | 105 | ' width="{}"' \ |
|
100 | 106 | ' height="{}"' \ |
|
101 | 107 | ' data-width="{}"' \ |
|
102 | 108 | ' data-height="{}" />' \ |
|
103 | 109 | '</a>' \ |
|
104 | 110 | '<div class="image-metadata">{image_meta}</div>' \ |
|
105 | 111 | '</div>'\ |
|
106 | 112 | .format(CSS_CLASS_IMAGE, CSS_CLASS_THUMB, |
|
107 | 113 | self.image.url_200x150, |
|
108 | 114 | str(self.hash), str(self.pre_width), |
|
109 | 115 | str(self.pre_height), str(self.width), str(self.height), |
|
110 | 116 | full=self.image.url, image_meta=metadata) |
|
117 | ||
|
118 | def get_random_associated_post(self): | |
|
119 | return boards.models.Post.objects.filter(images__in=[self])\ | |
|
120 | .order_by('?').first() |
@@ -1,32 +1,32 b'' | |||
|
1 | 1 | {% extends "boards/base.html" %} |
|
2 | 2 | |
|
3 | 3 | {% load i18n %} |
|
4 | 4 | |
|
5 | 5 | {% block head %} |
|
6 | 6 | <title>{% trans 'Random images' %} - {{ site_name }}</title> |
|
7 | 7 | {% endblock %} |
|
8 | 8 | |
|
9 | 9 | {% block content %} |
|
10 | 10 | |
|
11 |
{% if |
|
|
11 | {% if images %} | |
|
12 | 12 | <div class="random-images-table"> |
|
13 | 13 | <div> |
|
14 |
{% for |
|
|
14 | {% for image in images %} | |
|
15 | 15 | <div class="gallery_image"> |
|
16 | {% with post.get_first_image as image %} | |
|
17 | 16 | {% autoescape off %} |
|
18 | 17 | {{ image.get_view }} |
|
19 | 18 | {% endautoescape %} |
|
19 | {% with image.get_random_associated_post as post %} | |
|
20 | 20 | <a href="{{ post.get_absolute_url }}">>>{{ post.id }}</a> |
|
21 | 21 | {% endwith %} |
|
22 | 22 | </div> |
|
23 | 23 | {% if forloop.counter|divisibleby:"3" %} |
|
24 | 24 | </div> |
|
25 | 25 | <div> |
|
26 | 26 | {% endif %} |
|
27 | 27 | {% endfor %} |
|
28 | 28 | </div> |
|
29 | 29 | </div> |
|
30 | 30 | {% endif %} |
|
31 | 31 | |
|
32 | 32 | {% endblock %} |
@@ -1,28 +1,22 b'' | |||
|
1 | 1 | from django.shortcuts import render |
|
2 | from django.template import RequestContext | |
|
3 | 2 | from django.views.generic import View |
|
4 | from django.db.models import Count | |
|
5 | 3 | |
|
6 | from boards.models import Post | |
|
7 | from boards.mdx_neboard import Parser | |
|
4 | from boards.models import PostImage | |
|
8 | 5 | |
|
9 | 6 | __author__ = 'neko259' |
|
10 | 7 | |
|
11 | 8 | TEMPLATE = 'boards/random.html' |
|
12 | 9 | |
|
13 |
CONTEXT_ |
|
|
10 | CONTEXT_IMAGES = 'images' | |
|
14 | 11 | |
|
15 | 12 | RANDOM_POST_COUNT = 9 |
|
16 | 13 | |
|
17 | 14 | |
|
18 | 15 | class RandomImageView(View): |
|
19 | 16 | def get(self, request): |
|
20 | 17 | params = dict() |
|
21 | 18 | |
|
22 | posts = Post.objects.annotate(images_count=Count( | |
|
23 | 'images')).filter(images_count__gt=0).order_by('?')\ | |
|
24 | [:RANDOM_POST_COUNT] | |
|
25 | ||
|
26 | params[CONTEXT_POSTS] = posts | |
|
19 | params[CONTEXT_IMAGES] = PostImage.objects.get_random_images( | |
|
20 | RANDOM_POST_COUNT) | |
|
27 | 21 | |
|
28 | 22 | return render(request, TEMPLATE, params) |
General Comments 0
You need to be logged in to leave comments.
Login now