Dénote

Dénote Git Source Tree

Root/denote/models.py

1# -*- coding: utf-8 -*-
2"""
3 Copyright 2015 Grégory Soutadé
4
5 This file is part of Dénote.
6
7 Dénote is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 Dénote is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Dénote. If not, see <http://www.gnu.org/licenses/>.
19"""
20
21from datetime import datetime
22import re
23
24from django.db import models
25from django.contrib.auth.models import AbstractUser
26from django.http import HttpResponse
27from django.db.models.signals import pre_init, post_init, pre_delete, post_delete
28from django.db.models.signals import pre_save, post_save
29from django.dispatch import receiver
30
31import markdown2
32from search import Search
33
34class User(AbstractUser):
35 hidden_categories = models.TextField(blank=True)
36 home_notes_visibility = models.IntegerField(default=0, choices=[(0, 'private'), (1, 'registered'), (2, 'public')])
37
38 def getPreference(self, name):
39 if name == 'hidden_categories':
40 return HttpResponse('{"hidden_categories" : [' + self.hidden_categories + ']}', 'application/json')
41 else:
42 raise Http404
43
44 def setPreference(self, name, value):
45 if name == 'hidden_categories':
46 categories = []
47 for c in value.split(','):
48 if c == '-1' or \
49 (c and Category.objects.filter(id=c).exists()):
50 categories.append(c)
51 self.hidden_categories = ','.join(categories)
52 self.save()
53 return HttpResponse('')
54 else:
55 raise Http404
56
57class Category(models.Model):
58 author = models.ForeignKey(User, null=True, on_delete=models.CASCADE)
59 name = models.CharField(max_length=50, unique=True, blank=False)
60
61class Note(models.Model):
62
63 PRIVATE = 0
64 REGISTERED = 1
65 PUBLIC = 2
66
67 VISIBILITY = ((PRIVATE, 'Private'),
68 (REGISTERED, 'Registered'),
69 (PUBLIC, 'Public')
70 )
71
72 author = models.ForeignKey(User, null=False, on_delete=models.CASCADE)
73 title = models.CharField(max_length=100, blank=False)
74 long_summary = models.CharField(max_length=255)
75 short_summary = models.CharField(max_length=255)
76 text = models.TextField(blank=False)
77 transformed_text = models.TextField()
78 created_date = models.DateTimeField()
79 modified_date = models.DateTimeField()
80 visibility = models.IntegerField(default=PRIVATE, choices=VISIBILITY)
81 category = models.ForeignKey(Category, null=True, on_delete=models.SET_NULL)
82
83 def _wrap(self, text, limit, max_limit):
84 if len(text) < limit: return text
85
86 lower_limit = upper_limit = limit
87
88 while text[lower_limit-1] != ' ' and\
89 lower_limit > 1:
90 lower_limit -= 1
91
92 while text[upper_limit-1] != ' ' and\
93 upper_limit < len(text):
94 upper_limit += 1
95
96 lower = limit - lower_limit
97 upper = upper_limit - limit
98
99 if lower > max_limit and upper > max_limit:
100 cur_limit = limit + max_limit
101 else:
102 if lower < upper:
103 cur_limit = limit - lower
104 else:
105 cur_limit = limit + upper
106
107 if cur_limit and text[cur_limit-1] == ' ':
108 cur_limit -= 1
109
110 return text[:cur_limit] + '...'
111
112 def _summarize(self):
113 # Remove markup
114 self.long_summary = re.sub(r'<[^>]+>', '', self.transformed_text)
115 self.long_summary = re.sub(r'&[^;]+;', '', self.long_summary)
116 # Remove return
117 self.long_summary = re.sub(r'\n', ' ', self.long_summary)
118 self.long_summary = re.sub(r'\r', ' ', self.long_summary)
119 # Remove duplicated spaces
120 self.long_summary = re.sub(r' [ ]+', ' ', self.long_summary)
121 self.long_summary = self.long_summary.strip()
122 self.short_summary = self.long_summary[:]
123
124 self.long_summary = self._wrap(self.long_summary, 100, 5)
125 self.short_summary = self._wrap(self.short_summary, 30, 5)
126
127 def save(self):
128 self.modified_date = datetime.now()
129 self.transformed_text = markdown2.markdown(self.text, extras=['fenced-code-blocks'])
130 self._summarize()
131 s = Search()
132
133 super(Note, self).save()
134
135@receiver(post_save, sender=Note)
136def post_save_note_signal(sender, **kwargs):
137 s = Search()
138 if kwargs['created']:
139 s.index_note(kwargs['instance'].id)
140 else:
141 s.edit_note(kwargs['instance'].id)
142
143@receiver(pre_delete, sender=Note)
144def pre_delete_note_signal(sender, **kwargs):
145 s = Search()
146 s.delete_note(kwargs['instance'].id)
147
148def manage_category(user, cat_name):
149 category = None
150 if cat_name:
151 category = Category.objects.filter(name=cat_name)
152 # Create a new one
153 if not category:
154 if len(cat_name) > 50: cat_name = cat_name[:50]
155 category = Category(author=user, name=cat_name)
156 category.save()
157 else:
158 category = category[0]
159 return category

Archive Download this file

Branches

Tags