This repository has been archived by the owner on Mar 19, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 18
/
models.py
108 lines (88 loc) · 3.44 KB
/
models.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import datetime
from flask import Markup
from markdown import markdown
from markdown.extensions.codehilite import CodeHiliteExtension
from markdown.extensions.extra import ExtraExtension
from playhouse.sqlite_ext import *
from playhouse.fields import ManyToManyField
from app import application, flask_db, database
class Entry(flask_db.Model):
title = CharField()
slug = CharField(unique=True)
content = TextField()
timestamp = DateTimeField(default=datetime.datetime.now, index=True)
lastedited = DateTimeField(default=datetime.datetime.now, index=True)
archived = BooleanField(default=False)
@property
def html_content(self):
"""
Generate HTML representation of the markdown-formatted note,
and also convert any media URLs into rich media objects such as video
players or images.
"""
hilite = CodeHiliteExtension(linenums=False, css_class='highlight')
extras = ExtraExtension()
markdown_content = markdown(self.content, extensions=[hilite, extras])
return Markup(markdown_content)
def save(self, *args, **kwargs):
# Generate a URL-friendly representation of the entry's title.
if not self.slug:
self.slug = re.sub('[^\w]+', '-', self.title.lower()).strip('-')
ret = super(Entry, self).save(*args, **kwargs)
# Store search content.
self.update_search_index()
return ret
def update_search_index(self):
# Create a row in the FTSEntry table with the post content. This will
# allow us to use SQLite's awesome full-text search extension to
# search our entries.
try:
fts_entry = FTSEntry.get(FTSEntry.entry_id == self.id)
except FTSEntry.DoesNotExist:
fts_entry = FTSEntry(entry_id=self.id)
force_insert = True
else:
query = FTSEntry.delete().where(FTSEntry.entry_id == self.id)
query.execute()
force_insert = True
fts_entry.content = '\n'.join((self.title, self.content))
fts_entry.save(force_insert=force_insert)
@classmethod
def public(cls):
return Entry.select().where(Entry.archived == False)
@classmethod
def all(cls):
return Entry.select()
@classmethod
def archive(cls):
return Entry.select().where(Entry.archived == True)
@classmethod
def search(cls, query):
words = [word.strip() for word in query.split() if word.strip()]
if not words:
# Return an empty query.
return Entry.select().where(Entry.id == 0)
else:
search = ' '.join(words)
# Query the full-text search index for entries matching the given
# search query, then join the actual Entry data on the matching
# search result.
return (FTSEntry
.select(
FTSEntry,
Entry,
FTSEntry.rank().alias('score'))
.join(Entry, on=(FTSEntry.entry_id == Entry.id).alias('entry'))
.where(
(Entry.archived == False) &
(FTSEntry.match(search)))
.order_by(SQL('score').desc()))
class Tag(flask_db.Model):
tag = CharField()
entries = ManyToManyField(Entry, related_name='tags')
EntryTags = Tag.entries.get_through_model()
class FTSEntry(FTSModel):
entry_id = IntegerField(Entry)
content = TextField()
class Meta:
database = database