##// END OF EJS Templates
Added media directory cache size
neko259 -
r1424:78342ab8 default
parent child Browse files
Show More
@@ -1,138 +1,143
1 """
1 """
2 This module contains helper functions and helper classes.
2 This module contains helper functions and helper classes.
3 """
3 """
4 import hashlib
4 import hashlib
5 from random import random
5 from random import random
6 import time
6 import time
7 import hmac
7 import hmac
8
8
9 from django.core.cache import cache
9 from django.core.cache import cache
10 from django.db.models import Model
10 from django.db.models import Model
11 from django import forms
11 from django import forms
12 from django.utils import timezone
12 from django.utils import timezone
13 from django.utils.translation import ugettext_lazy as _
13 from django.utils.translation import ugettext_lazy as _
14 import magic
14 import magic
15 from portage import os
15 from portage import os
16
16
17 import boards
17 import boards
18 from boards.settings import get_bool
18 from boards.settings import get_bool
19 from neboard import settings
19 from neboard import settings
20
20
21 CACHE_KEY_DELIMITER = '_'
21 CACHE_KEY_DELIMITER = '_'
22
22
23 HTTP_FORWARDED = 'HTTP_X_FORWARDED_FOR'
23 HTTP_FORWARDED = 'HTTP_X_FORWARDED_FOR'
24 META_REMOTE_ADDR = 'REMOTE_ADDR'
24 META_REMOTE_ADDR = 'REMOTE_ADDR'
25
25
26 SETTING_MESSAGES = 'Messages'
26 SETTING_MESSAGES = 'Messages'
27 SETTING_ANON_MODE = 'AnonymousMode'
27 SETTING_ANON_MODE = 'AnonymousMode'
28
28
29 ANON_IP = '127.0.0.1'
29 ANON_IP = '127.0.0.1'
30
30
31 UPLOAD_DIRS ={
31 UPLOAD_DIRS ={
32 'PostImage': 'images/',
32 'PostImage': 'images/',
33 'Attachment': 'files/',
33 'Attachment': 'files/',
34 }
34 }
35 FILE_EXTENSION_DELIMITER = '.'
35 FILE_EXTENSION_DELIMITER = '.'
36
36
37
37
38 def is_anonymous_mode():
38 def is_anonymous_mode():
39 return get_bool(SETTING_MESSAGES, SETTING_ANON_MODE)
39 return get_bool(SETTING_MESSAGES, SETTING_ANON_MODE)
40
40
41
41
42 def get_client_ip(request):
42 def get_client_ip(request):
43 if is_anonymous_mode():
43 if is_anonymous_mode():
44 ip = ANON_IP
44 ip = ANON_IP
45 else:
45 else:
46 x_forwarded_for = request.META.get(HTTP_FORWARDED)
46 x_forwarded_for = request.META.get(HTTP_FORWARDED)
47 if x_forwarded_for:
47 if x_forwarded_for:
48 ip = x_forwarded_for.split(',')[-1].strip()
48 ip = x_forwarded_for.split(',')[-1].strip()
49 else:
49 else:
50 ip = request.META.get(META_REMOTE_ADDR)
50 ip = request.META.get(META_REMOTE_ADDR)
51 return ip
51 return ip
52
52
53
53
54 # TODO The output format is not epoch because it includes microseconds
54 # TODO The output format is not epoch because it includes microseconds
55 def datetime_to_epoch(datetime):
55 def datetime_to_epoch(datetime):
56 return int(time.mktime(timezone.localtime(
56 return int(time.mktime(timezone.localtime(
57 datetime,timezone.get_current_timezone()).timetuple())
57 datetime,timezone.get_current_timezone()).timetuple())
58 * 1000000 + datetime.microsecond)
58 * 1000000 + datetime.microsecond)
59
59
60
60
61 def get_websocket_token(user_id='', timestamp=''):
61 def get_websocket_token(user_id='', timestamp=''):
62 """
62 """
63 Create token to validate information provided by new connection.
63 Create token to validate information provided by new connection.
64 """
64 """
65
65
66 sign = hmac.new(settings.CENTRIFUGE_PROJECT_SECRET.encode())
66 sign = hmac.new(settings.CENTRIFUGE_PROJECT_SECRET.encode())
67 sign.update(settings.CENTRIFUGE_PROJECT_ID.encode())
67 sign.update(settings.CENTRIFUGE_PROJECT_ID.encode())
68 sign.update(user_id.encode())
68 sign.update(user_id.encode())
69 sign.update(timestamp.encode())
69 sign.update(timestamp.encode())
70 token = sign.hexdigest()
70 token = sign.hexdigest()
71
71
72 return token
72 return token
73
73
74
74
75 # TODO Test this carefully
75 def cached_result(key_method=None):
76 def cached_result(key_method=None):
76 """
77 """
77 Caches method result in the Django's cache system, persisted by object name,
78 Caches method result in the Django's cache system, persisted by object name,
78 object name and model id if object is a Django model.
79 object name, model id if object is a Django model, args and kwargs if any.
79 """
80 """
80 def _cached_result(function):
81 def _cached_result(function):
81 def inner_func(obj, *args, **kwargs):
82 def inner_func(obj, *args, **kwargs):
82 # TODO Include method arguments to the cache key
83 cache_key_params = [obj.__class__.__name__, function.__name__]
83 cache_key_params = [obj.__class__.__name__, function.__name__]
84
85 cache_key_params += args
86 for key, value in kwargs:
87 cache_key_params.append(key + ':' + value)
88
84 if isinstance(obj, Model):
89 if isinstance(obj, Model):
85 cache_key_params.append(str(obj.id))
90 cache_key_params.append(str(obj.id))
86
91
87 if key_method is not None:
92 if key_method is not None:
88 cache_key_params += [str(arg) for arg in key_method(obj)]
93 cache_key_params += [str(arg) for arg in key_method(obj)]
89
94
90 cache_key = CACHE_KEY_DELIMITER.join(cache_key_params)
95 cache_key = CACHE_KEY_DELIMITER.join(cache_key_params)
91
96
92 persisted_result = cache.get(cache_key)
97 persisted_result = cache.get(cache_key)
93 if persisted_result is not None:
98 if persisted_result is not None:
94 result = persisted_result
99 result = persisted_result
95 else:
100 else:
96 result = function(obj, *args, **kwargs)
101 result = function(obj, *args, **kwargs)
97 cache.set(cache_key, result)
102 cache.set(cache_key, result)
98
103
99 return result
104 return result
100
105
101 return inner_func
106 return inner_func
102 return _cached_result
107 return _cached_result
103
108
104
109
105 def get_file_hash(file) -> str:
110 def get_file_hash(file) -> str:
106 md5 = hashlib.md5()
111 md5 = hashlib.md5()
107 for chunk in file.chunks():
112 for chunk in file.chunks():
108 md5.update(chunk)
113 md5.update(chunk)
109 return md5.hexdigest()
114 return md5.hexdigest()
110
115
111
116
112 def validate_file_size(size: int):
117 def validate_file_size(size: int):
113 max_size = boards.settings.get_int('Forms', 'MaxFileSize')
118 max_size = boards.settings.get_int('Forms', 'MaxFileSize')
114 if size > max_size:
119 if size > max_size:
115 raise forms.ValidationError(
120 raise forms.ValidationError(
116 _('File must be less than %s bytes')
121 _('File must be less than %s bytes')
117 % str(max_size))
122 % str(max_size))
118
123
119
124
120 def get_extension(filename):
125 def get_extension(filename):
121 return filename.split(FILE_EXTENSION_DELIMITER)[-1:][0]
126 return filename.split(FILE_EXTENSION_DELIMITER)[-1:][0]
122
127
123
128
124 def get_upload_filename(model_instance, old_filename):
129 def get_upload_filename(model_instance, old_filename):
125 # TODO Use something other than random number in file name
130 # TODO Use something other than random number in file name
126 extension = get_extension(old_filename)
131 extension = get_extension(old_filename)
127 new_name = '{}{}.{}'.format(
132 new_name = '{}{}.{}'.format(
128 str(int(time.mktime(time.gmtime()))),
133 str(int(time.mktime(time.gmtime()))),
129 str(int(random() * 1000)),
134 str(int(random() * 1000)),
130 extension)
135 extension)
131
136
132 directory = UPLOAD_DIRS[type(model_instance).__name__]
137 directory = UPLOAD_DIRS[type(model_instance).__name__]
133
138
134 return os.path.join(directory, new_name)
139 return os.path.join(directory, new_name)
135
140
136
141
137 def get_file_mimetype(file) -> str:
142 def get_file_mimetype(file) -> str:
138 return magic.from_buffer(file.chunks().__next__(), mime=True).decode()
143 return magic.from_buffer(file.chunks().__next__(), mime=True).decode()
@@ -1,32 +1,34
1 import os
1 import os
2
2
3 from django.shortcuts import render
3 from django.shortcuts import render
4
4
5 import neboard
5 import neboard
6 from boards.authors import authors
6 from boards.authors import authors
7 from boards.utils import cached_result
7 from boards.views.base import BaseBoardView
8 from boards.views.base import BaseBoardView
8 from boards.models import Post
9 from boards.models import Post
9
10
10
11
11 PARAM_AUTHORS = 'authors'
12 PARAM_AUTHORS = 'authors'
12 PARAM_MEDIA_SIZE = 'media_size'
13 PARAM_MEDIA_SIZE = 'media_size'
13 PARAM_POST_COUNT = 'post_count'
14 PARAM_POST_COUNT = 'post_count'
14
15
15
16
16 class AuthorsView(BaseBoardView):
17 class AuthorsView(BaseBoardView):
17
18
18 def get(self, request):
19 def get(self, request):
19 params = dict()
20 params = dict()
20 params[PARAM_AUTHORS] = authors
21 params[PARAM_AUTHORS] = authors
21 params[PARAM_MEDIA_SIZE] = self._get_directory_size(neboard.settings.MEDIA_ROOT)
22 params[PARAM_MEDIA_SIZE] = self._get_directory_size(neboard.settings.MEDIA_ROOT)
22 params[PARAM_POST_COUNT] = Post.objects.count()
23 params[PARAM_POST_COUNT] = Post.objects.count()
23
24
24 return render(request, 'boards/authors.html', params)
25 return render(request, 'boards/authors.html', params)
25
26
27 @cached_result()
26 def _get_directory_size(self, directory):
28 def _get_directory_size(self, directory):
27 total_size = 0
29 total_size = 0
28 for dirpath, dirnames, filenames in os.walk(directory):
30 for dirpath, dirnames, filenames in os.walk(directory):
29 for f in filenames:
31 for f in filenames:
30 fp = os.path.join(dirpath, f)
32 fp = os.path.join(dirpath, f)
31 total_size += os.path.getsize(fp)
33 total_size += os.path.getsize(fp)
32 return total_size
34 return total_size
General Comments 0
You need to be logged in to leave comments. Login now