##// END OF EJS Templates
Fixed looping post loading
neko259 -
r800:fe3d4933 default
parent child Browse files
Show More
@@ -1,245 +1,248 b''
1 from datetime import datetime
1 from datetime import datetime
2 import json
2 import json
3 import logging
3 import logging
4 from django.db import transaction
4 from django.db import transaction
5 from django.http import HttpResponse
5 from django.http import HttpResponse
6 from django.shortcuts import get_object_or_404, render
6 from django.shortcuts import get_object_or_404, render
7 from django.template import RequestContext
7 from django.template import RequestContext
8 from django.utils import timezone
8 from django.utils import timezone
9 from django.core import serializers
9 from django.core import serializers
10 from django.template.loader import render_to_string
10 from django.template.loader import render_to_string
11
11
12 from boards.forms import PostForm, PlainErrorList
12 from boards.forms import PostForm, PlainErrorList
13 from boards.models import Post, Thread, Tag
13 from boards.models import Post, Thread, Tag
14 from boards.utils import datetime_to_epoch
14 from boards.utils import datetime_to_epoch
15 from boards.views.thread import ThreadView
15 from boards.views.thread import ThreadView
16
16
17 __author__ = 'neko259'
17 __author__ = 'neko259'
18
18
19 PARAMETER_TRUNCATED = 'truncated'
19 PARAMETER_TRUNCATED = 'truncated'
20 PARAMETER_TAG = 'tag'
20 PARAMETER_TAG = 'tag'
21 PARAMETER_OFFSET = 'offset'
21 PARAMETER_OFFSET = 'offset'
22 PARAMETER_DIFF_TYPE = 'type'
22 PARAMETER_DIFF_TYPE = 'type'
23
23
24 DIFF_TYPE_HTML = 'html'
24 DIFF_TYPE_HTML = 'html'
25 DIFF_TYPE_JSON = 'json'
25 DIFF_TYPE_JSON = 'json'
26
26
27 STATUS_OK = 'ok'
27 STATUS_OK = 'ok'
28 STATUS_ERROR = 'error'
28 STATUS_ERROR = 'error'
29
29
30 logger = logging.getLogger(__name__)
30 logger = logging.getLogger(__name__)
31
31
32
32
33 @transaction.atomic
33 @transaction.atomic
34 def api_get_threaddiff(request, thread_id, last_update_time):
34 def api_get_threaddiff(request, thread_id, last_update_time):
35 """
35 """
36 Gets posts that were changed or added since time
36 Gets posts that were changed or added since time
37 """
37 """
38
38
39 thread = get_object_or_404(Post, id=thread_id).get_thread()
39 thread = get_object_or_404(Post, id=thread_id).get_thread()
40
40
41 filter_time = datetime.fromtimestamp(float(last_update_time) / 1000000,
41 # Add 1 to ensure we don't load the same post over and over
42 last_update_timestamp = float(last_update_time) + 1
43
44 filter_time = datetime.fromtimestamp(last_update_timestamp / 1000000,
42 timezone.get_current_timezone())
45 timezone.get_current_timezone())
43
46
44 json_data = {
47 json_data = {
45 'added': [],
48 'added': [],
46 'updated': [],
49 'updated': [],
47 'last_update': None,
50 'last_update': None,
48 }
51 }
49 added_posts = Post.objects.filter(thread_new=thread,
52 added_posts = Post.objects.filter(thread_new=thread,
50 pub_time__gt=filter_time) \
53 pub_time__gt=filter_time) \
51 .order_by('pub_time')
54 .order_by('pub_time')
52 updated_posts = Post.objects.filter(thread_new=thread,
55 updated_posts = Post.objects.filter(thread_new=thread,
53 pub_time__lte=filter_time,
56 pub_time__lte=filter_time,
54 last_edit_time__gt=filter_time)
57 last_edit_time__gt=filter_time)
55
58
56 diff_type = DIFF_TYPE_HTML
59 diff_type = DIFF_TYPE_HTML
57 if PARAMETER_DIFF_TYPE in request.GET:
60 if PARAMETER_DIFF_TYPE in request.GET:
58 diff_type = request.GET[PARAMETER_DIFF_TYPE]
61 diff_type = request.GET[PARAMETER_DIFF_TYPE]
59
62
60 for post in added_posts:
63 for post in added_posts:
61 json_data['added'].append(_get_post_data(post.id, diff_type, request))
64 json_data['added'].append(_get_post_data(post.id, diff_type, request))
62 for post in updated_posts:
65 for post in updated_posts:
63 json_data['updated'].append(_get_post_data(post.id, diff_type, request))
66 json_data['updated'].append(_get_post_data(post.id, diff_type, request))
64 json_data['last_update'] = datetime_to_epoch(thread.last_edit_time)
67 json_data['last_update'] = datetime_to_epoch(thread.last_edit_time)
65
68
66 return HttpResponse(content=json.dumps(json_data))
69 return HttpResponse(content=json.dumps(json_data))
67
70
68
71
69 def api_add_post(request, opening_post_id):
72 def api_add_post(request, opening_post_id):
70 """
73 """
71 Adds a post and return the JSON response for it
74 Adds a post and return the JSON response for it
72 """
75 """
73
76
74 opening_post = get_object_or_404(Post, id=opening_post_id)
77 opening_post = get_object_or_404(Post, id=opening_post_id)
75
78
76 logger.info('Adding post via api...')
79 logger.info('Adding post via api...')
77
80
78 status = STATUS_OK
81 status = STATUS_OK
79 errors = []
82 errors = []
80
83
81 if request.method == 'POST':
84 if request.method == 'POST':
82 form = PostForm(request.POST, request.FILES, error_class=PlainErrorList)
85 form = PostForm(request.POST, request.FILES, error_class=PlainErrorList)
83 form.session = request.session
86 form.session = request.session
84
87
85 if form.need_to_ban:
88 if form.need_to_ban:
86 # Ban user because he is suspected to be a bot
89 # Ban user because he is suspected to be a bot
87 # _ban_current_user(request)
90 # _ban_current_user(request)
88 status = STATUS_ERROR
91 status = STATUS_ERROR
89 if form.is_valid():
92 if form.is_valid():
90 post = ThreadView().new_post(request, form, opening_post,
93 post = ThreadView().new_post(request, form, opening_post,
91 html_response=False)
94 html_response=False)
92 if not post:
95 if not post:
93 status = STATUS_ERROR
96 status = STATUS_ERROR
94 else:
97 else:
95 logger.info('Added post #%d via api.' % post.id)
98 logger.info('Added post #%d via api.' % post.id)
96 else:
99 else:
97 status = STATUS_ERROR
100 status = STATUS_ERROR
98 errors = form.as_json_errors()
101 errors = form.as_json_errors()
99
102
100 response = {
103 response = {
101 'status': status,
104 'status': status,
102 'errors': errors,
105 'errors': errors,
103 }
106 }
104
107
105 return HttpResponse(content=json.dumps(response))
108 return HttpResponse(content=json.dumps(response))
106
109
107
110
108 def get_post(request, post_id):
111 def get_post(request, post_id):
109 """
112 """
110 Gets the html of a post. Used for popups. Post can be truncated if used
113 Gets the html of a post. Used for popups. Post can be truncated if used
111 in threads list with 'truncated' get parameter.
114 in threads list with 'truncated' get parameter.
112 """
115 """
113
116
114 logger.info('Getting post #%s' % post_id)
117 logger.info('Getting post #%s' % post_id)
115
118
116 post = get_object_or_404(Post, id=post_id)
119 post = get_object_or_404(Post, id=post_id)
117
120
118 context = RequestContext(request)
121 context = RequestContext(request)
119 context['post'] = post
122 context['post'] = post
120 if PARAMETER_TRUNCATED in request.GET:
123 if PARAMETER_TRUNCATED in request.GET:
121 context[PARAMETER_TRUNCATED] = True
124 context[PARAMETER_TRUNCATED] = True
122
125
123 return render(request, 'boards/api_post.html', context)
126 return render(request, 'boards/api_post.html', context)
124
127
125
128
126 # TODO Test this
129 # TODO Test this
127 def api_get_threads(request, count):
130 def api_get_threads(request, count):
128 """
131 """
129 Gets the JSON thread opening posts list.
132 Gets the JSON thread opening posts list.
130 Parameters that can be used for filtering:
133 Parameters that can be used for filtering:
131 tag, offset (from which thread to get results)
134 tag, offset (from which thread to get results)
132 """
135 """
133
136
134 if PARAMETER_TAG in request.GET:
137 if PARAMETER_TAG in request.GET:
135 tag_name = request.GET[PARAMETER_TAG]
138 tag_name = request.GET[PARAMETER_TAG]
136 if tag_name is not None:
139 if tag_name is not None:
137 tag = get_object_or_404(Tag, name=tag_name)
140 tag = get_object_or_404(Tag, name=tag_name)
138 threads = tag.threads.filter(archived=False)
141 threads = tag.threads.filter(archived=False)
139 else:
142 else:
140 threads = Thread.objects.filter(archived=False)
143 threads = Thread.objects.filter(archived=False)
141
144
142 if PARAMETER_OFFSET in request.GET:
145 if PARAMETER_OFFSET in request.GET:
143 offset = request.GET[PARAMETER_OFFSET]
146 offset = request.GET[PARAMETER_OFFSET]
144 offset = int(offset) if offset is not None else 0
147 offset = int(offset) if offset is not None else 0
145 else:
148 else:
146 offset = 0
149 offset = 0
147
150
148 threads = threads.order_by('-bump_time')
151 threads = threads.order_by('-bump_time')
149 threads = threads[offset:offset + int(count)]
152 threads = threads[offset:offset + int(count)]
150
153
151 opening_posts = []
154 opening_posts = []
152 for thread in threads:
155 for thread in threads:
153 opening_post = thread.get_opening_post()
156 opening_post = thread.get_opening_post()
154
157
155 # TODO Add tags, replies and images count
158 # TODO Add tags, replies and images count
156 opening_posts.append(_get_post_data(opening_post.id,
159 opening_posts.append(_get_post_data(opening_post.id,
157 include_last_update=True))
160 include_last_update=True))
158
161
159 return HttpResponse(content=json.dumps(opening_posts))
162 return HttpResponse(content=json.dumps(opening_posts))
160
163
161
164
162 # TODO Test this
165 # TODO Test this
163 def api_get_tags(request):
166 def api_get_tags(request):
164 """
167 """
165 Gets all tags or user tags.
168 Gets all tags or user tags.
166 """
169 """
167
170
168 # TODO Get favorite tags for the given user ID
171 # TODO Get favorite tags for the given user ID
169
172
170 tags = Tag.objects.get_not_empty_tags()
173 tags = Tag.objects.get_not_empty_tags()
171 tag_names = []
174 tag_names = []
172 for tag in tags:
175 for tag in tags:
173 tag_names.append(tag.name)
176 tag_names.append(tag.name)
174
177
175 return HttpResponse(content=json.dumps(tag_names))
178 return HttpResponse(content=json.dumps(tag_names))
176
179
177
180
178 # TODO The result can be cached by the thread last update time
181 # TODO The result can be cached by the thread last update time
179 # TODO Test this
182 # TODO Test this
180 def api_get_thread_posts(request, opening_post_id):
183 def api_get_thread_posts(request, opening_post_id):
181 """
184 """
182 Gets the JSON array of thread posts
185 Gets the JSON array of thread posts
183 """
186 """
184
187
185 opening_post = get_object_or_404(Post, id=opening_post_id)
188 opening_post = get_object_or_404(Post, id=opening_post_id)
186 thread = opening_post.get_thread()
189 thread = opening_post.get_thread()
187 posts = thread.get_replies()
190 posts = thread.get_replies()
188
191
189 json_data = {
192 json_data = {
190 'posts': [],
193 'posts': [],
191 'last_update': None,
194 'last_update': None,
192 }
195 }
193 json_post_list = []
196 json_post_list = []
194
197
195 for post in posts:
198 for post in posts:
196 json_post_list.append(_get_post_data(post.id))
199 json_post_list.append(_get_post_data(post.id))
197 json_data['last_update'] = datetime_to_epoch(thread.last_edit_time)
200 json_data['last_update'] = datetime_to_epoch(thread.last_edit_time)
198 json_data['posts'] = json_post_list
201 json_data['posts'] = json_post_list
199
202
200 return HttpResponse(content=json.dumps(json_data))
203 return HttpResponse(content=json.dumps(json_data))
201
204
202
205
203 def api_get_post(request, post_id):
206 def api_get_post(request, post_id):
204 """
207 """
205 Gets the JSON of a post. This can be
208 Gets the JSON of a post. This can be
206 used as and API for external clients.
209 used as and API for external clients.
207 """
210 """
208
211
209 post = get_object_or_404(Post, id=post_id)
212 post = get_object_or_404(Post, id=post_id)
210
213
211 json = serializers.serialize("json", [post], fields=(
214 json = serializers.serialize("json", [post], fields=(
212 "pub_time", "_text_rendered", "title", "text", "image",
215 "pub_time", "_text_rendered", "title", "text", "image",
213 "image_width", "image_height", "replies", "tags"
216 "image_width", "image_height", "replies", "tags"
214 ))
217 ))
215
218
216 return HttpResponse(content=json)
219 return HttpResponse(content=json)
217
220
218
221
219 # TODO Add pub time and replies
222 # TODO Add pub time and replies
220 def _get_post_data(post_id, format_type=DIFF_TYPE_JSON, request=None,
223 def _get_post_data(post_id, format_type=DIFF_TYPE_JSON, request=None,
221 include_last_update=False):
224 include_last_update=False):
222 if format_type == DIFF_TYPE_HTML:
225 if format_type == DIFF_TYPE_HTML:
223 post = get_object_or_404(Post, id=post_id)
226 post = get_object_or_404(Post, id=post_id)
224
227
225 context = RequestContext(request)
228 context = RequestContext(request)
226 context['post'] = post
229 context['post'] = post
227 if PARAMETER_TRUNCATED in request.GET:
230 if PARAMETER_TRUNCATED in request.GET:
228 context[PARAMETER_TRUNCATED] = True
231 context[PARAMETER_TRUNCATED] = True
229
232
230 return render_to_string('boards/api_post.html', context)
233 return render_to_string('boards/api_post.html', context)
231 elif format_type == DIFF_TYPE_JSON:
234 elif format_type == DIFF_TYPE_JSON:
232 post = get_object_or_404(Post, id=post_id)
235 post = get_object_or_404(Post, id=post_id)
233 post_json = {
236 post_json = {
234 'id': post.id,
237 'id': post.id,
235 'title': post.title,
238 'title': post.title,
236 'text': post.text.rendered,
239 'text': post.text.rendered,
237 }
240 }
238 if post.images.exists():
241 if post.images.exists():
239 post_image = post.get_first_image()
242 post_image = post.get_first_image()
240 post_json['image'] = post_image.image.url
243 post_json['image'] = post_image.image.url
241 post_json['image_preview'] = post_image.image.url_200x150
244 post_json['image_preview'] = post_image.image.url_200x150
242 if include_last_update:
245 if include_last_update:
243 post_json['bump_time'] = datetime_to_epoch(
246 post_json['bump_time'] = datetime_to_epoch(
244 post.thread_new.bump_time)
247 post.thread_new.bump_time)
245 return post_json
248 return post_json
General Comments 0
You need to be logged in to leave comments. Login now