forked from frappe/erpnext
/
web_cache.py
266 lines (210 loc) · 7.02 KB
/
web_cache.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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
# ERPNext - web based ERP (http://erpnext.com)
# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# html generation functions
from __future__ import unicode_literals
template_map = {
'Web Page': 'html/web_page.html',
'Blog': 'html/blog_page.html',
'Item': 'html/product_page.html',
}
def get_html(page_name, comments=''):
import conf
html = ''
# load from cache, if auto cache clear is falsy
if not (hasattr(conf, 'auto_cache_clear') and conf.auto_cache_clear or 0):
html = load_from_cache(page_name)
if not html:
html = load_into_cache(page_name)
comments += "\n\npage load status: fresh"
# insert comments
import webnotes.utils
html += """\n<!-- %s -->""" % webnotes.utils.cstr(comments)
return html
def load_from_cache(page_name):
import webnotes
result = search_cache(page_name)
if not result:
if page_name in get_predefined_pages():
# if a predefined page doesn't exist, load it into cache
return None
else:
# if page doesn't exist, raise exception
raise Exception, "Page %s not found" % page_name
return result[0][0]
def load_into_cache(page_name):
args = prepare_args(page_name)
html = build_html(args)
# create cache entry for predefined pages, if not exists
if page_name in get_predefined_pages():
create_cache(page_name)
import webnotes
webnotes.conn.begin()
webnotes.conn.set_value('Web Cache', page_name, 'html', html)
webnotes.conn.commit()
return html
def get_predefined_pages():
"""
gets a list of predefined pages
they do not exist in `tabWeb Page`
"""
import os
import conf
import website.utils
pages_path = os.path.join(os.path.dirname(conf.__file__), 'app', 'website', 'templates', 'pages')
page_list = []
for page in os.listdir(pages_path):
page_list.append(website.utils.scrub_page_name(page))
return page_list
def prepare_args(page_name):
import webnotes
if page_name == 'index':
page_name = get_home_page()
if page_name in get_predefined_pages():
args = {
'template': 'pages/%s.html' % page_name,
'name': page_name,
'webnotes': webnotes
}
else:
args = get_doc_fields(page_name)
args.update(get_outer_env())
return args
def get_home_page():
import webnotes
doc_name = webnotes.conn.get_value('Website Settings', None, 'home_page')
if doc_name:
page_name = webnotes.conn.get_value('Web Page', doc_name, 'page_name')
else:
page_name = 'login'
return page_name
def get_doc_fields(page_name):
import webnotes
doc_type, doc_name = webnotes.conn.get_value('Web Cache', page_name, ['doc_type', 'doc_name'])
import webnotes.model.code
obj = webnotes.model.code.get_obj(doc_type, doc_name)
if hasattr(obj, 'prepare_template_args'):
obj.prepare_template_args()
args = obj.doc.fields
args['template'] = template_map[doc_type]
return args
def get_outer_env():
"""
env dict for outer template
"""
import webnotes
all_top_items = webnotes.conn.sql("""\
select * from `tabTop Bar Item`
where parent='Website Settings' and parentfield='top_bar_items'
order by idx asc""", as_dict=1)
top_items = [d for d in all_top_items if not d['parent_label']]
# attach child items to top bar
for d in all_top_items:
if d['parent_label']:
for t in top_items:
if t['label']==d['parent_label']:
if not 'child_items' in t:
t['child_items'] = []
t['child_items'].append(d)
break
return {
'top_bar_items': top_items,
'footer_items': webnotes.conn.sql("""\
select * from `tabTop Bar Item`
where parent='Website Settings' and parentfield='footer_items'
order by idx asc""", as_dict=1),
'brand': webnotes.conn.get_value('Website Settings', None, 'brand_html') or 'ERPNext',
'copyright': webnotes.conn.get_value('Website Settings', None, 'copyright'),
'favicon': webnotes.conn.get_value('Website Settings', None, 'favicon')
}
def build_html(args):
"""
build html using jinja2 templates
"""
import os
import conf
templates_path = os.path.join(os.path.dirname(conf.__file__), 'app', 'website', 'templates')
from jinja2 import Environment, FileSystemLoader
jenv = Environment(loader = FileSystemLoader(templates_path))
html = jenv.get_template(args['template']).render(args)
return html
# cache management
def search_cache(page_name):
if not page_name: return ()
import webnotes
return webnotes.conn.sql("""\
select html, doc_type, doc_name
from `tabWeb Cache`
where name = %s""", page_name)
def create_cache(page_name, doc_type=None, doc_name=None):
# check if a record already exists
result = search_cache(page_name)
if result: return
# create a Web Cache record
import webnotes.model.doc
d = webnotes.model.doc.Document('Web Cache')
d.name = page_name
d.doc_type = doc_type
d.doc_name = doc_name
d.html = None
d.save()
def clear_cache(page_name, doc_type=None, doc_name=None):
"""
* if no page name, clear whole cache
* if page_name, doc_type and doc_name match, clear cache's copy
* else, raise exception that such a page already exists
"""
import webnotes
if not page_name:
webnotes.conn.sql("""update `tabWeb Cache` set html = ''""")
return
result = search_cache(page_name)
if not doc_type or (result and result[0][1] == doc_type and result[0][2] == doc_name):
webnotes.conn.set_value('Web Cache', page_name, 'html', '')
else:
webnotes.msgprint("""Page with name "%s" already exists as a %s.
Please save it with another name.""" % (page_name, result[0][1]),
raise_exception=1)
def delete_cache(page_name):
"""
delete entry of page_name from Web Cache
used when:
* web page is deleted
* blog is un-published
"""
import webnotes
webnotes.conn.sql("""delete from `tabWeb Cache` where name=%s""", page_name)
def refresh_cache(build=None):
"""delete and re-create web cache entries"""
import webnotes
# webnotes.conn.sql("delete from `tabWeb Cache`")
clear_cache(None)
query_map = {
'Web Page': """select page_name, name from `tabWeb Page` where docstatus=0""",
'Blog': """\
select page_name, name from `tabBlog`
where docstatus = 0 and ifnull(published, 0) = 1""",
'Item': """\
select page_name, name from `tabItem`
where docstatus = 0 and ifnull(show_in_website, 0) = 1""",
}
for dt in query_map:
if build and dt in build:
for result in webnotes.conn.sql(query_map[dt], as_dict=1):
create_cache(result['page_name'], dt, result['name'])
load_into_cache(result['page_name'])
for page_name in get_predefined_pages():
create_cache(page_name, None, None)
if build: load_into_cache(page_name)