##// END OF EJS Templates
Another log names change
neko259 -
r868:07fdef4a 2.2.1 default
parent child Browse files
Show More
@@ -1,441 +1,441 b''
1 1 from datetime import datetime, timedelta, date
2 2 from datetime import time as dtime
3 3 from adjacent import Client
4 4 import logging
5 5 import re
6 6
7 7 from django.core.cache import cache
8 8 from django.core.urlresolvers import reverse
9 9 from django.db import models, transaction
10 10 from django.shortcuts import get_object_or_404
11 11 from django.template import RequestContext
12 12 from django.template.loader import render_to_string
13 13 from django.utils import timezone
14 14 from markupfield.fields import MarkupField
15 15 from boards import settings
16 16
17 17 from boards.models import PostImage
18 18 from boards.models.base import Viewable
19 19 from boards.models.thread import Thread
20 20 from boards.utils import datetime_to_epoch
21 21
22 22 WS_CHANNEL_THREAD = "thread:"
23 23
24 24 APP_LABEL_BOARDS = 'boards'
25 25
26 26 CACHE_KEY_PPD = 'ppd'
27 27 CACHE_KEY_POST_URL = 'post_url'
28 28
29 29 POSTS_PER_DAY_RANGE = 7
30 30
31 31 BAN_REASON_AUTO = 'Auto'
32 32
33 33 IMAGE_THUMB_SIZE = (200, 150)
34 34
35 35 TITLE_MAX_LENGTH = 200
36 36
37 37 DEFAULT_MARKUP_TYPE = 'bbcode'
38 38
39 39 # TODO This should be removed
40 40 NO_IP = '0.0.0.0'
41 41
42 42 # TODO Real user agent should be saved instead of this
43 43 UNKNOWN_UA = ''
44 44
45 45 REGEX_REPLY = re.compile(r'\[post\](\d+)\[/post\]')
46 46
47 47 PARAMETER_TRUNCATED = 'truncated'
48 48 PARAMETER_TAG = 'tag'
49 49 PARAMETER_OFFSET = 'offset'
50 50 PARAMETER_DIFF_TYPE = 'type'
51 51
52 52 DIFF_TYPE_HTML = 'html'
53 53 DIFF_TYPE_JSON = 'json'
54 54
55 55 PREPARSE_PATTERNS = {
56 56 r'>>(\d+)': r'[post]\1[/post]',
57 57 r'>(.+)': r'[quote]\1[/quote]'
58 58 }
59 59
60 60
61 61 class PostManager(models.Manager):
62 62 def create_post(self, title, text, image=None, thread=None, ip=NO_IP,
63 63 tags=None):
64 64 """
65 65 Creates new post
66 66 """
67 67
68 68 if not tags:
69 69 tags = []
70 70
71 71 posting_time = timezone.now()
72 72 if not thread:
73 73 thread = Thread.objects.create(bump_time=posting_time,
74 74 last_edit_time=posting_time)
75 75 new_thread = True
76 76 else:
77 77 thread.bump()
78 78 thread.last_edit_time = posting_time
79 79 if thread.can_bump() and (
80 80 thread.get_reply_count() >= settings.MAX_POSTS_PER_THREAD):
81 81 thread.bumpable = False
82 82 thread.save()
83 83 new_thread = False
84 84
85 85 pre_text = self._preparse_text(text)
86 86
87 87 post = self.create(title=title,
88 88 text=pre_text,
89 89 pub_time=posting_time,
90 90 thread_new=thread,
91 91 poster_ip=ip,
92 92 poster_user_agent=UNKNOWN_UA, # TODO Get UA at
93 93 # last!
94 94 last_edit_time=posting_time)
95 95
96 logger = logging.getLogger('create_post')
96 logger = logging.getLogger('boards.post.create')
97 97
98 98 logger.info('Created post #%d with title "%s"' % (post.id,
99 99 post.title))
100 100
101 101 if image:
102 102 post_image = PostImage.objects.create(image=image)
103 103 post.images.add(post_image)
104 104 logger.info('Created image #%d for post #%d' % (post_image.id,
105 105 post.id))
106 106
107 107 thread.replies.add(post)
108 108 list(map(thread.add_tag, tags))
109 109
110 110 if new_thread:
111 111 Thread.objects.process_oldest_threads()
112 112 self.connect_replies(post)
113 113
114 114
115 115 return post
116 116
117 117 def delete_post(self, post):
118 118 """
119 119 Deletes post and update or delete its thread
120 120 """
121 121
122 122 post_id = post.id
123 123
124 124 thread = post.get_thread()
125 125
126 126 if post.is_opening():
127 127 thread.delete()
128 128 else:
129 129 thread.last_edit_time = timezone.now()
130 130 thread.save()
131 131
132 132 post.delete()
133 133
134 logging.getLogger('delete_post').info('Deleted post #%d (%s)' % (post_id, post.get_title()))
134 logging.getLogger('boards.post.delete').info('Deleted post #%d (%s)' % (post_id, post.get_title()))
135 135
136 136 def delete_posts_by_ip(self, ip):
137 137 """
138 138 Deletes all posts of the author with same IP
139 139 """
140 140
141 141 posts = self.filter(poster_ip=ip)
142 142 for post in posts:
143 143 self.delete_post(post)
144 144
145 145 def connect_replies(self, post):
146 146 """
147 147 Connects replies to a post to show them as a reflink map
148 148 """
149 149
150 150 for reply_number in re.finditer(REGEX_REPLY, post.text.raw):
151 151 post_id = reply_number.group(1)
152 152 ref_post = self.filter(id=post_id)
153 153 if ref_post.count() > 0:
154 154 referenced_post = ref_post[0]
155 155 referenced_post.referenced_posts.add(post)
156 156 referenced_post.last_edit_time = post.pub_time
157 157 referenced_post.build_refmap()
158 158 referenced_post.save(update_fields=['refmap', 'last_edit_time'])
159 159
160 160 referenced_thread = referenced_post.get_thread()
161 161 referenced_thread.last_edit_time = post.pub_time
162 162 referenced_thread.save(update_fields=['last_edit_time'])
163 163
164 164 def get_posts_per_day(self):
165 165 """
166 166 Gets average count of posts per day for the last 7 days
167 167 """
168 168
169 169 day_end = date.today()
170 170 day_start = day_end - timedelta(POSTS_PER_DAY_RANGE)
171 171
172 172 cache_key = CACHE_KEY_PPD + str(day_end)
173 173 ppd = cache.get(cache_key)
174 174 if ppd:
175 175 return ppd
176 176
177 177 day_time_start = timezone.make_aware(datetime.combine(
178 178 day_start, dtime()), timezone.get_current_timezone())
179 179 day_time_end = timezone.make_aware(datetime.combine(
180 180 day_end, dtime()), timezone.get_current_timezone())
181 181
182 182 posts_per_period = float(self.filter(
183 183 pub_time__lte=day_time_end,
184 184 pub_time__gte=day_time_start).count())
185 185
186 186 ppd = posts_per_period / POSTS_PER_DAY_RANGE
187 187
188 188 cache.set(cache_key, ppd)
189 189 return ppd
190 190
191 191 def _preparse_text(self, text):
192 192 """
193 193 Preparses text to change patterns like '>>' to a proper bbcode
194 194 tags.
195 195 """
196 196
197 197 for key, value in PREPARSE_PATTERNS.items():
198 198 text = re.sub(key, value, text)
199 199
200 200 return text
201 201
202 202
203 203 class Post(models.Model, Viewable):
204 204 """A post is a message."""
205 205
206 206 objects = PostManager()
207 207
208 208 class Meta:
209 209 app_label = APP_LABEL_BOARDS
210 210 ordering = ('id',)
211 211
212 212 title = models.CharField(max_length=TITLE_MAX_LENGTH)
213 213 pub_time = models.DateTimeField()
214 214 text = MarkupField(default_markup_type=DEFAULT_MARKUP_TYPE,
215 215 escape_html=False)
216 216
217 217 images = models.ManyToManyField(PostImage, null=True, blank=True,
218 218 related_name='ip+', db_index=True)
219 219
220 220 poster_ip = models.GenericIPAddressField()
221 221 poster_user_agent = models.TextField()
222 222
223 223 thread_new = models.ForeignKey('Thread', null=True, default=None,
224 224 db_index=True)
225 225 last_edit_time = models.DateTimeField()
226 226
227 227 referenced_posts = models.ManyToManyField('Post', symmetrical=False,
228 228 null=True,
229 229 blank=True, related_name='rfp+',
230 230 db_index=True)
231 231 refmap = models.TextField(null=True, blank=True)
232 232
233 233 def __unicode__(self):
234 234 return '#' + str(self.id) + ' ' + self.title + ' (' + \
235 235 self.text.raw[:50] + ')'
236 236
237 237 def get_title(self):
238 238 """
239 239 Gets original post title or part of its text.
240 240 """
241 241
242 242 title = self.title
243 243 if not title:
244 244 title = self.text.rendered
245 245
246 246 return title
247 247
248 248 def build_refmap(self):
249 249 """
250 250 Builds a replies map string from replies list. This is a cache to stop
251 251 the server from recalculating the map on every post show.
252 252 """
253 253 map_string = ''
254 254
255 255 first = True
256 256 for refpost in self.referenced_posts.all():
257 257 if not first:
258 258 map_string += ', '
259 259 map_string += '<a href="%s">&gt;&gt;%s</a>' % (refpost.get_url(),
260 260 refpost.id)
261 261 first = False
262 262
263 263 self.refmap = map_string
264 264
265 265 def get_sorted_referenced_posts(self):
266 266 return self.refmap
267 267
268 268 def is_referenced(self):
269 269 return len(self.refmap) > 0
270 270
271 271 def is_opening(self):
272 272 """
273 273 Checks if this is an opening post or just a reply.
274 274 """
275 275
276 276 return self.get_thread().get_opening_post_id() == self.id
277 277
278 278 @transaction.atomic
279 279 def add_tag(self, tag):
280 280 edit_time = timezone.now()
281 281
282 282 thread = self.get_thread()
283 283 thread.add_tag(tag)
284 284 self.last_edit_time = edit_time
285 285 self.save(update_fields=['last_edit_time'])
286 286
287 287 thread.last_edit_time = edit_time
288 288 thread.save(update_fields=['last_edit_time'])
289 289
290 290 @transaction.atomic
291 291 def remove_tag(self, tag):
292 292 edit_time = timezone.now()
293 293
294 294 thread = self.get_thread()
295 295 thread.remove_tag(tag)
296 296 self.last_edit_time = edit_time
297 297 self.save(update_fields=['last_edit_time'])
298 298
299 299 thread.last_edit_time = edit_time
300 300 thread.save(update_fields=['last_edit_time'])
301 301
302 302 def get_url(self, thread=None):
303 303 """
304 304 Gets full url to the post.
305 305 """
306 306
307 307 cache_key = CACHE_KEY_POST_URL + str(self.id)
308 308 link = cache.get(cache_key)
309 309
310 310 if not link:
311 311 if not thread:
312 312 thread = self.get_thread()
313 313
314 314 opening_id = thread.get_opening_post_id()
315 315
316 316 if self.id != opening_id:
317 317 link = reverse('thread', kwargs={
318 318 'post_id': opening_id}) + '#' + str(self.id)
319 319 else:
320 320 link = reverse('thread', kwargs={'post_id': self.id})
321 321
322 322 cache.set(cache_key, link)
323 323
324 324 return link
325 325
326 326 def get_thread(self):
327 327 """
328 328 Gets post's thread.
329 329 """
330 330
331 331 return self.thread_new
332 332
333 333 def get_referenced_posts(self):
334 334 return self.referenced_posts.only('id', 'thread_new')
335 335
336 336 def get_text(self):
337 337 return self.text
338 338
339 339 def get_view(self, moderator=False, need_open_link=False,
340 340 truncated=False, *args, **kwargs):
341 341 if 'is_opening' in kwargs:
342 342 is_opening = kwargs['is_opening']
343 343 else:
344 344 is_opening = self.is_opening()
345 345
346 346 if 'thread' in kwargs:
347 347 thread = kwargs['thread']
348 348 else:
349 349 thread = self.get_thread()
350 350
351 351 if 'can_bump' in kwargs:
352 352 can_bump = kwargs['can_bump']
353 353 else:
354 354 can_bump = thread.can_bump()
355 355
356 356 if is_opening:
357 357 opening_post_id = self.id
358 358 else:
359 359 opening_post_id = thread.get_opening_post_id()
360 360
361 361 return render_to_string('boards/post.html', {
362 362 'post': self,
363 363 'moderator': moderator,
364 364 'is_opening': is_opening,
365 365 'thread': thread,
366 366 'bumpable': can_bump,
367 367 'need_open_link': need_open_link,
368 368 'truncated': truncated,
369 369 'opening_post_id': opening_post_id,
370 370 })
371 371
372 372 def get_first_image(self):
373 373 return self.images.earliest('id')
374 374
375 375 def delete(self, using=None):
376 376 """
377 377 Deletes all post images and the post itself.
378 378 """
379 379
380 380 self.images.all().delete()
381 381
382 382 super(Post, self).delete(using)
383 383
384 384 def get_post_data(self, format_type=DIFF_TYPE_JSON, request=None,
385 385 include_last_update=False):
386 386 """
387 387 Gets post HTML or JSON data that can be rendered on a page or used by
388 388 API.
389 389 """
390 390
391 391 if format_type == DIFF_TYPE_HTML:
392 392 context = RequestContext(request)
393 393 context['post'] = self
394 394 if PARAMETER_TRUNCATED in request.GET:
395 395 context[PARAMETER_TRUNCATED] = True
396 396
397 397 return render_to_string('boards/api_post.html', context)
398 398 elif format_type == DIFF_TYPE_JSON:
399 399 post_json = {
400 400 'id': self.id,
401 401 'title': self.title,
402 402 'text': self.text.rendered,
403 403 }
404 404 if self.images.exists():
405 405 post_image = self.get_first_image()
406 406 post_json['image'] = post_image.image.url
407 407 post_json['image_preview'] = post_image.image.url_200x150
408 408 if include_last_update:
409 409 post_json['bump_time'] = datetime_to_epoch(
410 410 self.thread_new.bump_time)
411 411 return post_json
412 412
413 413 def send_to_websocket(self, request, recursive=True):
414 414 """
415 415 Sends post HTML data to the thread web socket.
416 416 """
417 417
418 418 if not settings.WEBSOCKETS_ENABLED:
419 419 return
420 420
421 421 client = Client()
422 422
423 423 channel_name = WS_CHANNEL_THREAD + str(self.get_thread().get_opening_post_id())
424 424 client.publish(channel_name, {
425 425 'html': self.get_post_data(
426 426 format_type=DIFF_TYPE_HTML,
427 427 request=request),
428 428 'diff_type': 'added' if recursive else 'updated',
429 429 })
430 430 client.send()
431 431
432 logger = logging.getLogger('websocket')
432 logger = logging.getLogger('boards.post.websocket')
433 433
434 434 logger.info('Sent post #{} to channel {}'.format(self.id, channel_name))
435 435
436 436 if recursive:
437 437 for reply_number in re.finditer(REGEX_REPLY, self.text.raw):
438 438 post_id = reply_number.group(1)
439 439 ref_post = Post.objects.filter(id=post_id)[0]
440 440
441 441 ref_post.send_to_websocket(request, recursive=False)
@@ -1,245 +1,245 b''
1 1 # Django settings for neboard project.
2 2 import os
3 3 from boards.mdx_neboard import bbcode_extended
4 4
5 5 DEBUG = True
6 6 TEMPLATE_DEBUG = DEBUG
7 7
8 8 ADMINS = (
9 9 # ('Your Name', 'your_email@example.com'),
10 10 ('admin', 'admin@example.com')
11 11 )
12 12
13 13 MANAGERS = ADMINS
14 14
15 15 DATABASES = {
16 16 'default': {
17 17 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
18 18 'NAME': 'database.db', # Or path to database file if using sqlite3.
19 19 'USER': '', # Not used with sqlite3.
20 20 'PASSWORD': '', # Not used with sqlite3.
21 21 'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
22 22 'PORT': '', # Set to empty string for default. Not used with sqlite3.
23 23 'CONN_MAX_AGE': None,
24 24 }
25 25 }
26 26
27 27 # Local time zone for this installation. Choices can be found here:
28 28 # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
29 29 # although not all choices may be available on all operating systems.
30 30 # In a Windows environment this must be set to your system time zone.
31 31 TIME_ZONE = 'Europe/Kiev'
32 32
33 33 # Language code for this installation. All choices can be found here:
34 34 # http://www.i18nguy.com/unicode/language-identifiers.html
35 35 LANGUAGE_CODE = 'en'
36 36
37 37 SITE_ID = 1
38 38
39 39 # If you set this to False, Django will make some optimizations so as not
40 40 # to load the internationalization machinery.
41 41 USE_I18N = True
42 42
43 43 # If you set this to False, Django will not format dates, numbers and
44 44 # calendars according to the current locale.
45 45 USE_L10N = True
46 46
47 47 # If you set this to False, Django will not use timezone-aware datetimes.
48 48 USE_TZ = True
49 49
50 50 # Absolute filesystem path to the directory that will hold user-uploaded files.
51 51 # Example: "/home/media/media.lawrence.com/media/"
52 52 MEDIA_ROOT = './media/'
53 53
54 54 # URL that handles the media served from MEDIA_ROOT. Make sure to use a
55 55 # trailing slash.
56 56 # Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
57 57 MEDIA_URL = '/media/'
58 58
59 59 # Absolute path to the directory static files should be collected to.
60 60 # Don't put anything in this directory yourself; store your static files
61 61 # in apps' "static/" subdirectories and in STATICFILES_DIRS.
62 62 # Example: "/home/media/media.lawrence.com/static/"
63 63 STATIC_ROOT = ''
64 64
65 65 # URL prefix for static files.
66 66 # Example: "http://media.lawrence.com/static/"
67 67 STATIC_URL = '/static/'
68 68
69 69 # Additional locations of static files
70 70 # It is really a hack, put real paths, not related
71 71 STATICFILES_DIRS = (
72 72 os.path.dirname(__file__) + '/boards/static',
73 73
74 74 # '/d/work/python/django/neboard/neboard/boards/static',
75 75 # Put strings here, like "/home/html/static" or "C:/www/django/static".
76 76 # Always use forward slashes, even on Windows.
77 77 # Don't forget to use absolute paths, not relative paths.
78 78 )
79 79
80 80 # List of finder classes that know how to find static files in
81 81 # various locations.
82 82 STATICFILES_FINDERS = (
83 83 'django.contrib.staticfiles.finders.FileSystemFinder',
84 84 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
85 85 'compressor.finders.CompressorFinder',
86 86 )
87 87
88 88 if DEBUG:
89 89 STATICFILES_STORAGE = \
90 90 'django.contrib.staticfiles.storage.StaticFilesStorage'
91 91 else:
92 92 STATICFILES_STORAGE = \
93 93 'django.contrib.staticfiles.storage.CachedStaticFilesStorage'
94 94
95 95 # Make this unique, and don't share it with anybody.
96 96 SECRET_KEY = '@1rc$o(7=tt#kd+4s$u6wchm**z^)4x90)7f6z(i&amp;55@o11*8o'
97 97
98 98 # List of callables that know how to import templates from various sources.
99 99 TEMPLATE_LOADERS = (
100 100 'django.template.loaders.filesystem.Loader',
101 101 'django.template.loaders.app_directories.Loader',
102 102 )
103 103
104 104 TEMPLATE_CONTEXT_PROCESSORS = (
105 105 'django.core.context_processors.media',
106 106 'django.core.context_processors.static',
107 107 'django.core.context_processors.request',
108 108 'django.contrib.auth.context_processors.auth',
109 109 'boards.context_processors.user_and_ui_processor',
110 110 )
111 111
112 112 MIDDLEWARE_CLASSES = (
113 113 'django.contrib.sessions.middleware.SessionMiddleware',
114 114 'django.middleware.locale.LocaleMiddleware',
115 115 'django.middleware.common.CommonMiddleware',
116 116 'django.contrib.auth.middleware.AuthenticationMiddleware',
117 117 'django.contrib.messages.middleware.MessageMiddleware',
118 118 'boards.middlewares.BanMiddleware',
119 119 'boards.middlewares.MinifyHTMLMiddleware',
120 120 )
121 121
122 122 ROOT_URLCONF = 'neboard.urls'
123 123
124 124 # Python dotted path to the WSGI application used by Django's runserver.
125 125 WSGI_APPLICATION = 'neboard.wsgi.application'
126 126
127 127 TEMPLATE_DIRS = (
128 128 # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
129 129 # Always use forward slashes, even on Windows.
130 130 # Don't forget to use absolute paths, not relative paths.
131 131 'templates',
132 132 )
133 133
134 134 INSTALLED_APPS = (
135 135 'django.contrib.auth',
136 136 'django.contrib.contenttypes',
137 137 'django.contrib.sessions',
138 138 # 'django.contrib.sites',
139 139 'django.contrib.messages',
140 140 'django.contrib.staticfiles',
141 141 # Uncomment the next line to enable the admin:
142 142 'django.contrib.admin',
143 143 # Uncomment the next line to enable admin documentation:
144 144 # 'django.contrib.admindocs',
145 145 'django.contrib.humanize',
146 146 'django_cleanup',
147 147
148 148 # Migrations
149 149 'south',
150 150 'debug_toolbar',
151 151
152 152 # Search
153 153 'haystack',
154 154
155 155 # Static files compressor
156 156 'compressor',
157 157
158 158 'boards',
159 159 )
160 160
161 161 # A sample logging configuration. The only tangible logging
162 162 # performed by this configuration is to send an email to
163 163 # the site admins on every HTTP 500 error when DEBUG=False.
164 164 # See http://docs.djangoproject.com/en/dev/topics/logging for
165 165 # more details on how to customize your logging configuration.
166 166 LOGGING = {
167 167 'version': 1,
168 168 'disable_existing_loggers': False,
169 169 'formatters': {
170 170 'verbose': {
171 'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
171 'format': '%(levelname)s %(asctime)s %(name)s %(process)d %(thread)d %(message)s'
172 172 },
173 173 'simple': {
174 'format': '%(levelname)s %(asctime)s [%(module)s] %(message)s'
174 'format': '%(levelname)s %(asctime)s [%(name)s] %(message)s'
175 175 },
176 176 },
177 177 'filters': {
178 178 'require_debug_false': {
179 179 '()': 'django.utils.log.RequireDebugFalse'
180 180 }
181 181 },
182 182 'handlers': {
183 183 'console': {
184 184 'level': 'DEBUG',
185 185 'class': 'logging.StreamHandler',
186 186 'formatter': 'simple'
187 187 },
188 188 },
189 189 'loggers': {
190 190 'boards': {
191 191 'handlers': ['console'],
192 192 'level': 'DEBUG',
193 193 }
194 194 },
195 195 }
196 196
197 197 HAYSTACK_CONNECTIONS = {
198 198 'default': {
199 199 'ENGINE': 'haystack.backends.whoosh_backend.WhooshEngine',
200 200 'PATH': os.path.join(os.path.dirname(__file__), 'whoosh_index'),
201 201 },
202 202 }
203 203
204 204 MARKUP_FIELD_TYPES = (
205 205 ('bbcode', bbcode_extended),
206 206 )
207 207
208 208 THEMES = [
209 209 ('md', 'Mystic Dark'),
210 210 ('md_centered', 'Mystic Dark (centered)'),
211 211 ('sw', 'Snow White'),
212 212 ('pg', 'Photon Gray'),
213 213 ]
214 214
215 215 POSTING_DELAY = 20 # seconds
216 216
217 217 COMPRESS_HTML = False
218 218
219 219 # Websocket settins
220 220 CENTRIFUGE_HOST = 'localhost'
221 221 CENTRIFUGE_PORT = '9090'
222 222
223 223 CENTRIFUGE_ADDRESS = 'http://{}:{}'.format(CENTRIFUGE_HOST, CENTRIFUGE_PORT)
224 224 CENTRIFUGE_PROJECT_ID = '<project id here>'
225 225 CENTRIFUGE_PROJECT_SECRET = '<project secret here>'
226 226 CENTRIFUGE_TIMEOUT = 5
227 227
228 228 # Debug mode middlewares
229 229 if DEBUG:
230 230 MIDDLEWARE_CLASSES += (
231 231 'debug_toolbar.middleware.DebugToolbarMiddleware',
232 232 )
233 233
234 234 def custom_show_toolbar(request):
235 235 return True
236 236
237 237 DEBUG_TOOLBAR_CONFIG = {
238 238 'ENABLE_STACKTRACES': True,
239 239 'SHOW_TOOLBAR_CALLBACK': 'neboard.settings.custom_show_toolbar',
240 240 }
241 241
242 242 # FIXME Uncommenting this fails somehow. Need to investigate this
243 243 #DEBUG_TOOLBAR_PANELS += (
244 244 # 'debug_toolbar.panels.profiling.ProfilingDebugPanel',
245 #) No newline at end of file
245 #)
General Comments 0
You need to be logged in to leave comments. Login now