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 default_template = models.ForeignKey('Template', null=True, on_delete=models.SET_NULL)
38
39 def getPreference(self, name):
40 if name == 'hidden_categories':
41 return HttpResponse('{"hidden_categories" : [' + self.hidden_categories + ']}', 'application/json')
42 else:
43 raise Http404
44
45 def setPreference(self, name, value):
46 if name == 'hidden_categories':
47 categories = []
48 for c in value.split(','):
49 if c == '-1' or \
50 (c and Category.objects.filter(id=c).exists()):
51 categories.append(c)
52 self.hidden_categories = ','.join(categories)
53 self.save()
54 return HttpResponse('')
55 else:
56 raise Http404
57
58class Category(models.Model):
59 author = models.ForeignKey(User, null=True, on_delete=models.CASCADE)
60 name = models.CharField(max_length=50, unique=True, blank=False)
61
62class Note(models.Model):
63
64 PRIVATE = 0
65 REGISTERED = 1
66 PUBLIC = 2
67
68 VISIBILITY = ((PRIVATE, 'Private'),
69 (REGISTERED, 'Registered'),
70 (PUBLIC, 'Public')
71 )
72
73 author = models.ForeignKey(User, null=False, on_delete=models.CASCADE)
74 title = models.CharField(max_length=100, blank=False)
75 long_summary = models.CharField(max_length=255)
76 short_summary = models.CharField(max_length=255)
77 text = models.TextField(blank=False)
78 transformed_text = models.TextField()
79 created_date = models.DateTimeField()
80 modified_date = models.DateTimeField()
81 visibility = models.IntegerField(default=PRIVATE, choices=VISIBILITY)
82 category = models.ForeignKey(Category, null=True, on_delete=models.SET_NULL)
83
84 def _wrap(self, text, limit, max_limit):
85 if len(text) < limit: return text
86
87 lower_limit = upper_limit = limit
88
89 while text[lower_limit-1] != ' ' and\
90 lower_limit > 1:
91 lower_limit -= 1
92
93 while text[upper_limit-1] != ' ' and\
94 upper_limit < len(text):
95 upper_limit += 1
96
97 lower = limit - lower_limit
98 upper = upper_limit - limit
99
100 if lower > max_limit and upper > max_limit:
101 cur_limit = limit + max_limit
102 else:
103 if lower < upper:
104 cur_limit = limit - lower
105 else:
106 cur_limit = limit + upper
107
108 if cur_limit and text[cur_limit-1] == ' ':
109 cur_limit -= 1
110
111 return text[:cur_limit] + '...'
112
113 def _summarize(self):
114 # Remove markup
115 self.long_summary = re.sub(r'<[^>]+>', '', self.transformed_text)
116 self.long_summary = re.sub(r'&[^;]+;', '', self.long_summary)
117 # Remove return
118 self.long_summary = re.sub(r'\n', ' ', self.long_summary)
119 self.long_summary = re.sub(r'\r', ' ', self.long_summary)
120 # Remove duplicated spaces
121 self.long_summary = re.sub(r' [ ]+', ' ', self.long_summary)
122 self.long_summary = self.long_summary.strip()
123 self.short_summary = self.long_summary[:]
124
125 self.long_summary = self._wrap(self.long_summary, 100, 5)
126 self.short_summary = self._wrap(self.short_summary, 30, 5)
127
128 def save(self):
129 self.modified_date = datetime.now()
130 self.transformed_text = markdown2.markdown(self.text, extras=['fenced-code-blocks'])
131 self._summarize()
132 s = Search()
133
134 super(Note, self).save()
135
136class Template(models.Model):
137 name = models.CharField(max_length=30, blank=False, unique=True)
138
139 author = models.ForeignKey(User, null=False, on_delete=models.CASCADE)
140 title = models.CharField(max_length=100, blank=True)
141 text = models.TextField(blank=True)
142 visibility = models.IntegerField(default=Note.PRIVATE, choices=Note.VISIBILITY)
143 category = models.ForeignKey(Category, null=True, on_delete=models.SET_NULL)
144
145@receiver(post_save, sender=Note)
146def post_save_note_signal(sender, **kwargs):
147 s = Search()
148 if kwargs['created']:
149 s.index_note(kwargs['instance'].id)
150 else:
151 s.edit_note(kwargs['instance'].id)
152
153@receiver(pre_delete, sender=Note)
154def pre_delete_note_signal(sender, **kwargs):
155 s = Search()
156 s.delete_note(kwargs['instance'].id)
157
158def manage_category(user, cat_name):
159 category = None
160 if cat_name:
161 category = Category.objects.filter(name=cat_name)
162 # Create a new one
163 if not category:
164 if len(cat_name) > 50: cat_name = cat_name[:50]
165 category = Category(author=user, name=cat_name)
166 category.save()
167 else:
168 category = category[0]
169 return category

Archive Download this file

Branches

Tags