##// END OF EJS Templates
Added categories -- a redesign of old-style linked tags, a tree-based...
neko259 -
r1348:f0c5079d default
parent child Browse files
Show More
@@ -0,0 +1,19 b''
1 # -*- coding: utf-8 -*-
2 from __future__ import unicode_literals
3
4 from django.db import models, migrations
5
6
7 class Migration(migrations.Migration):
8
9 dependencies = [
10 ('boards', '0028_auto_20150928_2211'),
11 ]
12
13 operations = [
14 migrations.AddField(
15 model_name='tag',
16 name='parent',
17 field=models.ForeignKey(to='boards.Tag', null=True),
18 ),
19 ]
@@ -0,0 +1,19 b''
1 # -*- coding: utf-8 -*-
2 from __future__ import unicode_literals
3
4 from django.db import models, migrations
5
6
7 class Migration(migrations.Migration):
8
9 dependencies = [
10 ('boards', '0029_tag_parent'),
11 ]
12
13 operations = [
14 migrations.AlterField(
15 model_name='tag',
16 name='parent',
17 field=models.ForeignKey(related_name='children', null=True, to='boards.Tag'),
18 ),
19 ]
@@ -324,20 +324,27 b' class ThreadForm(PostForm):'
324 _('Inappropriate characters in tags.'))
324 _('Inappropriate characters in tags.'))
325
325
326 required_tag_exists = False
326 required_tag_exists = False
327 for tag in tags.split():
327 tag_set = set()
328 try:
328 for tag_string in tags.split():
329 Tag.objects.get(name=tag.strip().lower(), required=True)
329 tag, created = Tag.objects.get_or_create(name=tag_string.strip().lower())
330 tag_set.add(tag)
331
332 # If this is a new tag, don't check for its parents because nobody
333 # added them yet
334 if not created:
335 tag_set |= tag.get_all_parents()
336
337 for tag in tag_set:
338 if tag.required:
330 required_tag_exists = True
339 required_tag_exists = True
331 break
340 break
332 except ObjectDoesNotExist:
333 pass
334
341
335 if not required_tag_exists:
342 if not required_tag_exists:
336 all_tags = Tag.objects.filter(required=True)
343 all_tags = Tag.objects.filter(required=True)
337 raise forms.ValidationError(
344 raise forms.ValidationError(
338 _('Need at least one section.'))
345 _('Need at least one section.'))
339
346
340 return tags
347 return tag_set
341
348
342 def clean(self):
349 def clean(self):
343 cleaned_data = super(ThreadForm, self).clean()
350 cleaned_data = super(ThreadForm, self).clean()
1 NO CONTENT: modified file, binary diff hidden
NO CONTENT: modified file, binary diff hidden
@@ -483,4 +483,10 b' msgid "favorites"'
483 msgstr "ΠΈΠ·Π±Ρ€Π°Π½Π½ΠΎΠ΅"
483 msgstr "ΠΈΠ·Π±Ρ€Π°Π½Π½ΠΎΠ΅"
484
484
485 msgid "Loading..."
485 msgid "Loading..."
486 msgstr "Π—Π°Π³Ρ€ΡƒΠ·ΠΊΠ°..." No newline at end of file
486 msgstr "Π—Π°Π³Ρ€ΡƒΠ·ΠΊΠ°..."
487
488 msgid "Category:"
489 msgstr "ΠšΠ°Ρ‚Π΅Π³ΠΎΡ€ΠΈΡ:"
490
491 msgid "Subcategories:"
492 msgstr "ΠŸΠΎΠ΄ΠΊΠ°Ρ‚Π΅Π³ΠΎΡ€ΠΈΠΈ:"
@@ -48,6 +48,8 b' class Tag(models.Model, Viewable):'
48 required = models.BooleanField(default=False, db_index=True)
48 required = models.BooleanField(default=False, db_index=True)
49 description = models.TextField(blank=True)
49 description = models.TextField(blank=True)
50
50
51 parent = models.ForeignKey('Tag', null=True, related_name='children')
52
51 def __str__(self):
53 def __str__(self):
52 return self.name
54 return self.name
53
55
@@ -115,3 +117,18 b' class Tag(models.Model, Viewable):'
115 Gets color hashed from the tag name.
117 Gets color hashed from the tag name.
116 """
118 """
117 return hashlib.md5(self.name.encode()).hexdigest()[:6]
119 return hashlib.md5(self.name.encode()).hexdigest()[:6]
120
121 def get_parent(self):
122 return self.parent
123
124 def get_all_parents(self):
125 parents = set()
126 parent = self.get_parent()
127 if parent and parent not in parents:
128 parents.add(parent)
129 parents |= parent.get_all_parents()
130
131 return parents
132
133 def get_children(self):
134 return self.children
@@ -73,13 +73,18 b''
73 <p>{{ tag.get_description|safe }}</p>
73 <p>{{ tag.get_description|safe }}</p>
74 {% endif %}
74 {% endif %}
75 <p>{% blocktrans with active_thread_count=tag.get_active_thread_count thread_count=tag.get_thread_count post_count=tag.get_post_count %}This tag has {{ thread_count }} threads ({{ active_thread_count}} active) and {{ post_count }} posts.{% endblocktrans %}</p>
75 <p>{% blocktrans with active_thread_count=tag.get_active_thread_count thread_count=tag.get_thread_count post_count=tag.get_post_count %}This tag has {{ thread_count }} threads ({{ active_thread_count}} active) and {{ post_count }} posts.{% endblocktrans %}</p>
76 {% if related_tags %}
76 {% if tag.get_parent %}
77 <p>{% trans 'Related tags:' %}
77 <p>{% trans 'Category:' %} {{ tag.get_parent.get_view|safe }}</p>
78 {% for rel_tag in related_tags %}
78 {% endif %}
79 {{ rel_tag.get_view|safe }}{% if not forloop.last %}, {% else %}.{% endif %}
79 {% with children=tag.get_children.all %}
80 {% if children %}
81 <p>{% trans 'Subcategories:' %}
82 {% for child in children %}
83 {{ child.get_view|safe }}{% if not forloop.last %}, {% else %}.{% endif %}
80 {% endfor %}
84 {% endfor %}
81 </p>
85 </p>
82 {% endif %}
86 {% endif %}
87 {% endwith %}
83 </div>
88 </div>
84 </div>
89 </div>
85 {% endif %}
90 {% endif %}
@@ -104,24 +104,6 b' class AllThreadsView(PostMixin, BaseBoar'
104 return reverse('index') + '?page=' \
104 return reverse('index') + '?page=' \
105 + str(current_page.next_page_number())
105 + str(current_page.next_page_number())
106
106
107 @staticmethod
108 def parse_tags_string(tag_strings):
109 """
110 Parses tag list string and returns tag object list.
111 """
112
113 tags = []
114
115 if tag_strings:
116 tag_strings = tag_strings.split(TAG_DELIMITER)
117 for tag_name in tag_strings:
118 tag_name = tag_name.strip().lower()
119 if len(tag_name) > 0:
120 tag, created = Tag.objects.get_or_create(name=tag_name)
121 tags.append(tag)
122
123 return tags
124
125 @transaction.atomic
107 @transaction.atomic
126 def create_thread(self, request, form: ThreadForm, html_response=True):
108 def create_thread(self, request, form: ThreadForm, html_response=True):
127 """
109 """
@@ -146,9 +128,7 b' class AllThreadsView(PostMixin, BaseBoar'
146
128
147 text = self._remove_invalid_links(text)
129 text = self._remove_invalid_links(text)
148
130
149 tag_strings = data[FORM_TAGS]
131 tags = data[FORM_TAGS]
150
151 tags = self.parse_tags_string(tag_strings)
152
132
153 post = Post.objects.create_post(title=title, text=text, file=file,
133 post = Post.objects.create_post(title=title, text=text, file=file,
154 ip=ip, tags=tags, opening_posts=threads,
134 ip=ip, tags=tags, opening_posts=threads,
General Comments 0
You need to be logged in to leave comments. Login now