##// END OF EJS Templates
Added thread field to the post. 'parent' field is deprecated now.
neko259 -
r174:481c6224 default
parent child Browse files
Show More
@@ -0,0 +1,72 b''
1 # -*- coding: utf-8 -*-
2 import 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.thread'
12 db.add_column(u'boards_post', 'thread',
13 self.gf('django.db.models.fields.related.ForeignKey')(default=None, to=orm['boards.Post'], null=True),
14 keep_default=False)
15
16
17 def backwards(self, orm):
18 # Deleting field 'Post.thread'
19 db.delete_column(u'boards_post', 'thread_id')
20
21
22 models = {
23 u'boards.ban': {
24 'Meta': {'object_name': 'Ban'},
25 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
26 'ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'})
27 },
28 u'boards.post': {
29 'Meta': {'object_name': 'Post'},
30 '_text_rendered': ('django.db.models.fields.TextField', [], {}),
31 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
32 'image': ('boards.thumbs.ImageWithThumbsField', [], {'max_length': '100', 'blank': 'True'}),
33 'image_height': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
34 'image_width': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
35 'last_edit_time': ('django.db.models.fields.DateTimeField', [], {}),
36 'parent': ('django.db.models.fields.BigIntegerField', [], {}),
37 'poster_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}),
38 'poster_user_agent': ('django.db.models.fields.TextField', [], {}),
39 'pub_time': ('django.db.models.fields.DateTimeField', [], {}),
40 'replies': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'re+'", 'null': 'True', 'symmetrical': 'False', 'to': u"orm['boards.Post']"}),
41 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['boards.Tag']", 'symmetrical': 'False'}),
42 'text': ('markupfield.fields.MarkupField', [], {'rendered_field': 'True'}),
43 'text_markup_type': ('django.db.models.fields.CharField', [], {'default': "'markdown'", 'max_length': '30'}),
44 'thread': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['boards.Post']", 'null': 'True'}),
45 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
46 'user': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['boards.User']", 'null': 'True'})
47 },
48 u'boards.setting': {
49 'Meta': {'object_name': 'Setting'},
50 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
51 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
52 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['boards.User']"}),
53 'value': ('django.db.models.fields.CharField', [], {'max_length': '50'})
54 },
55 u'boards.tag': {
56 'Meta': {'object_name': 'Tag'},
57 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
58 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
59 },
60 u'boards.user': {
61 'Meta': {'object_name': 'User'},
62 'fav_tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['boards.Tag']", 'null': 'True', 'blank': 'True'}),
63 'fav_threads': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'symmetrical': 'False', 'to': u"orm['boards.Post']"}),
64 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
65 'last_access_time': ('django.db.models.fields.DateTimeField', [], {}),
66 'rank': ('django.db.models.fields.IntegerField', [], {}),
67 'registration_time': ('django.db.models.fields.DateTimeField', [], {}),
68 'user_id': ('django.db.models.fields.CharField', [], {'max_length': '50'})
69 }
70 }
71
72 complete_apps = ['boards'] No newline at end of file
@@ -33,27 +33,26 b' RANK_USER = 100'
33
33
34
34
35 class PostManager(models.Manager):
35 class PostManager(models.Manager):
36 def create_post(self, title, text, image=None, parent_id=NO_PARENT,
36 def create_post(self, title, text, image=None, thread=None,
37 ip=NO_IP, tags=None, user=None):
37 ip=NO_IP, tags=None, user=None):
38 post = self.create(title=title,
38 post = self.create(title=title,
39 text=text,
39 text=text,
40 pub_time=timezone.now(),
40 pub_time=timezone.now(),
41 parent=parent_id,
41 thread=thread,
42 image=image,
42 image=image,
43 poster_ip=ip,
43 poster_ip=ip,
44 poster_user_agent=UNKNOWN_UA,
44 poster_user_agent=UNKNOWN_UA,
45 last_edit_time=timezone.now(),
45 last_edit_time=timezone.now(),
46 user=user)
46 user=user)
47
47
48 if parent_id != NO_PARENT:
48 if thread:
49 parent = self.get(id=parent_id)
49 thread.replies.add(post)
50 parent.replies.add(post)
51
50
52 if tags:
51 if tags:
53 map(post.tags.add, tags)
52 map(post.tags.add, tags)
54
53
55 if parent_id != NO_PARENT:
54 if thread:
56 self._bump_thread(parent_id)
55 thread.bump()
57 else:
56 else:
58 self._delete_old_threads()
57 self._delete_old_threads()
59
58
@@ -61,7 +60,7 b' class PostManager(models.Manager):'
61
60
62 def delete_post(self, post):
61 def delete_post(self, post):
63 if post.replies.count() > 0:
62 if post.replies.count() > 0:
64 map(self.delete_post, post.replies)
63 map(self.delete_post, post.replies.all())
65 post.delete()
64 post.delete()
66
65
67 def delete_posts_by_ip(self, ip):
66 def delete_posts_by_ip(self, ip):
@@ -71,11 +70,15 b' class PostManager(models.Manager):'
71 def get_threads(self, tag=None, page=ALL_PAGES,
70 def get_threads(self, tag=None, page=ALL_PAGES,
72 order_by='-last_edit_time'):
71 order_by='-last_edit_time'):
73 if tag:
72 if tag:
74 threads = self.filter(parent=NO_PARENT, tags=tag)
73 threads = self.filter(thread=None, tags=tag)
74
75 # TODO This needs to be uncommented when 'all tags' view won't
76 # use this method to get threads for tag
75
77
76 # TODO Throw error 404 if no threads for tag found?
78 # if threads.count() == 0:
79 # raise Http404
77 else:
80 else:
78 threads = self.filter(parent=NO_PARENT)
81 threads = self.filter(thread=None)
79
82
80 threads = threads.order_by(order_by)
83 threads = threads.order_by(order_by)
81
84
@@ -92,7 +95,7 b' class PostManager(models.Manager):'
92
95
93 def get_thread(self, opening_post_id):
96 def get_thread(self, opening_post_id):
94 try:
97 try:
95 opening_post = self.get(id=opening_post_id, parent=NO_PARENT)
98 opening_post = self.get(id=opening_post_id, thread=None)
96 except Post.DoesNotExist:
99 except Post.DoesNotExist:
97 raise Http404
100 raise Http404
98
101
@@ -109,9 +112,9 b' class PostManager(models.Manager):'
109
112
110 def get_thread_page_count(self, tag=None):
113 def get_thread_page_count(self, tag=None):
111 if tag:
114 if tag:
112 threads = self.filter(parent=NO_PARENT, tags=tag)
115 threads = self.filter(thread=None, tags=tag)
113 else:
116 else:
114 threads = self.filter(parent=NO_PARENT)
117 threads = self.filter(thread=None)
115
118
116 return int(math.ceil(threads.count() / float(
119 return int(math.ceil(threads.count() / float(
117 settings.THREADS_PER_PAGE)))
120 settings.THREADS_PER_PAGE)))
@@ -225,8 +228,9 b' class Post(models.Model):'
225 poster_user_agent = models.TextField()
228 poster_user_agent = models.TextField()
226
229
227 # TODO Convert this field to ForeignKey
230 # TODO Convert this field to ForeignKey
228 parent = models.BigIntegerField()
231 parent = models.BigIntegerField(default=NO_PARENT)
229
232
233 thread = models.ForeignKey('Post', null=True, default=None)
230 tags = models.ManyToManyField(Tag)
234 tags = models.ManyToManyField(Tag)
231 last_edit_time = models.DateTimeField()
235 last_edit_time = models.DateTimeField()
232 user = models.ForeignKey('User', null=True, default=None)
236 user = models.ForeignKey('User', null=True, default=None)
@@ -267,7 +271,12 b' class Post(models.Model):'
267
271
268 return post_count <= settings.MAX_POSTS_PER_THREAD
272 return post_count <= settings.MAX_POSTS_PER_THREAD
269
273
270 def get_last_replies(self):
274 def bump(self):
275 if self.can_bump():
276 self.last_edit_time = timezone.now()
277 self.save()
278
279 def get_last_replies(self):
271 if settings.LAST_REPLIES_COUNT > 0:
280 if settings.LAST_REPLIES_COUNT > 0:
272 reply_count = self.get_reply_count()
281 reply_count = self.get_reply_count()
273
282
@@ -28,8 +28,10 b''
28 <div class="navigation_panel">
28 <div class="navigation_panel">
29 <a class="link" href="{% url 'index' %}">{% trans "All threads" %}</a>
29 <a class="link" href="{% url 'index' %}">{% trans "All threads" %}</a>
30 {% for tag in tags %}
30 {% for tag in tags %}
31 <a class="tag" href="{% url 'tag' tag_name=tag.name %}"
31 {% if not tag.is_empty %}
32 >{{ tag.name }}</a>
32 <a class="tag" href="{% url 'tag' tag_name=tag.name %}"
33 >{{ tag.name }}</a>
34 {% endif %}
33 {% endfor %}
35 {% endfor %}
34 <a class="tag" href="{% url 'tags' %}" alt="{% trans 'Tag management' %}"
36 <a class="tag" href="{% url 'tags' %}" alt="{% trans 'Tag management' %}"
35 >[...]</a>
37 >[...]</a>
@@ -47,22 +47,13 b' class BoardTests(TestCase):'
47
47
48 # Authentication tests
48 # Authentication tests
49
49
50 def _create_test_user(self):
51 admin = Admin(name='test_username12313584353165',
52 password='test_userpassword135135512')
53
54 admin.save()
55 return admin
56
57 def test_get_thread(self):
50 def test_get_thread(self):
58 opening_post = self._create_post()
51 opening_post = self._create_post()
59 op_id = opening_post.id
60
52
61 for i in range(0, 2):
53 for i in range(0, 2):
62 Post.objects.create_post('title', 'text',
54 Post.objects.create_post('title', 'text',thread=opening_post)
63 parent_id=op_id)
64
55
65 thread = Post.objects.get_thread(op_id)
56 thread = Post.objects.get_thread(opening_post.id)
66
57
67 self.assertEqual(3, len(thread))
58 self.assertEqual(3, len(thread))
68
59
@@ -85,8 +85,10 b' def _new_post(request, form, thread_id=b'
85 # TODO Add a possibility to define a link image instead of an image file.
85 # TODO Add a possibility to define a link image instead of an image file.
86 # If a link is given, download the image automatically.
86 # If a link is given, download the image automatically.
87
87
88 op = None if thread_id == boards.models.NO_PARENT else \
89 get_object_or_404(Post, id=thread_id)
88 post = Post.objects.create_post(title=title, text=text, ip=ip,
90 post = Post.objects.create_post(title=title, text=text, ip=ip,
89 parent_id=thread_id, image=image,
91 thread=op, image=image,
90 tags=tags)
92 tags=tags)
91
93
92 thread_to_show = (post.id if new_thread else thread_id)
94 thread_to_show = (post.id if new_thread else thread_id)
@@ -94,9 +96,8 b' def _new_post(request, form, thread_id=b'
94 if new_thread:
96 if new_thread:
95 return redirect(thread, post_id=thread_to_show)
97 return redirect(thread, post_id=thread_to_show)
96 else:
98 else:
97 return redirect(reverse(thread,
99 return redirect(reverse(thread, kwargs={'post_id': thread_to_show}) +
98 kwargs={'post_id': thread_to_show}) + '#'
100 '#' + str(post.id))
99 + str(post.id))
100
101
101
102
102 def tag(request, tag_name, page=0):
103 def tag(request, tag_name, page=0):
@@ -216,12 +217,10 b' def jump_to_post(request, post_id):'
216
217
217 post = get_object_or_404(Post, id=post_id)
218 post = get_object_or_404(Post, id=post_id)
218
219
219 if boards.models.NO_PARENT == post.parent:
220 if not post.thread:
220 return redirect(thread, post_id=post.id)
221 return redirect(thread, post_id=post.id)
221 else:
222 else:
222 # TODO Change this code to not use 'parent' field anymore
223 return redirect(reverse(thread, kwargs={'post_id': post.thread.id})
223 parent_thread = get_object_or_404(Post, id=post.parent)
224 return redirect(reverse(thread, kwargs={'post_id': parent_thread.id})
225 + '#' + str(post.id))
224 + '#' + str(post.id))
226
225
227
226
@@ -240,10 +239,10 b' def delete(request, post_id):'
240 # TODO Show confirmation page before deletion
239 # TODO Show confirmation page before deletion
241 Post.objects.delete_post(post)
240 Post.objects.delete_post(post)
242
241
243 if NO_PARENT == post.parent:
242 if not post.thread:
244 return _redirect_to_next(request)
243 return _redirect_to_next(request)
245 else:
244 else:
246 return redirect(thread, post_id=post.parent)
245 return redirect(thread, post_id=post.thread.id)
247
246
248
247
249 def ban(request, post_id):
248 def ban(request, post_id):
General Comments 0
You need to be logged in to leave comments. Login now