Show More
@@ -0,0 +1,86 b'' | |||||
|
1 | # -*- coding: utf-8 -*- | |||
|
2 | from south.utils import datetime_utils as datetime | |||
|
3 | from south.db import db | |||
|
4 | from south.v2 import SchemaMigration | |||
|
5 | from django.db import models | |||
|
6 | ||||
|
7 | ||||
|
8 | class Migration(SchemaMigration): | |||
|
9 | ||||
|
10 | def forwards(self, orm): | |||
|
11 | # Adding field 'Post.image_hash' | |||
|
12 | db.add_column(u'boards_post', 'image_hash', | |||
|
13 | self.gf('django.db.models.fields.CharField')(default='', max_length=36), | |||
|
14 | keep_default=False) | |||
|
15 | ||||
|
16 | ||||
|
17 | def backwards(self, orm): | |||
|
18 | # Deleting field 'Post.image_hash' | |||
|
19 | db.delete_column(u'boards_post', 'image_hash') | |||
|
20 | ||||
|
21 | ||||
|
22 | models = { | |||
|
23 | 'boards.ban': { | |||
|
24 | 'Meta': {'object_name': 'Ban'}, | |||
|
25 | 'can_read': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | |||
|
26 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | |||
|
27 | 'ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}), | |||
|
28 | 'reason': ('django.db.models.fields.CharField', [], {'default': "'Auto'", 'max_length': '200'}) | |||
|
29 | }, | |||
|
30 | 'boards.post': { | |||
|
31 | 'Meta': {'object_name': 'Post'}, | |||
|
32 | '_text_rendered': ('django.db.models.fields.TextField', [], {}), | |||
|
33 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | |||
|
34 | 'image': ('boards.thumbs.ImageWithThumbsField', [], {'max_length': '100', 'blank': 'True'}), | |||
|
35 | 'image_hash': ('django.db.models.fields.CharField', [], {'max_length': '36'}), | |||
|
36 | 'image_height': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | |||
|
37 | 'image_pre_height': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | |||
|
38 | 'image_pre_width': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | |||
|
39 | 'image_width': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | |||
|
40 | 'last_edit_time': ('django.db.models.fields.DateTimeField', [], {}), | |||
|
41 | 'poster_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}), | |||
|
42 | 'poster_user_agent': ('django.db.models.fields.TextField', [], {}), | |||
|
43 | 'pub_time': ('django.db.models.fields.DateTimeField', [], {}), | |||
|
44 | 'referenced_posts': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'rfp+'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['boards.Post']"}), | |||
|
45 | 'text': ('markupfield.fields.MarkupField', [], {'rendered_field': 'True'}), | |||
|
46 | 'text_markup_type': ('django.db.models.fields.CharField', [], {'default': "'markdown'", 'max_length': '30'}), | |||
|
47 | 'thread': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['boards.Post']", 'null': 'True'}), | |||
|
48 | 'thread_new': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['boards.Thread']", 'null': 'True'}), | |||
|
49 | 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'}), | |||
|
50 | 'user': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['boards.User']", 'null': 'True'}) | |||
|
51 | }, | |||
|
52 | 'boards.setting': { | |||
|
53 | 'Meta': {'object_name': 'Setting'}, | |||
|
54 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | |||
|
55 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}), | |||
|
56 | 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['boards.User']"}), | |||
|
57 | 'value': ('django.db.models.fields.CharField', [], {'max_length': '50'}) | |||
|
58 | }, | |||
|
59 | 'boards.tag': { | |||
|
60 | 'Meta': {'object_name': 'Tag'}, | |||
|
61 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | |||
|
62 | 'linked': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['boards.Tag']", 'null': 'True', 'blank': 'True'}), | |||
|
63 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | |||
|
64 | 'threads': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'tag+'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['boards.Thread']"}) | |||
|
65 | }, | |||
|
66 | 'boards.thread': { | |||
|
67 | 'Meta': {'object_name': 'Thread'}, | |||
|
68 | 'archived': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | |||
|
69 | 'bump_time': ('django.db.models.fields.DateTimeField', [], {}), | |||
|
70 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | |||
|
71 | 'last_edit_time': ('django.db.models.fields.DateTimeField', [], {}), | |||
|
72 | 'replies': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'tre+'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['boards.Post']"}), | |||
|
73 | 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['boards.Tag']", 'symmetrical': 'False'}) | |||
|
74 | }, | |||
|
75 | 'boards.user': { | |||
|
76 | 'Meta': {'object_name': 'User'}, | |||
|
77 | 'fav_tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['boards.Tag']", 'null': 'True', 'blank': 'True'}), | |||
|
78 | 'fav_threads': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['boards.Post']"}), | |||
|
79 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | |||
|
80 | 'rank': ('django.db.models.fields.IntegerField', [], {}), | |||
|
81 | 'registration_time': ('django.db.models.fields.DateTimeField', [], {}), | |||
|
82 | 'user_id': ('django.db.models.fields.CharField', [], {'max_length': '50'}) | |||
|
83 | } | |||
|
84 | } | |||
|
85 | ||||
|
86 | complete_apps = ['boards'] No newline at end of file |
@@ -0,0 +1,91 b'' | |||||
|
1 | # -*- coding: utf-8 -*- | |||
|
2 | import hashlib | |||
|
3 | ||||
|
4 | from south.utils import datetime_utils as datetime | |||
|
5 | from south.db import db | |||
|
6 | from south.v2 import DataMigration | |||
|
7 | from django.db import models | |||
|
8 | ||||
|
9 | class Migration(DataMigration): | |||
|
10 | ||||
|
11 | def forwards(self, orm): | |||
|
12 | # Note: Don't use "from appname.models import ModelName". | |||
|
13 | # Use orm.ModelName to refer to models in this application, | |||
|
14 | # and orm['appname.ModelName'] for models in other applications. | |||
|
15 | for post in orm.Post.objects.filter(image_width__gt=0): | |||
|
16 | md5 = hashlib.md5() | |||
|
17 | for chunk in post.image.chunks(): | |||
|
18 | md5.update(chunk) | |||
|
19 | image_hash = md5.hexdigest() | |||
|
20 | post.image_hash = image_hash | |||
|
21 | post.save() | |||
|
22 | ||||
|
23 | def backwards(self, orm): | |||
|
24 | "Write your backwards methods here." | |||
|
25 | ||||
|
26 | models = { | |||
|
27 | 'boards.ban': { | |||
|
28 | 'Meta': {'object_name': 'Ban'}, | |||
|
29 | 'can_read': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | |||
|
30 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | |||
|
31 | 'ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}), | |||
|
32 | 'reason': ('django.db.models.fields.CharField', [], {'default': "'Auto'", 'max_length': '200'}) | |||
|
33 | }, | |||
|
34 | 'boards.post': { | |||
|
35 | 'Meta': {'object_name': 'Post'}, | |||
|
36 | '_text_rendered': ('django.db.models.fields.TextField', [], {}), | |||
|
37 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | |||
|
38 | 'image': ('boards.thumbs.ImageWithThumbsField', [], {'max_length': '100', 'blank': 'True'}), | |||
|
39 | 'image_hash': ('django.db.models.fields.CharField', [], {'max_length': '36'}), | |||
|
40 | 'image_height': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | |||
|
41 | 'image_pre_height': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | |||
|
42 | 'image_pre_width': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | |||
|
43 | 'image_width': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | |||
|
44 | 'last_edit_time': ('django.db.models.fields.DateTimeField', [], {}), | |||
|
45 | 'poster_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}), | |||
|
46 | 'poster_user_agent': ('django.db.models.fields.TextField', [], {}), | |||
|
47 | 'pub_time': ('django.db.models.fields.DateTimeField', [], {}), | |||
|
48 | 'referenced_posts': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'rfp+'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['boards.Post']"}), | |||
|
49 | 'text': ('markupfield.fields.MarkupField', [], {'rendered_field': 'True'}), | |||
|
50 | 'text_markup_type': ('django.db.models.fields.CharField', [], {'default': "'markdown'", 'max_length': '30'}), | |||
|
51 | 'thread': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['boards.Post']", 'null': 'True'}), | |||
|
52 | 'thread_new': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['boards.Thread']", 'null': 'True'}), | |||
|
53 | 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'}), | |||
|
54 | 'user': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['boards.User']", 'null': 'True'}) | |||
|
55 | }, | |||
|
56 | 'boards.setting': { | |||
|
57 | 'Meta': {'object_name': 'Setting'}, | |||
|
58 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | |||
|
59 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}), | |||
|
60 | 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['boards.User']"}), | |||
|
61 | 'value': ('django.db.models.fields.CharField', [], {'max_length': '50'}) | |||
|
62 | }, | |||
|
63 | 'boards.tag': { | |||
|
64 | 'Meta': {'object_name': 'Tag'}, | |||
|
65 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | |||
|
66 | 'linked': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['boards.Tag']", 'null': 'True', 'blank': 'True'}), | |||
|
67 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | |||
|
68 | 'threads': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'tag+'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['boards.Thread']"}) | |||
|
69 | }, | |||
|
70 | 'boards.thread': { | |||
|
71 | 'Meta': {'object_name': 'Thread'}, | |||
|
72 | 'archived': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | |||
|
73 | 'bump_time': ('django.db.models.fields.DateTimeField', [], {}), | |||
|
74 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | |||
|
75 | 'last_edit_time': ('django.db.models.fields.DateTimeField', [], {}), | |||
|
76 | 'replies': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'tre+'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['boards.Post']"}), | |||
|
77 | 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['boards.Tag']", 'symmetrical': 'False'}) | |||
|
78 | }, | |||
|
79 | 'boards.user': { | |||
|
80 | 'Meta': {'object_name': 'User'}, | |||
|
81 | 'fav_tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['boards.Tag']", 'null': 'True', 'blank': 'True'}), | |||
|
82 | 'fav_threads': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['boards.Post']"}), | |||
|
83 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | |||
|
84 | 'rank': ('django.db.models.fields.IntegerField', [], {}), | |||
|
85 | 'registration_time': ('django.db.models.fields.DateTimeField', [], {}), | |||
|
86 | 'user_id': ('django.db.models.fields.CharField', [], {'max_length': '50'}) | |||
|
87 | } | |||
|
88 | } | |||
|
89 | ||||
|
90 | complete_apps = ['boards'] | |||
|
91 | symmetrical = True |
@@ -1,12 +1,15 b'' | |||||
1 | import re |
|
1 | import re | |
|
2 | import time | |||
|
3 | import hashlib | |||
|
4 | ||||
2 | from captcha.fields import CaptchaField |
|
5 | from captcha.fields import CaptchaField | |
3 | from django import forms |
|
6 | from django import forms | |
4 | from django.forms.util import ErrorList |
|
7 | from django.forms.util import ErrorList | |
5 | from django.utils.translation import ugettext_lazy as _ |
|
8 | from django.utils.translation import ugettext_lazy as _ | |
6 | import time |
|
9 | ||
7 | from boards.mdx_neboard import formatters |
|
10 | from boards.mdx_neboard import formatters | |
8 | from boards.models.post import TITLE_MAX_LENGTH |
|
11 | from boards.models.post import TITLE_MAX_LENGTH | |
9 | from boards.models import User |
|
12 | from boards.models import User, Post | |
10 | from neboard import settings |
|
13 | from neboard import settings | |
11 | from boards import utils |
|
14 | from boards import utils | |
12 | import boards.settings as board_settings |
|
15 | import boards.settings as board_settings | |
@@ -19,6 +22,11 b" TEXT_PLACEHOLDER = _('''Type message her" | |||||
19 | this. 2 new lines are required to start new paragraph.''') |
|
22 | this. 2 new lines are required to start new paragraph.''') | |
20 | TAGS_PLACEHOLDER = _('tag1 several_words_tag') |
|
23 | TAGS_PLACEHOLDER = _('tag1 several_words_tag') | |
21 |
|
24 | |||
|
25 | ERROR_IMAGE_DUPLICATE = _('Such image was already posted') | |||
|
26 | ||||
|
27 | LABEL_TITLE = _('Title') | |||
|
28 | LABEL_TEXT = _('Text') | |||
|
29 | ||||
22 |
|
30 | |||
23 | class FormatPanel(forms.Textarea): |
|
31 | class FormatPanel(forms.Textarea): | |
24 | def render(self, name, value, attrs=None): |
|
32 | def render(self, name, value, attrs=None): | |
@@ -74,10 +82,10 b' class NeboardForm(forms.Form):' | |||||
74 | class PostForm(NeboardForm): |
|
82 | class PostForm(NeboardForm): | |
75 |
|
83 | |||
76 | title = forms.CharField(max_length=TITLE_MAX_LENGTH, required=False, |
|
84 | title = forms.CharField(max_length=TITLE_MAX_LENGTH, required=False, | |
77 |
label= |
|
85 | label=LABEL_TITLE) | |
78 | text = forms.CharField( |
|
86 | text = forms.CharField( | |
79 | widget=FormatPanel(attrs={ATTRIBUTE_PLACEHOLDER: TEXT_PLACEHOLDER}), |
|
87 | widget=FormatPanel(attrs={ATTRIBUTE_PLACEHOLDER: TEXT_PLACEHOLDER}), | |
80 |
required=False, label= |
|
88 | required=False, label=LABEL_TEXT) | |
81 | image = forms.ImageField(required=False, label=_('Image')) |
|
89 | image = forms.ImageField(required=False, label=_('Image')) | |
82 |
|
90 | |||
83 | # This field is for spam prevention only |
|
91 | # This field is for spam prevention only | |
@@ -114,6 +122,14 b' class PostForm(NeboardForm):' | |||||
114 | raise forms.ValidationError( |
|
122 | raise forms.ValidationError( | |
115 | _('Image must be less than %s bytes') |
|
123 | _('Image must be less than %s bytes') | |
116 | % str(board_settings.MAX_IMAGE_SIZE)) |
|
124 | % str(board_settings.MAX_IMAGE_SIZE)) | |
|
125 | ||||
|
126 | md5 = hashlib.md5() | |||
|
127 | for chunk in image.chunks(): | |||
|
128 | md5.update(chunk) | |||
|
129 | image_hash = md5.hexdigest() | |||
|
130 | if Post.objects.filter(image_hash=image_hash).exists(): | |||
|
131 | raise forms.ValidationError(ERROR_IMAGE_DUPLICATE) | |||
|
132 | ||||
117 | return image |
|
133 | return image | |
118 |
|
134 | |||
119 | def clean(self): |
|
135 | def clean(self): |
1 | NO CONTENT: modified file, binary diff hidden |
|
NO CONTENT: modified file, binary diff hidden |
@@ -7,7 +7,7 b' msgid ""' | |||||
7 | msgstr "" |
|
7 | msgstr "" | |
8 | "Project-Id-Version: PACKAGE VERSION\n" |
|
8 | "Project-Id-Version: PACKAGE VERSION\n" | |
9 | "Report-Msgid-Bugs-To: \n" |
|
9 | "Report-Msgid-Bugs-To: \n" | |
10 |
"POT-Creation-Date: 2014-01-1 |
|
10 | "POT-Creation-Date: 2014-01-15 10:46+0200\n" | |
11 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" |
|
11 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" | |
12 | "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" |
|
12 | "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" | |
13 | "Language-Team: LANGUAGE <LL@li.org>\n" |
|
13 | "Language-Team: LANGUAGE <LL@li.org>\n" | |
@@ -34,7 +34,7 b' msgstr "\xd1\x80\xd0\xb0\xd0\xb7\xd1\x80\xd0\xb0\xd0\xb1\xd0\xbe\xd1\x82\xd1\x87\xd0\xb8\xd0\xba javascript"' | |||||
34 | msgid "designer" |
|
34 | msgid "designer" | |
35 | msgstr "дизайнер" |
|
35 | msgstr "дизайнер" | |
36 |
|
36 | |||
37 |
#: forms.py:1 |
|
37 | #: forms.py:21 | |
38 | msgid "" |
|
38 | msgid "" | |
39 | "Type message here. You can reply to message >>123 like\n" |
|
39 | "Type message here. You can reply to message >>123 like\n" | |
40 | " this. 2 new lines are required to start new paragraph." |
|
40 | " this. 2 new lines are required to start new paragraph." | |
@@ -42,75 +42,79 b' msgstr ""' | |||||
42 | "Введите сообщение здесь. Вы можете ответить на сообщение >>123 вот так. 2 " |
|
42 | "Введите сообщение здесь. Вы можете ответить на сообщение >>123 вот так. 2 " | |
43 | "переноса строки обязательны для создания нового абзаца." |
|
43 | "переноса строки обязательны для создания нового абзаца." | |
44 |
|
44 | |||
45 |
#: forms.py:2 |
|
45 | #: forms.py:23 | |
46 | msgid "tag1 several_words_tag" |
|
46 | msgid "tag1 several_words_tag" | |
47 | msgstr "тег1 тег_из_нескольких_слов" |
|
47 | msgstr "тег1 тег_из_нескольких_слов" | |
48 |
|
48 | |||
49 |
#: forms.py: |
|
49 | #: forms.py:25 | |
|
50 | msgid "Such image was already posted" | |||
|
51 | msgstr "Такое изображение уже было загружено" | |||
|
52 | ||||
|
53 | #: forms.py:27 | |||
50 | msgid "Title" |
|
54 | msgid "Title" | |
51 | msgstr "Заголовок" |
|
55 | msgstr "Заголовок" | |
52 |
|
56 | |||
53 |
#: forms.py:8 |
|
57 | #: forms.py:28 | |
54 | msgid "Text" |
|
58 | msgid "Text" | |
55 | msgstr "Текст" |
|
59 | msgstr "Текст" | |
56 |
|
60 | |||
57 |
#: forms.py:8 |
|
61 | #: forms.py:89 | |
58 | msgid "Image" |
|
62 | msgid "Image" | |
59 | msgstr "Изображение" |
|
63 | msgstr "Изображение" | |
60 |
|
64 | |||
61 |
#: forms.py: |
|
65 | #: forms.py:92 | |
62 | msgid "e-mail" |
|
66 | msgid "e-mail" | |
63 | msgstr "" |
|
67 | msgstr "" | |
64 |
|
68 | |||
65 |
#: forms.py: |
|
69 | #: forms.py:103 | |
66 | #, python-format |
|
70 | #, python-format | |
67 | msgid "Title must have less than %s characters" |
|
71 | msgid "Title must have less than %s characters" | |
68 | msgstr "Заголовок должен иметь меньше %s символов" |
|
72 | msgstr "Заголовок должен иметь меньше %s символов" | |
69 |
|
73 | |||
70 |
#: forms.py:1 |
|
74 | #: forms.py:112 | |
71 | #, python-format |
|
75 | #, python-format | |
72 | msgid "Text must have less than %s characters" |
|
76 | msgid "Text must have less than %s characters" | |
73 | msgstr "Текст должен быть короче %s символов" |
|
77 | msgstr "Текст должен быть короче %s символов" | |
74 |
|
78 | |||
75 |
#: forms.py:1 |
|
79 | #: forms.py:123 | |
76 | #, python-format |
|
80 | #, python-format | |
77 | msgid "Image must be less than %s bytes" |
|
81 | msgid "Image must be less than %s bytes" | |
78 | msgstr "Изображение должно быть менее %s байт" |
|
82 | msgstr "Изображение должно быть менее %s байт" | |
79 |
|
83 | |||
80 |
#: forms.py:1 |
|
84 | #: forms.py:158 | |
81 | msgid "Either text or image must be entered." |
|
85 | msgid "Either text or image must be entered." | |
82 | msgstr "Текст или картинка должны быть введены." |
|
86 | msgstr "Текст или картинка должны быть введены." | |
83 |
|
87 | |||
84 |
#: forms.py:1 |
|
88 | #: forms.py:171 | |
85 | #, python-format |
|
89 | #, python-format | |
86 | msgid "Wait %s seconds after last posting" |
|
90 | msgid "Wait %s seconds after last posting" | |
87 | msgstr "Подождите %s секунд после последнего постинга" |
|
91 | msgstr "Подождите %s секунд после последнего постинга" | |
88 |
|
92 | |||
89 |
#: forms.py:17 |
|
93 | #: forms.py:187 templates/boards/tags.html:6 templates/boards/rss/post.html:10 | |
90 | msgid "Tags" |
|
94 | msgid "Tags" | |
91 | msgstr "Теги" |
|
95 | msgstr "Теги" | |
92 |
|
96 | |||
93 |
#: forms.py:1 |
|
97 | #: forms.py:195 | |
94 | msgid "Inappropriate characters in tags." |
|
98 | msgid "Inappropriate characters in tags." | |
95 | msgstr "Недопустимые символы в тегах." |
|
99 | msgstr "Недопустимые символы в тегах." | |
96 |
|
100 | |||
97 |
#: forms.py:2 |
|
101 | #: forms.py:223 forms.py:244 | |
98 | msgid "Captcha validation failed" |
|
102 | msgid "Captcha validation failed" | |
99 | msgstr "Проверка капчи провалена" |
|
103 | msgstr "Проверка капчи провалена" | |
100 |
|
104 | |||
101 |
#: forms.py:2 |
|
105 | #: forms.py:250 | |
102 | msgid "Theme" |
|
106 | msgid "Theme" | |
103 | msgstr "Тема" |
|
107 | msgstr "Тема" | |
104 |
|
108 | |||
105 |
#: forms.py:2 |
|
109 | #: forms.py:255 | |
106 | msgid "Enable moderation panel" |
|
110 | msgid "Enable moderation panel" | |
107 | msgstr "Включить панель модерации" |
|
111 | msgstr "Включить панель модерации" | |
108 |
|
112 | |||
109 |
#: forms.py:2 |
|
113 | #: forms.py:270 | |
110 | msgid "No such user found" |
|
114 | msgid "No such user found" | |
111 | msgstr "Данный пользователь не найден" |
|
115 | msgstr "Данный пользователь не найден" | |
112 |
|
116 | |||
113 |
#: forms.py:2 |
|
117 | #: forms.py:284 | |
114 | #, python-format |
|
118 | #, python-format | |
115 | msgid "Wait %s minutes after last login" |
|
119 | msgid "Wait %s minutes after last login" | |
116 | msgstr "Подождите %s минут после последнего входа" |
|
120 | msgstr "Подождите %s минут после последнего входа" |
@@ -5,6 +5,8 b' from random import random' | |||||
5 | import time |
|
5 | import time | |
6 | import math |
|
6 | import math | |
7 | import re |
|
7 | import re | |
|
8 | import hashlib | |||
|
9 | ||||
8 | from django.core.cache import cache |
|
10 | from django.core.cache import cache | |
9 | from django.core.paginator import Paginator |
|
11 | from django.core.paginator import Paginator | |
10 |
|
12 | |||
@@ -232,6 +234,7 b' class Post(models.Model):' | |||||
232 | height_field='image_height', |
|
234 | height_field='image_height', | |
233 | preview_width_field='image_pre_width', |
|
235 | preview_width_field='image_pre_width', | |
234 | preview_height_field='image_pre_height') |
|
236 | preview_height_field='image_pre_height') | |
|
237 | image_hash = models.CharField(max_length=36) | |||
235 |
|
238 | |||
236 | poster_ip = models.GenericIPAddressField() |
|
239 | poster_ip = models.GenericIPAddressField() | |
237 | poster_user_agent = models.TextField() |
|
240 | poster_user_agent = models.TextField() | |
@@ -265,6 +268,18 b' class Post(models.Model):' | |||||
265 | def is_opening(self): |
|
268 | def is_opening(self): | |
266 | return self.thread_new.get_replies()[0] == self |
|
269 | return self.thread_new.get_replies()[0] == self | |
267 |
|
270 | |||
|
271 | def save(self, *args, **kwargs): | |||
|
272 | """ | |||
|
273 | Save the model and compute the image hash | |||
|
274 | """ | |||
|
275 | ||||
|
276 | if not self.pk and self.image: | |||
|
277 | md5 = hashlib.md5() | |||
|
278 | for chunk in self.image.chunks(): | |||
|
279 | md5.update(chunk) | |||
|
280 | self.image_hash = md5.hexdigest() | |||
|
281 | super(Post, self).save(*args, **kwargs) | |||
|
282 | ||||
268 |
|
283 | |||
269 | class Thread(models.Model): |
|
284 | class Thread(models.Model): | |
270 |
|
285 |
@@ -160,6 +160,9 b' class ImageWithThumbsField(ImageField):' | |||||
160 |
|
160 | |||
161 | """ |
|
161 | """ | |
162 |
|
162 | |||
|
163 | preview_width_field = None | |||
|
164 | preview_height_field = None | |||
|
165 | ||||
163 | def __init__(self, verbose_name=None, name=None, width_field=None, |
|
166 | def __init__(self, verbose_name=None, name=None, width_field=None, | |
164 | height_field=None, sizes=None, |
|
167 | height_field=None, sizes=None, | |
165 | preview_width_field=None, preview_height_field=None, |
|
168 | preview_width_field=None, preview_height_field=None, |
General Comments 0
You need to be logged in to leave comments.
Login now