##// END OF EJS Templates
Allow deleting attachments with their files already deleted
neko259 -
r1879:2272bd98 default
parent child Browse files
Show More
@@ -1,135 +1,141 b''
1 import re
1 import re
2 import os
2 import os
3
3
4 from django.db.models.signals import post_save, pre_save, pre_delete, \
4 from django.db.models.signals import post_save, pre_save, pre_delete, \
5 post_delete
5 post_delete
6 from django.dispatch import receiver
6 from django.dispatch import receiver
7 from django.utils import timezone
7 from django.utils import timezone
8
8
9 from boards import thumbs
9 from boards import thumbs
10 from boards.mdx_neboard import get_parser
10 from boards.mdx_neboard import get_parser
11
11
12 from boards.models import Post, GlobalId, Attachment
12 from boards.models import Post, GlobalId, Attachment
13 from boards.models.attachment.viewers import FILE_TYPES_IMAGE
13 from boards.models.attachment.viewers import FILE_TYPES_IMAGE
14 from boards.models.post import REGEX_NOTIFICATION, REGEX_REPLY,\
14 from boards.models.post import REGEX_NOTIFICATION, REGEX_REPLY,\
15 REGEX_GLOBAL_REPLY
15 REGEX_GLOBAL_REPLY
16 from boards.models.post.manager import post_import_deps
16 from boards.models.post.manager import post_import_deps
17 from boards.models.user import Notification
17 from boards.models.user import Notification
18 from neboard.settings import MEDIA_ROOT
18 from neboard.settings import MEDIA_ROOT
19
19
20
20
21 THUMB_SIZES = ((200, 150),)
21 THUMB_SIZES = ((200, 150),)
22
22
23
23
24 @receiver(post_save, sender=Post)
24 @receiver(post_save, sender=Post)
25 def connect_replies(instance, **kwargs):
25 def connect_replies(instance, **kwargs):
26 if not kwargs['update_fields']:
26 if not kwargs['update_fields']:
27 for reply_number in re.finditer(REGEX_REPLY, instance.get_raw_text()):
27 for reply_number in re.finditer(REGEX_REPLY, instance.get_raw_text()):
28 post_id = reply_number.group(1)
28 post_id = reply_number.group(1)
29
29
30 try:
30 try:
31 referenced_post = Post.objects.get(id=post_id)
31 referenced_post = Post.objects.get(id=post_id)
32
32
33 if not referenced_post.referenced_posts.filter(
33 if not referenced_post.referenced_posts.filter(
34 id=instance.id).exists():
34 id=instance.id).exists():
35 referenced_post.referenced_posts.add(instance)
35 referenced_post.referenced_posts.add(instance)
36 referenced_post.last_edit_time = instance.pub_time
36 referenced_post.last_edit_time = instance.pub_time
37 referenced_post.build_refmap()
37 referenced_post.build_refmap()
38 referenced_post.save(update_fields=['refmap', 'last_edit_time'])
38 referenced_post.save(update_fields=['refmap', 'last_edit_time'])
39 except Post.DoesNotExist:
39 except Post.DoesNotExist:
40 pass
40 pass
41
41
42
42
43 @receiver(post_save, sender=Post)
43 @receiver(post_save, sender=Post)
44 @receiver(post_import_deps, sender=Post)
44 @receiver(post_import_deps, sender=Post)
45 def connect_global_replies(instance, **kwargs):
45 def connect_global_replies(instance, **kwargs):
46 if not kwargs['update_fields']:
46 if not kwargs['update_fields']:
47 for reply_number in re.finditer(REGEX_GLOBAL_REPLY, instance.get_raw_text()):
47 for reply_number in re.finditer(REGEX_GLOBAL_REPLY, instance.get_raw_text()):
48 key_type = reply_number.group(1)
48 key_type = reply_number.group(1)
49 key = reply_number.group(2)
49 key = reply_number.group(2)
50 local_id = reply_number.group(3)
50 local_id = reply_number.group(3)
51
51
52 try:
52 try:
53 global_id = GlobalId.objects.get(key_type=key_type, key=key,
53 global_id = GlobalId.objects.get(key_type=key_type, key=key,
54 local_id=local_id)
54 local_id=local_id)
55 referenced_post = Post.objects.get(global_id=global_id)
55 referenced_post = Post.objects.get(global_id=global_id)
56 referenced_post.referenced_posts.add(instance)
56 referenced_post.referenced_posts.add(instance)
57 referenced_post.last_edit_time = instance.pub_time
57 referenced_post.last_edit_time = instance.pub_time
58 referenced_post.build_refmap()
58 referenced_post.build_refmap()
59 referenced_post.save(update_fields=['refmap', 'last_edit_time'])
59 referenced_post.save(update_fields=['refmap', 'last_edit_time'])
60 except (GlobalId.DoesNotExist, Post.DoesNotExist):
60 except (GlobalId.DoesNotExist, Post.DoesNotExist):
61 pass
61 pass
62
62
63
63
64 @receiver(post_save, sender=Post)
64 @receiver(post_save, sender=Post)
65 def connect_notifications(instance, **kwargs):
65 def connect_notifications(instance, **kwargs):
66 if not kwargs['update_fields']:
66 if not kwargs['update_fields']:
67 for reply_number in re.finditer(REGEX_NOTIFICATION, instance.get_raw_text()):
67 for reply_number in re.finditer(REGEX_NOTIFICATION, instance.get_raw_text()):
68 user_name = reply_number.group(1).lower()
68 user_name = reply_number.group(1).lower()
69 Notification.objects.get_or_create(name=user_name, post=instance)
69 Notification.objects.get_or_create(name=user_name, post=instance)
70
70
71
71
72 @receiver(pre_save, sender=Post)
72 @receiver(pre_save, sender=Post)
73 @receiver(post_import_deps, sender=Post)
73 @receiver(post_import_deps, sender=Post)
74 def parse_text(instance, **kwargs):
74 def parse_text(instance, **kwargs):
75 instance._text_rendered = get_parser().parse(instance.get_raw_text())
75 instance._text_rendered = get_parser().parse(instance.get_raw_text())
76
76
77
77
78 @receiver(pre_delete, sender=Post)
78 @receiver(pre_delete, sender=Post)
79 def delete_attachments(instance, **kwargs):
79 def delete_attachments(instance, **kwargs):
80 for attachment in instance.attachments.all():
80 for attachment in instance.attachments.all():
81 attachment_refs_count = attachment.attachment_posts.count()
81 attachment_refs_count = attachment.attachment_posts.count()
82 if attachment_refs_count == 1:
82 if attachment_refs_count == 1:
83 attachment.delete()
83 attachment.delete()
84
84
85
85
86 @receiver(post_delete, sender=Post)
86 @receiver(post_delete, sender=Post)
87 def update_thread_on_delete(instance, **kwargs):
87 def update_thread_on_delete(instance, **kwargs):
88 thread = instance.get_thread()
88 thread = instance.get_thread()
89 thread.last_edit_time = timezone.now()
89 thread.last_edit_time = timezone.now()
90 thread.save()
90 thread.save()
91
91
92
92
93 @receiver(post_delete, sender=Post)
93 @receiver(post_delete, sender=Post)
94 def delete_global_id(instance, **kwargs):
94 def delete_global_id(instance, **kwargs):
95 if instance.global_id and instance.global_id.id:
95 if instance.global_id and instance.global_id.id:
96 instance.global_id.delete()
96 instance.global_id.delete()
97
97
98
98
99 @receiver(post_save, sender=Attachment)
99 @receiver(post_save, sender=Attachment)
100 def generate_thumb(instance, **kwargs):
100 def generate_thumb(instance, **kwargs):
101 if instance.mimetype in FILE_TYPES_IMAGE:
101 if instance.mimetype in FILE_TYPES_IMAGE:
102 for size in THUMB_SIZES:
102 for size in THUMB_SIZES:
103 (w, h) = size
103 (w, h) = size
104 split = instance.file.name.rsplit('.', 1)
104 split = instance.file.name.rsplit('.', 1)
105 thumb_name = '%s.%sx%s.%s' % (split[0], w, h, split[1])
105 thumb_name = '%s.%sx%s.%s' % (split[0], w, h, split[1])
106
106
107 if not instance.file.storage.exists(thumb_name):
107 if not instance.file.storage.exists(thumb_name):
108 # you can use another thumbnailing function if you like
108 # you can use another thumbnailing function if you like
109 thumb_content = thumbs.generate_thumb(instance.file, size, split[1])
109 thumb_content = thumbs.generate_thumb(instance.file, size, split[1])
110
110
111 thumb_name_ = instance.file.storage.save(thumb_name, thumb_content)
111 thumb_name_ = instance.file.storage.save(thumb_name, thumb_content)
112
112
113 if not thumb_name == thumb_name_:
113 if not thumb_name == thumb_name_:
114 raise ValueError(
114 raise ValueError(
115 'There is already a file named %s' % thumb_name_)
115 'There is already a file named %s' % thumb_name_)
116
116
117
117
118 @receiver(pre_delete, sender=Post)
118 @receiver(pre_delete, sender=Post)
119 def rebuild_refmap(instance, **kwargs):
119 def rebuild_refmap(instance, **kwargs):
120 for referenced_post in instance.refposts.all():
120 for referenced_post in instance.refposts.all():
121 referenced_post.build_refmap(excluded_ids=[instance.id])
121 referenced_post.build_refmap(excluded_ids=[instance.id])
122 referenced_post.save(update_fields=['refmap'])
122 referenced_post.save(update_fields=['refmap'])
123
123
124
124
125 @receiver(post_delete, sender=Attachment)
125 @receiver(post_delete, sender=Attachment)
126 def delete_file(instance, **kwargs):
126 def delete_file(instance, **kwargs):
127 if instance.is_internal():
127 if instance.is_internal():
128 file = MEDIA_ROOT + instance.file.name
128 file = MEDIA_ROOT + instance.file.name
129 os.remove(file)
129 try:
130 os.remove(file)
131 except FileNotFoundError:
132 pass
130 if instance.mimetype in FILE_TYPES_IMAGE:
133 if instance.mimetype in FILE_TYPES_IMAGE:
131 for size in THUMB_SIZES:
134 for size in THUMB_SIZES:
132 file_name_parts = instance.file.name.split('.')
135 file_name_parts = instance.file.name.split('.')
133 thumb_file = MEDIA_ROOT + '{}.{}x{}.{}'.format(file_name_parts[0], size[0], size[1], file_name_parts[1])
136 thumb_file = MEDIA_ROOT + '{}.{}x{}.{}'.format(file_name_parts[0], size[0], size[1], file_name_parts[1])
134 os.remove(thumb_file)
137 try:
138 os.remove(thumb_file)
139 except FileNotFoundError:
140 pass
135
141
@@ -1,31 +1,32 b''
1 from django.core.urlresolvers import reverse
1 from django.core.urlresolvers import reverse
2 from django.shortcuts import get_object_or_404, render
2 from django.shortcuts import get_object_or_404, 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.models import Tag
6 from boards.models import Tag
7 from boards.views.base import BaseBoardView
7 from boards.views.base import BaseBoardView
8 from boards.views.mixins import PaginatedMixin
8 from boards.views.mixins import PaginatedMixin
9
9
10 IMAGES_PER_PAGE = settings.get_int('View', 'ImagesPerPageGallery')
10 IMAGES_PER_PAGE = settings.get_int('View', 'ImagesPerPageGallery')
11
11
12 TEMPLATE = 'boards/tag_gallery.html'
12 TEMPLATE = 'boards/tag_gallery.html'
13
13
14
14
15 class TagGalleryView(BaseBoardView, PaginatedMixin):
15 class TagGalleryView(BaseBoardView, PaginatedMixin):
16
16
17 def get(self, request, tag_name):
17 def get(self, request, tag_name):
18 page = int(request.GET.get('page', 1))
18 page = int(request.GET.get('page', 1))
19
19
20 params = dict()
20 params = dict()
21 tag = get_object_or_404(Tag, name=tag_name)
21 tag_alias = get_object_or_404(TagAlias, name=tag_name)
22 tag = tag_alias.parent
22 params['tag'] = tag
23 params['tag'] = tag
23 paginator = get_paginator(tag.get_images(), IMAGES_PER_PAGE,
24 paginator = get_paginator(tag.get_images(), IMAGES_PER_PAGE,
24 current_page=page)
25 current_page=page)
25 params['paginator'] = paginator
26 params['paginator'] = paginator
26 params['images'] = paginator.page(page).object_list
27 params['images'] = paginator.page(page).object_list
27 paginator.set_url(reverse('tag_gallery', kwargs={'tag_name': tag_name}),
28 paginator.set_url(reverse('tag_gallery', kwargs={'tag_name': tag_name}),
28 request.GET.dict())
29 request.GET.dict())
29 params.update(self.get_page_context(paginator, page))
30 params.update(self.get_page_context(paginator, page))
30
31
31 return render(request, TEMPLATE, params)
32 return render(request, TEMPLATE, params)
General Comments 0
You need to be logged in to leave comments. Login now