##// END OF EJS Templates
Moved pagination related stuff to the mixin
neko259 -
r1854:b4c06973 default
parent child Browse files
Show More
@@ -1,189 +1,179 b''
1 from django.core.urlresolvers import reverse
1 from django.core.urlresolvers import reverse
2 from django.core.files import File
2 from django.core.files import File
3 from django.core.files.temp import NamedTemporaryFile
3 from django.core.files.temp import NamedTemporaryFile
4 from django.core.paginator import EmptyPage
4 from django.core.paginator import EmptyPage
5 from django.db import transaction
5 from django.db import transaction
6 from django.http import Http404
6 from django.http import Http404
7 from django.shortcuts import render, redirect
7 from django.shortcuts import render, redirect
8 from django.utils.decorators import method_decorator
8 from django.utils.decorators import method_decorator
9 from django.views.decorators.csrf import csrf_protect
9 from django.views.decorators.csrf import csrf_protect
10
10
11 from boards import utils, settings
11 from boards import utils, settings
12 from boards.abstracts.paginator import get_paginator
12 from boards.abstracts.paginator import get_paginator
13 from boards.abstracts.settingsmanager import get_settings_manager,\
13 from boards.abstracts.settingsmanager import get_settings_manager,\
14 SETTING_ONLY_FAVORITES
14 SETTING_ONLY_FAVORITES
15 from boards.forms import ThreadForm, PlainErrorList
15 from boards.forms import ThreadForm, PlainErrorList
16 from boards.models import Post, Thread, Ban
16 from boards.models import Post, Thread, Ban
17 from boards.views.banned import BannedView
17 from boards.views.banned import BannedView
18 from boards.views.base import BaseBoardView, CONTEXT_FORM
18 from boards.views.base import BaseBoardView, CONTEXT_FORM
19 from boards.views.posting_mixin import PostMixin
19 from boards.views.posting_mixin import PostMixin
20 from boards.views.mixins import FileUploadMixin, PaginatedMixin,\
20 from boards.views.mixins import FileUploadMixin, PaginatedMixin,\
21 DispatcherMixin, PARAMETER_METHOD
21 DispatcherMixin, PARAMETER_METHOD
22
22
23 FORM_TAGS = 'tags'
23 FORM_TAGS = 'tags'
24 FORM_TEXT = 'text'
24 FORM_TEXT = 'text'
25 FORM_TITLE = 'title'
25 FORM_TITLE = 'title'
26 FORM_IMAGE = 'image'
26 FORM_IMAGE = 'image'
27 FORM_THREADS = 'threads'
27 FORM_THREADS = 'threads'
28
28
29 TAG_DELIMITER = ' '
29 TAG_DELIMITER = ' '
30
30
31 PARAMETER_CURRENT_PAGE = 'current_page'
31 PARAMETER_CURRENT_PAGE = 'current_page'
32 PARAMETER_PAGINATOR = 'paginator'
32 PARAMETER_PAGINATOR = 'paginator'
33 PARAMETER_THREADS = 'threads'
33 PARAMETER_THREADS = 'threads'
34 PARAMETER_ADDITIONAL = 'additional_params'
34 PARAMETER_ADDITIONAL = 'additional_params'
35 PARAMETER_MAX_FILE_SIZE = 'max_file_size'
35 PARAMETER_MAX_FILE_SIZE = 'max_file_size'
36 PARAMETER_RSS_URL = 'rss_url'
36 PARAMETER_RSS_URL = 'rss_url'
37 PARAMETER_MAX_FILES = 'max_files'
37 PARAMETER_MAX_FILES = 'max_files'
38
38
39 TEMPLATE = 'boards/all_threads.html'
39 TEMPLATE = 'boards/all_threads.html'
40 DEFAULT_PAGE = 1
40 DEFAULT_PAGE = 1
41
41
42 FORM_TAGS = 'tags'
42 FORM_TAGS = 'tags'
43
43
44
44
45 class AllThreadsView(PostMixin, FileUploadMixin, BaseBoardView, PaginatedMixin, DispatcherMixin):
45 class AllThreadsView(PostMixin, FileUploadMixin, BaseBoardView, PaginatedMixin, DispatcherMixin):
46
46
47 tag_name = ''
47 tag_name = ''
48
48
49 def __init__(self):
49 def __init__(self):
50 self.settings_manager = None
50 self.settings_manager = None
51 super(AllThreadsView, self).__init__()
51 super(AllThreadsView, self).__init__()
52
52
53 @method_decorator(csrf_protect)
53 @method_decorator(csrf_protect)
54 def get(self, request, form: ThreadForm=None):
54 def get(self, request, form: ThreadForm=None):
55 page = request.GET.get('page', DEFAULT_PAGE)
55 page = request.GET.get('page', DEFAULT_PAGE)
56
56
57 params = self.get_context_data(request=request)
57 params = self.get_context_data(request=request)
58
58
59 if not form:
59 if not form:
60 form = ThreadForm(error_class=PlainErrorList,
60 form = ThreadForm(error_class=PlainErrorList,
61 initial={FORM_TAGS: self.tag_name})
61 initial={FORM_TAGS: self.tag_name})
62
62
63 self.settings_manager = get_settings_manager(request)
63 self.settings_manager = get_settings_manager(request)
64
64
65 threads = self.get_threads()
65 threads = self.get_threads()
66
66
67 order = request.GET.get('order', 'bump')
67 order = request.GET.get('order', 'bump')
68 if order == 'bump':
68 if order == 'bump':
69 threads = threads.order_by('-bump_time')
69 threads = threads.order_by('-bump_time')
70 else:
70 else:
71 threads = threads.filter(replies__opening=True)\
71 threads = threads.filter(replies__opening=True)\
72 .order_by('-replies__pub_time')
72 .order_by('-replies__pub_time')
73 filter = request.GET.get('filter')
73 filter = request.GET.get('filter')
74 threads = threads.distinct()
74 threads = threads.distinct()
75
75
76 paginator = get_paginator(threads,
76 paginator = get_paginator(threads,
77 settings.get_int('View', 'ThreadsPerPage'))
77 settings.get_int('View', 'ThreadsPerPage'))
78 paginator.current_page = int(page)
78 paginator.current_page = int(page)
79
79
80 try:
80 try:
81 threads = paginator.page(page).object_list
81 threads = paginator.page(page).object_list
82 except EmptyPage:
82 except EmptyPage:
83 raise Http404()
83 raise Http404()
84
84
85 params[PARAMETER_THREADS] = threads
85 params[PARAMETER_THREADS] = threads
86 params[CONTEXT_FORM] = form
86 params[CONTEXT_FORM] = form
87 params[PARAMETER_MAX_FILE_SIZE] = self.get_max_upload_size()
87 params[PARAMETER_MAX_FILE_SIZE] = self.get_max_upload_size()
88 params[PARAMETER_RSS_URL] = self.get_rss_url()
88 params[PARAMETER_RSS_URL] = self.get_rss_url()
89 params[PARAMETER_MAX_FILES] = settings.get_int('Forms', 'MaxFileCount')
89 params[PARAMETER_MAX_FILES] = settings.get_int('Forms', 'MaxFileCount')
90
90
91 paginator.set_url(self.get_reverse_url(), request.GET.dict())
91 paginator.set_url(self.get_reverse_url(), request.GET.dict())
92 self.get_page_context(paginator, params, page)
92 params.update(self.get_page_context(paginator, page))
93
93
94 return render(request, TEMPLATE, params)
94 return render(request, TEMPLATE, params)
95
95
96 @method_decorator(csrf_protect)
96 @method_decorator(csrf_protect)
97 def post(self, request):
97 def post(self, request):
98 if PARAMETER_METHOD in request.POST:
98 if PARAMETER_METHOD in request.POST:
99 self.dispatch_method(request)
99 self.dispatch_method(request)
100
100
101 return redirect('index') # FIXME Different for different modes
101 return redirect('index') # FIXME Different for different modes
102
102
103 form = ThreadForm(request.POST, request.FILES,
103 form = ThreadForm(request.POST, request.FILES,
104 error_class=PlainErrorList)
104 error_class=PlainErrorList)
105 form.session = request.session
105 form.session = request.session
106
106
107 if form.is_valid():
107 if form.is_valid():
108 return self.create_thread(request, form)
108 return self.create_thread(request, form)
109 if form.need_to_ban:
109 if form.need_to_ban:
110 # Ban user because he is suspected to be a bot
110 # Ban user because he is suspected to be a bot
111 self._ban_current_user(request)
111 self._ban_current_user(request)
112
112
113 return self.get(request, form)
113 return self.get(request, form)
114
114
115 def get_page_context(self, paginator, params, page):
116 """
117 Get pagination context variables
118 """
119
120 params[PARAMETER_PAGINATOR] = paginator
121 current_page = paginator.page(int(page))
122 params[PARAMETER_CURRENT_PAGE] = current_page
123 self.set_page_urls(paginator, params)
124
125 def get_reverse_url(self):
115 def get_reverse_url(self):
126 return reverse('index')
116 return reverse('index')
127
117
128 @transaction.atomic
118 @transaction.atomic
129 def create_thread(self, request, form: ThreadForm, html_response=True):
119 def create_thread(self, request, form: ThreadForm, html_response=True):
130 """
120 """
131 Creates a new thread with an opening post.
121 Creates a new thread with an opening post.
132 """
122 """
133
123
134 ip = utils.get_client_ip(request)
124 ip = utils.get_client_ip(request)
135 is_banned = Ban.objects.filter(ip=ip).exists()
125 is_banned = Ban.objects.filter(ip=ip).exists()
136
126
137 if is_banned:
127 if is_banned:
138 if html_response:
128 if html_response:
139 return redirect(BannedView().as_view())
129 return redirect(BannedView().as_view())
140 else:
130 else:
141 return
131 return
142
132
143 data = form.cleaned_data
133 data = form.cleaned_data
144
134
145 title = form.get_title()
135 title = form.get_title()
146 text = data[FORM_TEXT]
136 text = data[FORM_TEXT]
147 files = form.get_files()
137 files = form.get_files()
148 file_urls = form.get_file_urls()
138 file_urls = form.get_file_urls()
149 images = form.get_images()
139 images = form.get_images()
150
140
151 text = self._remove_invalid_links(text)
141 text = self._remove_invalid_links(text)
152
142
153 tags = data[FORM_TAGS]
143 tags = data[FORM_TAGS]
154 monochrome = form.is_monochrome()
144 monochrome = form.is_monochrome()
155
145
156 post = Post.objects.create_post(title=title, text=text, files=files,
146 post = Post.objects.create_post(title=title, text=text, files=files,
157 ip=ip, tags=tags,
147 ip=ip, tags=tags,
158 tripcode=form.get_tripcode(),
148 tripcode=form.get_tripcode(),
159 monochrome=monochrome, images=images,
149 monochrome=monochrome, images=images,
160 file_urls=file_urls)
150 file_urls=file_urls)
161
151
162 if form.is_subscribe():
152 if form.is_subscribe():
163 settings_manager = get_settings_manager(request)
153 settings_manager = get_settings_manager(request)
164 settings_manager.add_or_read_fav_thread(post)
154 settings_manager.add_or_read_fav_thread(post)
165
155
166 if html_response:
156 if html_response:
167 return redirect(post.get_absolute_url())
157 return redirect(post.get_absolute_url())
168
158
169 def get_threads(self):
159 def get_threads(self):
170 """
160 """
171 Gets list of threads that will be shown on a page.
161 Gets list of threads that will be shown on a page.
172 """
162 """
173
163
174 threads = Thread.objects\
164 threads = Thread.objects\
175 .exclude(tags__in=self.settings_manager.get_hidden_tags())
165 .exclude(tags__in=self.settings_manager.get_hidden_tags())
176 if self.settings_manager.get_setting(SETTING_ONLY_FAVORITES):
166 if self.settings_manager.get_setting(SETTING_ONLY_FAVORITES):
177 fav_tags = self.settings_manager.get_fav_tags()
167 fav_tags = self.settings_manager.get_fav_tags()
178 if len(fav_tags) > 0:
168 if len(fav_tags) > 0:
179 threads = threads.filter(tags__in=fav_tags)
169 threads = threads.filter(tags__in=fav_tags)
180
170
181 return threads
171 return threads
182
172
183 def get_rss_url(self):
173 def get_rss_url(self):
184 return self.get_reverse_url() + 'rss/'
174 return self.get_reverse_url() + 'rss/'
185
175
186 def toggle_fav(self, request):
176 def toggle_fav(self, request):
187 settings_manager = get_settings_manager(request)
177 settings_manager = get_settings_manager(request)
188 settings_manager.set_setting(SETTING_ONLY_FAVORITES,
178 settings_manager.set_setting(SETTING_ONLY_FAVORITES,
189 not settings_manager.get_setting(SETTING_ONLY_FAVORITES, False))
179 not settings_manager.get_setting(SETTING_ONLY_FAVORITES, False))
@@ -1,151 +1,131 b''
1 from django.core.urlresolvers import reverse
1 from django.core.urlresolvers import reverse
2 from django.shortcuts import render
2 from django.shortcuts import render
3
3
4 from boards import settings
4 from boards import settings
5 from boards.abstracts.paginator import get_paginator
5 from boards.abstracts.paginator import get_paginator
6 from boards.abstracts.settingsmanager import get_settings_manager
6 from boards.abstracts.settingsmanager import get_settings_manager
7 from boards.models import Post
7 from boards.models import Post
8 from boards.views.base import BaseBoardView
8 from boards.views.base import BaseBoardView
9 from boards.views.posting_mixin import PostMixin
9 from boards.views.posting_mixin import PostMixin
10 from boards.views.mixins import PaginatedMixin
10
11
11 POSTS_PER_PAGE = settings.get_int('View', 'PostsPerPage')
12 POSTS_PER_PAGE = settings.get_int('View', 'PostsPerPage')
12
13
13 PARAMETER_CURRENT_PAGE = 'current_page'
14 PARAMETER_PAGINATOR = 'paginator'
15 PARAMETER_POSTS = 'posts'
14 PARAMETER_POSTS = 'posts'
16 PARAMETER_QUERIES = 'queries'
15 PARAMETER_QUERIES = 'queries'
17
16
18 PARAMETER_PREV_LINK = 'prev_page_link'
19 PARAMETER_NEXT_LINK = 'next_page_link'
20
21 TEMPLATE = 'boards/feed.html'
17 TEMPLATE = 'boards/feed.html'
22 DEFAULT_PAGE = 1
18 DEFAULT_PAGE = 1
23
19
24
20
25 class FeedFilter:
21 class FeedFilter:
26 @staticmethod
22 @staticmethod
27 def get_filtered_posts(request, posts):
23 def get_filtered_posts(request, posts):
28 return posts
24 return posts
29
25
30 @staticmethod
26 @staticmethod
31 def get_query(request):
27 def get_query(request):
32 return None
28 return None
33
29
34
30
35 class TripcodeFilter(FeedFilter):
31 class TripcodeFilter(FeedFilter):
36 @staticmethod
32 @staticmethod
37 def get_filtered_posts(request, posts):
33 def get_filtered_posts(request, posts):
38 filtered_posts = posts
34 filtered_posts = posts
39 tripcode = request.GET.get('tripcode', None)
35 tripcode = request.GET.get('tripcode', None)
40 if tripcode:
36 if tripcode:
41 filtered_posts = filtered_posts.filter(tripcode=tripcode)
37 filtered_posts = filtered_posts.filter(tripcode=tripcode)
42 return filtered_posts
38 return filtered_posts
43
39
44 @staticmethod
40 @staticmethod
45 def get_query(request):
41 def get_query(request):
46 tripcode = request.GET.get('tripcode', None)
42 tripcode = request.GET.get('tripcode', None)
47 if tripcode:
43 if tripcode:
48 return 'Tripcode: {}'.format(tripcode)
44 return 'Tripcode: {}'.format(tripcode)
49
45
50
46
51 class FavoritesFilter(FeedFilter):
47 class FavoritesFilter(FeedFilter):
52 @staticmethod
48 @staticmethod
53 def get_filtered_posts(request, posts):
49 def get_filtered_posts(request, posts):
54 filtered_posts = posts
50 filtered_posts = posts
55
51
56 favorites = 'favorites' in request.GET
52 favorites = 'favorites' in request.GET
57 if favorites:
53 if favorites:
58 settings_manager = get_settings_manager(request)
54 settings_manager = get_settings_manager(request)
59 fav_thread_ops = Post.objects.filter(id__in=settings_manager.get_fav_threads().keys())
55 fav_thread_ops = Post.objects.filter(id__in=settings_manager.get_fav_threads().keys())
60 fav_threads = [op.get_thread() for op in fav_thread_ops]
56 fav_threads = [op.get_thread() for op in fav_thread_ops]
61 filtered_posts = filtered_posts.filter(thread__in=fav_threads)
57 filtered_posts = filtered_posts.filter(thread__in=fav_threads)
62 return filtered_posts
58 return filtered_posts
63
59
64
60
65 class IpFilter(FeedFilter):
61 class IpFilter(FeedFilter):
66 @staticmethod
62 @staticmethod
67 def get_filtered_posts(request, posts):
63 def get_filtered_posts(request, posts):
68 filtered_posts = posts
64 filtered_posts = posts
69
65
70 ip = request.GET.get('ip', None)
66 ip = request.GET.get('ip', None)
71 if ip and request.user.has_perm('post_delete'):
67 if ip and request.user.has_perm('post_delete'):
72 filtered_posts = filtered_posts.filter(poster_ip=ip)
68 filtered_posts = filtered_posts.filter(poster_ip=ip)
73 return filtered_posts
69 return filtered_posts
74
70
75 @staticmethod
71 @staticmethod
76 def get_query(request):
72 def get_query(request):
77 ip = request.GET.get('ip', None)
73 ip = request.GET.get('ip', None)
78 if ip:
74 if ip:
79 return 'IP: {}'.format(ip)
75 return 'IP: {}'.format(ip)
80
76
81
77
82 class ImageFilter(FeedFilter):
78 class ImageFilter(FeedFilter):
83 @staticmethod
79 @staticmethod
84 def get_filtered_posts(request, posts):
80 def get_filtered_posts(request, posts):
85 filtered_posts = posts
81 filtered_posts = posts
86
82
87 image = request.GET.get('image', None)
83 image = request.GET.get('image', None)
88 if image:
84 if image:
89 filtered_posts = filtered_posts.filter(attachments__file=image)
85 filtered_posts = filtered_posts.filter(attachments__file=image)
90 return filtered_posts
86 return filtered_posts
91
87
92 @staticmethod
88 @staticmethod
93 def get_query(request):
89 def get_query(request):
94 image = request.GET.get('image', None)
90 image = request.GET.get('image', None)
95 if image:
91 if image:
96 return 'File: {}'.format(image)
92 return 'File: {}'.format(image)
97
93
98
94
99 class FeedView(PostMixin, BaseBoardView):
95 class FeedView(PostMixin, PaginatedMixin, BaseBoardView):
100 filters = (
96 filters = (
101 TripcodeFilter,
97 TripcodeFilter,
102 FavoritesFilter,
98 FavoritesFilter,
103 IpFilter,
99 IpFilter,
104 ImageFilter,
100 ImageFilter,
105 )
101 )
106
102
107 def get(self, request):
103 def get(self, request):
108 page = request.GET.get('page', DEFAULT_PAGE)
104 page = request.GET.get('page', DEFAULT_PAGE)
109
105
110 params = self.get_context_data(request=request)
106 params = self.get_context_data(request=request)
111
107
112 settings_manager = get_settings_manager(request)
108 settings_manager = get_settings_manager(request)
113
109
114 posts = Post.objects.exclude(
110 posts = Post.objects.exclude(
115 thread__tags__in=settings_manager.get_hidden_tags()).order_by(
111 thread__tags__in=settings_manager.get_hidden_tags()).order_by(
116 '-pub_time').prefetch_related('attachments', 'thread')
112 '-pub_time').prefetch_related('attachments', 'thread')
117 queries = []
113 queries = []
118 for filter in self.filters:
114 for filter in self.filters:
119 posts = filter.get_filtered_posts(request, posts)
115 posts = filter.get_filtered_posts(request, posts)
120 query = filter.get_query(request)
116 query = filter.get_query(request)
121 if query:
117 if query:
122 queries.append(query)
118 queries.append(query)
123 params[PARAMETER_QUERIES] = queries
119 params[PARAMETER_QUERIES] = queries
124
120
125 paginator = get_paginator(posts, POSTS_PER_PAGE)
121 paginator = get_paginator(posts, POSTS_PER_PAGE)
126 paginator.current_page = int(page)
122 paginator.current_page = int(page)
127
123
128 params[PARAMETER_POSTS] = paginator.page(page).object_list
124 params[PARAMETER_POSTS] = paginator.page(page).object_list
129
125
130 paginator.set_url(reverse('feed'), request.GET.dict())
126 paginator.set_url(reverse('feed'), request.GET.dict())
131
127
132 self.get_page_context(paginator, params, page)
128 params.update(self.get_page_context(paginator, page))
133
129
134 return render(request, TEMPLATE, params)
130 return render(request, TEMPLATE, params)
135
131
136 # TODO Dedup this into PagedMixin
137 def get_page_context(self, paginator, params, page):
138 """
139 Get pagination context variables
140 """
141
142 params[PARAMETER_PAGINATOR] = paginator
143 current_page = paginator.page(int(page))
144 params[PARAMETER_CURRENT_PAGE] = current_page
145 if current_page.has_previous():
146 params[PARAMETER_PREV_LINK] = paginator.get_page_url(
147 current_page.previous_page_number())
148 if current_page.has_next():
149 params[PARAMETER_NEXT_LINK] = paginator.get_page_url(
150 current_page.next_page_number())
151
@@ -1,40 +1,61 b''
1 import boards
1 import boards
2
2
3
3
4 PARAM_NEXT = 'next'
4 PARAM_NEXT = 'next'
5 PARAMETER_METHOD = 'method'
5 PARAMETER_METHOD = 'method'
6
6
7 PARAMETER_CURRENT_PAGE = 'current_page'
8 PARAMETER_PAGINATOR = 'paginator'
9
10 PARAMETER_PREV_LINK = 'prev_page_link'
11 PARAMETER_NEXT_LINK = 'next_page_link'
7
12
8 class DispatcherMixin:
13 class DispatcherMixin:
9 """
14 """
10 This class contains a dispather method that can run a method specified by
15 This class contains a dispather method that can run a method specified by
11 'method' request parameter.
16 'method' request parameter.
12 """
17 """
13
18
14 def __init__(self):
19 def __init__(self):
15 self.user = None
20 self.user = None
16
21
17 def dispatch_method(self, *args, **kwargs):
22 def dispatch_method(self, *args, **kwargs):
18 request = args[0]
23 request = args[0]
19
24
20 self.user = request.user
25 self.user = request.user
21
26
22 method_name = None
27 method_name = None
23 if PARAMETER_METHOD in request.GET:
28 if PARAMETER_METHOD in request.GET:
24 method_name = request.GET[PARAMETER_METHOD]
29 method_name = request.GET[PARAMETER_METHOD]
25 elif PARAMETER_METHOD in request.POST:
30 elif PARAMETER_METHOD in request.POST:
26 method_name = request.POST[PARAMETER_METHOD]
31 method_name = request.POST[PARAMETER_METHOD]
27
32
28 if method_name:
33 if method_name:
29 return getattr(self, method_name)(*args, **kwargs)
34 return getattr(self, method_name)(*args, **kwargs)
30
35
31
36
32 class FileUploadMixin:
37 class FileUploadMixin:
33 def get_max_upload_size(self):
38 def get_max_upload_size(self):
34 return boards.settings.get_int('Forms', 'MaxFileSize')
39 return boards.settings.get_int('Forms', 'MaxFileSize')
35
40
36
41
37 class PaginatedMixin:
42 class PaginatedMixin:
38 def set_page_urls(self, paginator, params):
43 def get_page_context(self, paginator, page):
39 params['prev_page_link'] = paginator.get_prev_page_url()
44 """
40 params['next_page_link'] = paginator.get_next_page_url()
45 Get pagination context variables
46 """
47
48 params = {}
49
50 params[PARAMETER_PAGINATOR] = paginator
51 current_page = paginator.page(int(page))
52 params[PARAMETER_CURRENT_PAGE] = current_page
53 if current_page.has_previous():
54 params[PARAMETER_PREV_LINK] = paginator.get_page_url(
55 current_page.previous_page_number())
56 if current_page.has_next():
57 params[PARAMETER_NEXT_LINK] = paginator.get_page_url(
58 current_page.next_page_number())
59
60 return params
61
General Comments 0
You need to be logged in to leave comments. Login now