Bläddra i källkod

Replaced doc, doc.fields frappe/frappe#478

version-14
Anand Doshi 11 år sedan
förälder
incheckning
f1eb0dd005
67 ändrade filer med 507 tillägg och 502 borttagningar
  1. +1
    -1
      frappe/boot.py
  2. +3
    -3
      frappe/client.py
  3. +15
    -15
      frappe/core/doctype/comment/comment.py
  4. +5
    -5
      frappe/core/doctype/comment/test_comment.py
  5. +4
    -4
      frappe/core/doctype/communication/communication.py
  6. +19
    -19
      frappe/core/doctype/custom_field/custom_field.py
  7. +3
    -3
      frappe/core/doctype/custom_script/custom_script.py
  8. +31
    -31
      frappe/core/doctype/customize_form/customize_form.py
  9. +6
    -6
      frappe/core/doctype/doctype/doctype.py
  10. +10
    -10
      frappe/core/doctype/file_data/file_data.py
  11. +6
    -6
      frappe/core/doctype/letter_head/letter_head.py
  12. +1
    -1
      frappe/core/doctype/notification_count/notification_count.py
  13. +7
    -7
      frappe/core/doctype/outgoing_email_settings/outgoing_email_settings.py
  14. +10
    -10
      frappe/core/doctype/print_format/print_format.py
  15. +11
    -11
      frappe/core/doctype/property_setter/property_setter.py
  16. +10
    -10
      frappe/core/doctype/report/report.py
  17. +9
    -9
      frappe/core/doctype/todo/todo.py
  18. +1
    -1
      frappe/core/doctype/user/test_user.py
  19. +43
    -43
      frappe/core/doctype/user/user.py
  20. +2
    -2
      frappe/core/doctype/userrole/userrole.py
  21. +13
    -13
      frappe/core/doctype/workflow/workflow.py
  22. +5
    -5
      frappe/core/page/data_import_tool/data_import_tool.py
  23. +2
    -2
      frappe/model/__init__.py
  24. +6
    -1
      frappe/model/base_document.py
  25. +4
    -4
      frappe/model/code.py
  26. +2
    -2
      frappe/model/controller.py
  27. +10
    -10
      frappe/model/create_new.py
  28. +8
    -8
      frappe/model/mapper.py
  29. +4
    -4
      frappe/model/meta.py
  30. +1
    -1
      frappe/model/utils.py
  31. +1
    -1
      frappe/modules/__init__.py
  32. +11
    -11
      frappe/templates/generators/web_page.py
  33. +5
    -5
      frappe/templates/generators/website_group.py
  34. +6
    -6
      frappe/templates/includes/comments.py
  35. +4
    -4
      frappe/templates/pages/contact.py
  36. +5
    -5
      frappe/templates/pages/login.py
  37. +2
    -2
      frappe/templates/pages/style_settings.py
  38. +15
    -15
      frappe/templates/website_group/post.py
  39. +3
    -3
      frappe/templates/website_group/settings.py
  40. +7
    -7
      frappe/test_runner.py
  41. +2
    -2
      frappe/utils/datautils.py
  42. +3
    -3
      frappe/utils/file_manager.py
  43. +20
    -20
      frappe/utils/nestedset.py
  44. +1
    -1
      frappe/utils/response.py
  45. +1
    -1
      frappe/utils/user.py
  46. +2
    -2
      frappe/website/doctype/blog_category/blog_category.py
  47. +11
    -11
      frappe/website/doctype/blog_post/blog_post.py
  48. +1
    -1
      frappe/website/doctype/blog_post/test_blog_post.py
  49. +3
    -3
      frappe/website/doctype/blogger/blogger.py
  50. +30
    -30
      frappe/website/doctype/post/post.py
  51. +4
    -4
      frappe/website/doctype/style_settings/style_settings.py
  52. +5
    -5
      frappe/website/doctype/user_vote/user_vote.py
  53. +4
    -4
      frappe/website/doctype/web_page/test_web_page.py
  54. +3
    -3
      frappe/website/doctype/website_group/website_group.py
  55. +49
    -49
      frappe/website/doctype/website_route/website_route.py
  56. +1
    -1
      frappe/website/doctype/website_route_permission/website_route_permission.py
  57. +3
    -3
      frappe/website/doctype/website_settings/website_settings.py
  58. +2
    -2
      frappe/website/doctype/website_slideshow/website_slideshow.py
  59. +9
    -9
      frappe/website/doctype/website_template/website_template.py
  60. +1
    -1
      frappe/website/page/sitemap_browser/sitemap_browser.py
  61. +10
    -10
      frappe/website/statics.py
  62. +23
    -23
      frappe/website/website_generator.py
  63. +2
    -2
      frappe/widgets/calendar.py
  64. +1
    -1
      frappe/widgets/event.py
  65. +2
    -2
      frappe/widgets/form/assign_to.py
  66. +1
    -1
      frappe/widgets/form/run_method.py
  67. +2
    -2
      frappe/widgets/query_report.py

+ 1
- 1
frappe/boot.py Visa fil

@@ -22,7 +22,7 @@ def get_bootinfo():
get_user(bootinfo) get_user(bootinfo)
# control panel # control panel
cp = frappe.model.doc.getsingle('Control Panel')
cp = frappe.model.getsingle('Control Panel')
# system info # system info
bootinfo['control_panel'] = frappe._dict(cp.copy()) bootinfo['control_panel'] = frappe._dict(cp.copy())


+ 3
- 3
frappe/client.py Visa fil

@@ -34,10 +34,10 @@ def set_value(doctype, name, fieldname, value):
if doc and doc.parent: if doc and doc.parent:
bean = frappe.bean(doc.parenttype, doc.parent) bean = frappe.bean(doc.parenttype, doc.parent)
child = bean.doclist.getone({"doctype": doctype, "name": name}) child = bean.doclist.getone({"doctype": doctype, "name": name})
child.fields[fieldname] = value
child.set(fieldname, value)
else: else:
bean = frappe.bean(doctype, name) bean = frappe.bean(doctype, name)
bean.doc.fields[fieldname] = value
bean.set(fieldname, value)
bean.save() bean.save()
@@ -120,7 +120,7 @@ def bulk_update(docs):
doctype = doc['doctype'] doctype = doc['doctype']
docname = doc['docname'] docname = doc['docname']
bean = frappe.bean(doctype, docname) bean = frappe.bean(doctype, docname)
bean.doc.update(ddoc)
bean.update(ddoc)
bean.save() bean.save()
except: except:
failed_docs.append({ failed_docs.append({


+ 15
- 15
frappe/core/doctype/comment/comment.py Visa fil

@@ -11,33 +11,33 @@ class Comment(Document):
def validate(self): def validate(self):
if frappe.db.sql("""select count(*) from tabComment where comment_doctype=%s if frappe.db.sql("""select count(*) from tabComment where comment_doctype=%s
and comment_docname=%s""", (self.doc.doctype, self.doc.name))[0][0] >= 50:
and comment_docname=%s""", (self.doctype, self.name))[0][0] >= 50:
frappe.msgprint("Max Comments reached!", raise_exception=True) frappe.msgprint("Max Comments reached!", raise_exception=True)
def on_update(self): def on_update(self):
self.update_comment_in_doc() self.update_comment_in_doc()
def update_comment_in_doc(self): def update_comment_in_doc(self):
if self.doc.comment_doctype and self.doc.comment_docname and self.doc.comment:
if self.comment_doctype and self.comment_docname and self.comment:
try: try:
_comments = self.get_comments_from_parent() _comments = self.get_comments_from_parent()
updated = False updated = False
for c in _comments: for c in _comments:
if c.get("name")==self.doc.name:
c["comment"] = self.doc.comment
if c.get("name")==self.name:
c["comment"] = self.comment
updated = True updated = True
if not updated: if not updated:
_comments.append({ _comments.append({
"comment": self.doc.comment,
"by": self.doc.comment_by or self.doc.owner,
"name":self.doc.name
"comment": self.comment,
"by": self.comment_by or self.owner,
"name":self.name
}) })
self.update_comments_in_parent(_comments) self.update_comments_in_parent(_comments)
except Exception, e: except Exception, e:
if e.args[0]==1054: if e.args[0]==1054:
from frappe.model.db_schema import add_column from frappe.model.db_schema import add_column
add_column(self.doc.comment_doctype, "_comments", "Text")
add_column(self.comment_doctype, "_comments", "Text")
self.update_comment_in_doc() self.update_comment_in_doc()
elif e.args[0]==1146: elif e.args[0]==1146:
# no table # no table
@@ -46,18 +46,18 @@ class Comment(Document):
raise raise
def get_comments_from_parent(self): def get_comments_from_parent(self):
_comments = frappe.db.get_value(self.doc.comment_doctype,
self.doc.comment_docname, "_comments") or "[]"
_comments = frappe.db.get_value(self.comment_doctype,
self.comment_docname, "_comments") or "[]"
return json.loads(_comments) return json.loads(_comments)
def update_comments_in_parent(self, _comments): def update_comments_in_parent(self, _comments):
# use sql, so that we do not mess with the timestamp # use sql, so that we do not mess with the timestamp
frappe.db.sql("""update `tab%s` set `_comments`=%s where name=%s""" % (self.doc.comment_doctype,
"%s", "%s"), (json.dumps(_comments), self.doc.comment_docname))
frappe.db.sql("""update `tab%s` set `_comments`=%s where name=%s""" % (self.comment_doctype,
"%s", "%s"), (json.dumps(_comments), self.comment_docname))
# clear parent cache if route exists: # clear parent cache if route exists:
route = frappe.db.get_value("Website Route", {"ref_doctype": self.doc.comment_doctype,
"docname": self.doc.comment_docname})
route = frappe.db.get_value("Website Route", {"ref_doctype": self.comment_doctype,
"docname": self.comment_docname})
if route: if route:
clear_cache(route) clear_cache(route)
@@ -65,7 +65,7 @@ class Comment(Document):
def on_trash(self): def on_trash(self):
_comments = self.get_comments_from_parent() _comments = self.get_comments_from_parent()
for c in _comments: for c in _comments:
if c.get("name")==self.doc.name:
if c.get("name")==self.name:
_comments.remove(c) _comments.remove(c)
self.update_comments_in_parent(_comments) self.update_comments_in_parent(_comments)


+ 5
- 5
frappe/core/doctype/comment/test_comment.py Visa fil

@@ -31,19 +31,19 @@ import frappe, unittest, json
# def test_add_comment(self): # def test_add_comment(self):
# self.comment = frappe.bean({ # self.comment = frappe.bean({
# "doctype":"Comment", # "doctype":"Comment",
# "comment_doctype": self.test_rec.doc.doctype,
# "comment_docname": self.test_rec.doc.name,
# "comment_doctype": self.test_rec.doctype,
# "comment_docname": self.test_rec.name,
# "comment": "__Test Comment" # "comment": "__Test Comment"
# }).insert() # }).insert()
# #
# test_rec = frappe.doc(self.test_rec.doc.doctype, self.test_rec.doc.name)
# test_rec = frappe.doc(self.test_rec.doctype, self.test_rec.name)
# _comments = json.loads(test_rec.get("_comments")) # _comments = json.loads(test_rec.get("_comments"))
# self.assertTrue(_comments[0].get("comment")=="__Test Comment") # self.assertTrue(_comments[0].get("comment")=="__Test Comment")
# #
# def test_remove_comment(self): # def test_remove_comment(self):
# self.test_add_comment() # self.test_add_comment()
# frappe.delete_doc("Comment", self.comment.doc.name)
# test_rec = frappe.doc(self.test_rec.doc.doctype, self.test_rec.doc.name)
# frappe.delete_doc("Comment", self.comment.name)
# test_rec = frappe.doc(self.test_rec.doctype, self.test_rec.name)
# _comments = json.loads(test_rec.get("_comments")) # _comments = json.loads(test_rec.get("_comments"))
# self.assertEqual(len(_comments), 0) # self.assertEqual(len(_comments), 0)
# #


+ 4
- 4
frappe/core/doctype/communication/communication.py Visa fil

@@ -16,7 +16,7 @@ from frappe.model.document import Document


class Communication(Document): class Communication(Document):
def get_parent_bean(self): def get_parent_bean(self):
return frappe.bean(self.doc.parenttype, self.doc.parent)
return frappe.bean(self.parenttype, self.parent)
def update_parent(self): def update_parent(self):
"""update status of parent Lead or Contact based on who is replying""" """update status of parent Lead or Contact based on who is replying"""
@@ -147,10 +147,10 @@ def set_portal_link(sent_via, comm):
if is_signup_enabled() and hasattr(sent_via, "get_portal_page"): if is_signup_enabled() and hasattr(sent_via, "get_portal_page"):
portal_page = sent_via.get_portal_page() portal_page = sent_via.get_portal_page()
if portal_page: if portal_page:
is_valid_recipient = cstr(sent_via.doc.email or sent_via.doc.email_id or
sent_via.doc.contact_email) in comm.recipients
is_valid_recipient = cstr(sent_via.email or sent_via.email_id or
sent_via.contact_email) in comm.recipients
if is_valid_recipient: if is_valid_recipient:
url = "%s/%s?name=%s" % (get_url(), portal_page, urllib.quote(sent_via.doc.name))
url = "%s/%s?name=%s" % (get_url(), portal_page, urllib.quote(sent_via.name))
footer = """<!-- Portal Link --><hr> footer = """<!-- Portal Link --><hr>
<a href="%s" target="_blank">View this on our website</a>""" % url <a href="%s" target="_blank">View this on our website</a>""" % url


+ 19
- 19
frappe/core/doctype/custom_field/custom_field.py Visa fil

@@ -12,39 +12,39 @@ class CustomField(Document):
def autoname(self): def autoname(self):
self.set_fieldname() self.set_fieldname()
self.doc.name = self.doc.dt + "-" + self.doc.fieldname
self.name = self.dt + "-" + self.fieldname


def set_fieldname(self): def set_fieldname(self):
if not self.doc.fieldname:
if not self.doc.label:
if not self.fieldname:
if not self.label:
frappe.throw(_("Label is mandatory")) frappe.throw(_("Label is mandatory"))
# remove special characters from fieldname # remove special characters from fieldname
self.doc.fieldname = filter(lambda x: x.isdigit() or x.isalpha() or '_',
cstr(self.doc.label).lower().replace(' ','_'))
self.fieldname = filter(lambda x: x.isdigit() or x.isalpha() or '_',
cstr(self.label).lower().replace(' ','_'))


def validate(self): def validate(self):
from frappe.model.doctype import get from frappe.model.doctype import get
temp_doclist = get(self.doc.dt).get_parent_doclist()
temp_doclist = get(self.dt).get_parent_doclist()
# set idx # set idx
if not self.doc.idx:
if not self.idx:
max_idx = max(d.idx for d in temp_doclist if d.doctype=='DocField') max_idx = max(d.idx for d in temp_doclist if d.doctype=='DocField')
self.doc.idx = cint(max_idx) + 1
self.idx = cint(max_idx) + 1
def on_update(self): def on_update(self):
# validate field # validate field
from frappe.core.doctype.doctype.doctype import validate_fields_for_doctype from frappe.core.doctype.doctype.doctype import validate_fields_for_doctype


validate_fields_for_doctype(self.doc.dt)
validate_fields_for_doctype(self.dt)


frappe.clear_cache(doctype=self.doc.dt)
frappe.clear_cache(doctype=self.dt)
# create property setter to emulate insert after # create property setter to emulate insert after
self.create_property_setter() self.create_property_setter()


# update the schema # update the schema
from frappe.model.db_schema import updatedb from frappe.model.db_schema import updatedb
updatedb(self.doc.dt)
updatedb(self.dt)


def on_trash(self): def on_trash(self):
# delete property setter entries # delete property setter entries
@@ -52,14 +52,14 @@ class CustomField(Document):
DELETE FROM `tabProperty Setter` DELETE FROM `tabProperty Setter`
WHERE doc_type = %s WHERE doc_type = %s
AND field_name = %s""", AND field_name = %s""",
(self.doc.dt, self.doc.fieldname))
(self.dt, self.fieldname))


frappe.clear_cache(doctype=self.doc.dt)
frappe.clear_cache(doctype=self.dt)


def create_property_setter(self): def create_property_setter(self):
if not self.doc.insert_after: return
idx_label_list, field_list = get_fields_label(self.doc.dt, 0)
label_index = idx_label_list.index(self.doc.insert_after)
if not self.insert_after: return
idx_label_list, field_list = get_fields_label(self.dt, 0)
label_index = idx_label_list.index(self.insert_after)
if label_index==-1: return if label_index==-1: return


prev_field = field_list[label_index] prev_field = field_list[label_index]
@@ -67,11 +67,11 @@ class CustomField(Document):
DELETE FROM `tabProperty Setter` DELETE FROM `tabProperty Setter`
WHERE doc_type = %s WHERE doc_type = %s
AND field_name = %s AND field_name = %s
AND property = 'previous_field'""", (self.doc.dt, self.doc.fieldname))
AND property = 'previous_field'""", (self.dt, self.fieldname))
frappe.make_property_setter({ frappe.make_property_setter({
"doctype":self.doc.dt,
"fieldname": self.doc.fieldname,
"doctype":self.dt,
"fieldname": self.fieldname,
"property": "previous_field", "property": "previous_field",
"value": prev_field "value": prev_field
}) })


+ 3
- 3
frappe/core/doctype/custom_script/custom_script.py Visa fil

@@ -9,11 +9,11 @@ from frappe.model.document import Document
class CustomScript(Document): class CustomScript(Document):
def autoname(self): def autoname(self):
self.doc.name = self.doc.dt + "-" + self.doc.script_type
self.name = self.dt + "-" + self.script_type


def on_update(self): def on_update(self):
frappe.clear_cache(doctype=self.doc.dt)
frappe.clear_cache(doctype=self.dt)
def on_trash(self): def on_trash(self):
frappe.clear_cache(doctype=self.doc.dt)
frappe.clear_cache(doctype=self.dt)



+ 31
- 31
frappe/core/doctype/customize_form/customize_form.py Visa fil

@@ -58,11 +58,11 @@ class CustomizeForm(Document):
""" """
self.clear() self.clear()


if self.doc.doc_type:
if self.doc_type:
for d in self.get_ref_doclist(): for d in self.get_ref_doclist():
if d.doctype=='DocField': if d.doctype=='DocField':
new = self.doc.append('fields', {})
new = self.append('fields', {})
self.set( self.set(
{ {
'list': self.docfield_properties, 'list': self.docfield_properties,
@@ -76,15 +76,15 @@ class CustomizeForm(Document):


def get_ref_doclist(self): def get_ref_doclist(self):
""" """
* Gets doclist of type self.doc.doc_type
* Gets doclist of type self.doc_type
* Applies property setter properties on the doclist * Applies property setter properties on the doclist
* returns the modified doclist * returns the modified doclist
""" """
from frappe.model.doctype import get from frappe.model.doctype import get
ref_doclist = get(self.doc.doc_type)
ref_doclist = get(self.doc_type)
ref_doclist = frappe.doclist([ref_doclist[0]] ref_doclist = frappe.doclist([ref_doclist[0]]
+ ref_doclist.get({"parent": self.doc.doc_type}))
+ ref_doclist.get({"parent": self.doc_type}))


return ref_doclist return ref_doclist


@@ -115,10 +115,10 @@ class CustomizeForm(Document):
if 'list' in args: if 'list' in args:
if 'value' in args: if 'value' in args:
for f in args['list']: for f in args['list']:
args['doc_to_set'].fields[f] = None
args['doc_to_set'].set(f, None)
elif 'doc' in args: elif 'doc' in args:
for f in args['list']: for f in args['list']:
args['doc_to_set'].fields[f] = args['doc'].fields.get(f)
args['doc_to_set'].set(f, args['doc'].get(f))
else: else:
frappe.msgprint("Please specify args['list'] to set", raise_exception=1) frappe.msgprint("Please specify args['list'] to set", raise_exception=1)


@@ -127,13 +127,13 @@ class CustomizeForm(Document):
""" """
Save diff between Customize Form Bean and DocType Bean as property setter entries Save diff between Customize Form Bean and DocType Bean as property setter entries
""" """
if self.doc.doc_type:
if self.doc_type:
from frappe.model import doc from frappe.model import doc
from frappe.core.doctype.doctype.doctype import validate_fields_for_doctype from frappe.core.doctype.doctype.doctype import validate_fields_for_doctype
this_doclist = frappe.doclist([self.doc] + self.doclist) this_doclist = frappe.doclist([self.doc] + self.doclist)
ref_doclist = self.get_ref_doclist() ref_doclist = self.get_ref_doclist()
dt_doclist = doc.get('DocType', self.doc.doc_type)
dt_doclist = doc.get('DocType', self.doc_type)
# get a list of property setter docs # get a list of property setter docs
self.idx_dirty = False self.idx_dirty = False
@@ -144,9 +144,9 @@ class CustomizeForm(Document):
self.set_properties(diff_list) self.set_properties(diff_list)


validate_fields_for_doctype(self.doc.doc_type)
validate_fields_for_doctype(self.doc_type)


frappe.clear_cache(doctype=self.doc.doc_type)
frappe.clear_cache(doctype=self.doc_type)
frappe.msgprint("Updated") frappe.msgprint("Updated")




@@ -207,15 +207,15 @@ class CustomizeForm(Document):




def has_property_changed(self, ref_d, new_d, prop): def has_property_changed(self, ref_d, new_d, prop):
return new_d.fields.get(prop) != ref_d.fields.get(prop) \
return new_d.get(prop) != ref_d.get(prop) \
and not \ and not \
( \ ( \
new_d.fields.get(prop) in [None, 0] \
and ref_d.fields.get(prop) in [None, 0] \
new_d.get(prop) in [None, 0] \
and ref_d.get(prop) in [None, 0] \
) and not \ ) and not \
( \ ( \
new_d.fields.get(prop) in [None, ''] \
and ref_d.fields.get(prop) in [None, ''] \
new_d.get(prop) in [None, ''] \
and ref_d.get(prop) in [None, ''] \
) )
def prepare_to_set(self, prop, new_d, ref_d, dt_doclist, delete=0): def prepare_to_set(self, prop, new_d, ref_d, dt_doclist, delete=0):
@@ -230,26 +230,26 @@ class CustomizeForm(Document):
# If yes, we need to delete the property setter entry # If yes, we need to delete the property setter entry
for dt_d in dt_doclist: for dt_d in dt_doclist:
if dt_d.name == ref_d.name \ if dt_d.name == ref_d.name \
and (new_d.fields.get(prop) == dt_d.fields.get(prop) \
and (new_d.get(prop) == dt_d.get(prop) \
or \ or \
( \ ( \
new_d.fields.get(prop) in [None, 0] \
and dt_d.fields.get(prop) in [None, 0] \
new_d.get(prop) in [None, 0] \
and dt_d.get(prop) in [None, 0] \
) or \ ) or \
( \ ( \
new_d.fields.get(prop) in [None, ''] \
and dt_d.fields.get(prop) in [None, ''] \
new_d.get(prop) in [None, ''] \
and dt_d.get(prop) in [None, ''] \
)): )):
delete = 1 delete = 1
break break
value = new_d.fields.get(prop)
value = new_d.get(prop)
if prop in self.property_restrictions: if prop in self.property_restrictions:
allow_change = False allow_change = False
for restrict_list in self.property_restrictions.get(prop): for restrict_list in self.property_restrictions.get(prop):
if value in restrict_list and \ if value in restrict_list and \
ref_d.fields.get(prop) in restrict_list:
ref_d.get(prop) in restrict_list:
allow_change = True allow_change = True
break break
if not allow_change: if not allow_change:
@@ -258,8 +258,8 @@ class CustomizeForm(Document):
%s can only be changed among %s. %s can only be changed among %s.
<i>Ignoring this change and saving.</i>""" % \ <i>Ignoring this change and saving.</i>""" % \
(self.defaults.get(prop, {}).get("label") or prop, (self.defaults.get(prop, {}).get("label") or prop,
new_d.fields.get("label") or new_d.fields.get("idx"),
ref_d.fields.get(prop), value,
new_d.get("label") or new_d.get("idx"),
ref_d.get(prop), value,
self.defaults.get(prop, {}).get("label") or prop, self.defaults.get(prop, {}).get("label") or prop,
" -or- ".join([", ".join(r) for r in \ " -or- ".join([", ".join(r) for r in \
self.property_restrictions.get(prop)])), raise_exception=True) self.property_restrictions.get(prop)])), raise_exception=True)
@@ -269,7 +269,7 @@ class CustomizeForm(Document):
# create a property setter doc, but dont save it yet. # create a property setter doc, but dont save it yet.
d = frappe.get_doc('Property Setter') d = frappe.get_doc('Property Setter')
d.doctype_or_field = ref_d.doctype=='DocField' and 'DocField' or 'DocType' d.doctype_or_field = ref_d.doctype=='DocField' and 'DocField' or 'DocType'
d.doc_type = self.doc.doc_type
d.doc_type = self.doc_type
d.field_name = ref_d.fieldname d.field_name = ref_d.fieldname
d.property = prop d.property = prop
d.value = value d.value = value
@@ -295,7 +295,7 @@ class CustomizeForm(Document):
d = frappe.doc('Property Setter') d = frappe.doc('Property Setter')
d.doctype_or_field = 'DocType' d.doctype_or_field = 'DocType'
d.doc_type = self.doc.doc_type
d.doc_type = self.doc_type
d.property = "_idx" d.property = "_idx"
d.value = json.dumps(fields) d.value = json.dumps(fields)
d.property_type = "Text" d.property_type = "Text"
@@ -310,7 +310,7 @@ class CustomizeForm(Document):
""" """
for d in ps_doclist: for d in ps_doclist:
# Delete existing property setter entry # Delete existing property setter entry
if not d.fields.get("field_name"):
if not d.get("field_name"):
frappe.db.sql(""" frappe.db.sql("""
DELETE FROM `tabProperty Setter` DELETE FROM `tabProperty Setter`
WHERE doc_type = %(doc_type)s WHERE doc_type = %(doc_type)s
@@ -332,12 +332,12 @@ class CustomizeForm(Document):
Deletes all property setter entries for the selected doctype Deletes all property setter entries for the selected doctype
and resets it to standard and resets it to standard
""" """
if self.doc.doc_type:
if self.doc_type:
frappe.db.sql(""" frappe.db.sql("""
DELETE FROM `tabProperty Setter` DELETE FROM `tabProperty Setter`
WHERE doc_type = %s""", self.doc.doc_type)
WHERE doc_type = %s""", self.doc_type)
frappe.clear_cache(doctype=self.doc.doc_type)
frappe.clear_cache(doctype=self.doc_type)


self.get() self.get()




+ 6
- 6
frappe/core/doctype/doctype/doctype.py Visa fil

@@ -277,10 +277,10 @@ def validate_permissions(permissions, for_remove=False):
if d.amend and not d.write: if d.amend and not d.write:
frappe.msgprint(get_txt(d) + " Cannot set Amend if Cancel is not set.", frappe.msgprint(get_txt(d) + " Cannot set Amend if Cancel is not set.",
raise_exception=True) raise_exception=True)
if (d.fields.get("import") or d.export) and not d.report:
if (d.get("import") or d.export) and not d.report:
frappe.msgprint(get_txt(d) + " Cannot set Import or Export permission if Report is not set.", frappe.msgprint(get_txt(d) + " Cannot set Import or Export permission if Report is not set.",
raise_exception=True) raise_exception=True)
if d.fields.get("import") and not d.create:
if d.get("import") and not d.create:
frappe.msgprint(get_txt(d) + " Cannot set Import if Create is not set.", frappe.msgprint(get_txt(d) + " Cannot set Import if Create is not set.",
raise_exception=True) raise_exception=True)
@@ -292,8 +292,8 @@ def validate_permissions(permissions, for_remove=False):
frappe.msgprint("{doctype} {meaningless}".format(doctype=doctype, frappe.msgprint("{doctype} {meaningless}".format(doctype=doctype,
meaningless=_("is a single DocType, permission of type Report is meaningless."))) meaningless=_("is a single DocType, permission of type Report is meaningless.")))
d.report = 0 d.report = 0
d.fields["import"] = 0
d.fields["export"] = 0
d.set("import", 0)
d.set("export", 0)
if d.restrict: if d.restrict:
frappe.msgprint("{doctype} {meaningless}".format(doctype=doctype, frappe.msgprint("{doctype} {meaningless}".format(doctype=doctype,
@@ -309,7 +309,7 @@ def validate_permissions(permissions, for_remove=False):
raise_exception=True) raise_exception=True)
def check_if_importable(d): def check_if_importable(d):
if d.fields.get("import") and not isimportable:
if d.get("import") and not isimportable:
frappe.throw("{doctype}: {not_importable}".format(doctype=doctype, frappe.throw("{doctype}: {not_importable}".format(doctype=doctype,
not_importable=_("is not allowed to be imported, cannot assign import rights."))) not_importable=_("is not allowed to be imported, cannot assign import rights.")))
@@ -337,7 +337,7 @@ def make_module_and_roles(doc, perm_fieldname="permissions"):
for role in list(set(roles)): for role in list(set(roles)):
if not frappe.db.exists("Role", role): if not frappe.db.exists("Role", role):
r = frappe.bean({"doctype": "Role", "role_name": role}) r = frappe.bean({"doctype": "Role", "role_name": role})
r.doc.role_name = role
r.role_name = role
r.insert() r.insert()
except frappe.DoesNotExistError, e: except frappe.DoesNotExistError, e:
pass pass


+ 10
- 10
frappe/core/doctype/file_data/file_data.py Visa fil

@@ -22,20 +22,20 @@ class FileData(Document):
where file_name=%s where file_name=%s
and name!=%s and name!=%s
and attached_to_doctype=%s and attached_to_doctype=%s
and attached_to_name=%s""", (self.doc.file_name, self.doc.name, self.doc.attached_to_doctype,
self.doc.attached_to_name))
and attached_to_name=%s""", (self.file_name, self.name, self.attached_to_doctype,
self.attached_to_name))
if len(n_records) > 0: if len(n_records) > 0:
self.doc.duplicate_entry = n_records[0][0]
self.duplicate_entry = n_records[0][0]
frappe.msgprint(frappe._("Same file has already been attached to the record")) frappe.msgprint(frappe._("Same file has already been attached to the record"))
frappe.db.rollback() frappe.db.rollback()
raise frappe.DuplicateEntryError raise frappe.DuplicateEntryError


def on_trash(self): def on_trash(self):
if self.doc.attached_to_name:
if self.attached_to_name:
# check persmission # check persmission
try: try:
if not self.bean.ignore_permissions and \ if not self.bean.ignore_permissions and \
not frappe.has_permission(self.doc.attached_to_doctype, "write", self.doc.attached_to_name):
not frappe.has_permission(self.attached_to_doctype, "write", self.attached_to_name):
frappe.msgprint(frappe._("No permission to write / remove."), raise_exception=True) frappe.msgprint(frappe._("No permission to write / remove."), raise_exception=True)
@@ -43,12 +43,12 @@ class FileData(Document):
pass pass


# if file not attached to any other record, delete it # if file not attached to any other record, delete it
if self.doc.file_name and not frappe.db.count("File Data",
{"file_name": self.doc.file_name, "name": ["!=", self.doc.name]}):
if self.doc.file_name.startswith("files/"):
path = frappe.utils.get_site_path("public", self.doc.file_name)
if self.file_name and not frappe.db.count("File Data",
{"file_name": self.file_name, "name": ["!=", self.name]}):
if self.file_name.startswith("files/"):
path = frappe.utils.get_site_path("public", self.file_name)
else: else:
path = frappe.utils.get_site_path("public", "files", self.doc.file_name)
path = frappe.utils.get_site_path("public", "files", self.file_name)
if os.path.exists(path): if os.path.exists(path):
os.remove(path) os.remove(path)




+ 6
- 6
frappe/core/doctype/letter_head/letter_head.py Visa fil

@@ -17,13 +17,13 @@ class LetterHead(Document):
def set_as_default(self): def set_as_default(self):
from frappe.utils import set_default from frappe.utils import set_default
if not self.doc.is_default:
if not self.is_default:
if not frappe.db.sql("""select count(*) from `tabLetter Head` where ifnull(is_default,0)=1"""): if not frappe.db.sql("""select count(*) from `tabLetter Head` where ifnull(is_default,0)=1"""):
self.doc.is_default = 1
if self.doc.is_default:
self.is_default = 1
if self.is_default:
frappe.db.sql("update `tabLetter Head` set is_default=0 where name != %s", frappe.db.sql("update `tabLetter Head` set is_default=0 where name != %s",
self.doc.name)
set_default('letter_head', self.doc.name)
self.name)
set_default('letter_head', self.name)


# update control panel - so it loads new letter directly # update control panel - so it loads new letter directly
frappe.db.set_value('Control Panel', None, 'letter_head', self.doc.content)
frappe.db.set_value('Control Panel', None, 'letter_head', self.content)

+ 1
- 1
frappe/core/doctype/notification_count/notification_count.py Visa fil

@@ -61,7 +61,7 @@ def clear_doctype_notifications(bean, method=None):
return return
config = get_notification_config() config = get_notification_config()
doctype = bean.doc.doctype
doctype = bean.doctype


if doctype in config.for_doctype: if doctype in config.for_doctype:
delete_notification_count_for(doctype) delete_notification_count_for(doctype)


+ 7
- 7
frappe/core/doctype/outgoing_email_settings/outgoing_email_settings.py Visa fil

@@ -11,15 +11,15 @@ from frappe.model.document import Document
class OutgoingEmailSettings(Document): class OutgoingEmailSettings(Document):
def validate(self): def validate(self):
self.doc.encode()
if self.doc.mail_server:
self.encode()
if self.mail_server:
from frappe.utils import cint from frappe.utils import cint
from frappe.utils.email_lib.smtp import SMTPServer from frappe.utils.email_lib.smtp import SMTPServer
smtpserver = SMTPServer(login = self.doc.mail_login,
password = self.doc.mail_password,
server = self.doc.mail_server,
port = cint(self.doc.mail_port),
use_ssl = self.doc.use_ssl
smtpserver = SMTPServer(login = self.mail_login,
password = self.mail_password,
server = self.mail_server,
port = cint(self.mail_port),
use_ssl = self.use_ssl
) )
# exceptions are handled in session connect # exceptions are handled in session connect

+ 10
- 10
frappe/core/doctype/print_format/print_format.py Visa fil

@@ -15,31 +15,31 @@ class PrintFormat(Document):
self.doc, self.doclist = d,dl self.doc, self.doclist = d,dl


def validate(self): def validate(self):
if self.doc.standard=="Yes" and frappe.session.user != "Administrator":
if self.standard=="Yes" and frappe.session.user != "Administrator":
frappe.msgprint("Standard Print Format cannot be updated.", raise_exception=1) frappe.msgprint("Standard Print Format cannot be updated.", raise_exception=1)
# old_doc_type is required for clearing item cache # old_doc_type is required for clearing item cache
self.old_doc_type = frappe.db.get_value('Print Format', self.old_doc_type = frappe.db.get_value('Print Format',
self.doc.name, 'doc_type')
self.name, 'doc_type')


def on_update(self): def on_update(self):
if hasattr(self, 'old_doc_type') and self.old_doc_type: if hasattr(self, 'old_doc_type') and self.old_doc_type:
frappe.clear_cache(doctype=self.old_doc_type) frappe.clear_cache(doctype=self.old_doc_type)
if self.doc.doc_type:
frappe.clear_cache(doctype=self.doc.doc_type)
if self.doc_type:
frappe.clear_cache(doctype=self.doc_type)


self.export_doc() self.export_doc()
def export_doc(self): def export_doc(self):
# export # export
if self.doc.standard == 'Yes' and (frappe.conf.get('developer_mode') or 0) == 1:
if self.standard == 'Yes' and (frappe.conf.get('developer_mode') or 0) == 1:
from frappe.modules.export_file import export_to_files from frappe.modules.export_file import export_to_files
export_to_files(record_list=[['Print Format', self.doc.name]],
record_module=self.doc.module)
export_to_files(record_list=[['Print Format', self.name]],
record_module=self.module)
def on_trash(self): def on_trash(self):
if self.doc.doc_type:
frappe.clear_cache(doctype=self.doc.doc_type)
if self.doc_type:
frappe.clear_cache(doctype=self.doc_type)


def get_args(): def get_args():
if not frappe.form_dict.format: if not frappe.form_dict.format:
@@ -53,7 +53,7 @@ def get_args():
bean = frappe.bean(frappe.form_dict.doctype, frappe.form_dict.name) bean = frappe.bean(frappe.form_dict.doctype, frappe.form_dict.name)
for ptype in ("read", "print"): for ptype in ("read", "print"):
if not frappe.has_permission(bean.doc.doctype, ptype, bean.doc):
if not frappe.has_permission(bean.doctype, ptype, bean.doc):
return { return {
"body": """<h1>Error</h1> "body": """<h1>Error</h1>
<p>No {ptype} permission</p>""".format(ptype=ptype) <p>No {ptype} permission</p>""".format(ptype=ptype)


+ 11
- 11
frappe/core/doctype/property_setter/property_setter.py Visa fil

@@ -9,21 +9,21 @@ from frappe.model.document import Document
class PropertySetter(Document): class PropertySetter(Document):


def autoname(self): def autoname(self):
self.doc.name = self.doc.doc_type + "-" \
+ (self.doc.field_name and (self.doc.field_name + "-") or "") \
+ self.doc.property
self.name = self.doc_type + "-" \
+ (self.field_name and (self.field_name + "-") or "") \
+ self.property


def validate(self): def validate(self):
"""delete other property setters on this, if this is new""" """delete other property setters on this, if this is new"""
if self.doc.fields['__islocal']:
if self.fields['__islocal']:
frappe.db.sql("""delete from `tabProperty Setter` where frappe.db.sql("""delete from `tabProperty Setter` where
doctype_or_field = %(doctype_or_field)s doctype_or_field = %(doctype_or_field)s
and doc_type = %(doc_type)s and doc_type = %(doc_type)s
and ifnull(field_name,'') = ifnull(%(field_name)s, '') and ifnull(field_name,'') = ifnull(%(field_name)s, '')
and property = %(property)s""", self.doc.fields)
and property = %(property)s""", self.fields)
# clear cache # clear cache
frappe.clear_cache(doctype = self.doc.doc_type)
frappe.clear_cache(doctype = self.doc_type)
def get_property_list(self, dt): def get_property_list(self, dt):
return frappe.db.sql("""select fieldname, label, fieldtype return frappe.db.sql("""select fieldname, label, fieldtype
@@ -41,18 +41,18 @@ class PropertySetter(Document):
} }
def get_field_ids(self): def get_field_ids(self):
return frappe.db.sql("select name, fieldtype, label, fieldname from tabDocField where parent=%s", self.doc.doc_type, as_dict = 1)
return frappe.db.sql("select name, fieldtype, label, fieldname from tabDocField where parent=%s", self.doc_type, as_dict = 1)
def get_defaults(self): def get_defaults(self):
if not self.doc.field_name:
return frappe.db.sql("select * from `tabDocType` where name=%s", self.doc.doc_type, as_dict = 1)[0]
if not self.field_name:
return frappe.db.sql("select * from `tabDocType` where name=%s", self.doc_type, as_dict = 1)[0]
else: else:
return frappe.db.sql("select * from `tabDocField` where fieldname=%s and parent=%s", return frappe.db.sql("select * from `tabDocField` where fieldname=%s and parent=%s",
(self.doc.field_name, self.doc.doc_type), as_dict = 1)[0]
(self.field_name, self.doc_type), as_dict = 1)[0]
def on_update(self): def on_update(self):
from frappe.core.doctype.doctype.doctype import validate_fields_for_doctype from frappe.core.doctype.doctype.doctype import validate_fields_for_doctype
validate_fields_for_doctype(self.doc.doc_type)
validate_fields_for_doctype(self.doc_type)
def make_property_setter(doctype, fieldname, property, value, property_type, for_doctype = False): def make_property_setter(doctype, fieldname, property, value, property_type, for_doctype = False):
return frappe.bean({ return frappe.bean({


+ 10
- 10
frappe/core/doctype/report/report.py Visa fil

@@ -13,19 +13,19 @@ class Report(Document):
def validate(self): def validate(self):
"""only administrator can save standard report""" """only administrator can save standard report"""
if not self.doc.module:
self.doc.module = frappe.db.get_value("DocType", self.doc.ref_doctype, "module")
if not self.module:
self.module = frappe.db.get_value("DocType", self.ref_doctype, "module")
if not self.doc.is_standard:
self.doc.is_standard = "No"
if not self.is_standard:
self.is_standard = "No"
if frappe.session.user=="Administrator" and getattr(conf, 'developer_mode',0)==1: if frappe.session.user=="Administrator" and getattr(conf, 'developer_mode',0)==1:
self.doc.is_standard = "Yes"
self.is_standard = "Yes"


if self.doc.is_standard == "Yes" and frappe.session.user!="Administrator":
if self.is_standard == "Yes" and frappe.session.user!="Administrator":
frappe.msgprint(_("Only Administrator can save a standard report. Please rename and save."), frappe.msgprint(_("Only Administrator can save a standard report. Please rename and save."),
raise_exception=True) raise_exception=True)


if self.doc.report_type in ("Query Report", "Script Report") \
if self.report_type in ("Query Report", "Script Report") \
and frappe.session.user!="Administrator": and frappe.session.user!="Administrator":
frappe.msgprint(_("Only Administrator allowed to create Query / Script Reports"), frappe.msgprint(_("Only Administrator allowed to create Query / Script Reports"),
raise_exception=True) raise_exception=True)
@@ -35,6 +35,6 @@ class Report(Document):
def export_doc(self): def export_doc(self):
from frappe.modules.export_file import export_to_files from frappe.modules.export_file import export_to_files
if self.doc.is_standard == 'Yes' and (conf.get('developer_mode') or 0) == 1:
export_to_files(record_list=[['Report', self.doc.name]],
record_module=self.doc.module)
if self.is_standard == 'Yes' and (conf.get('developer_mode') or 0) == 1:
export_to_files(record_list=[['Report', self.name]],
record_module=self.module)

+ 9
- 9
frappe/core/doctype/todo/todo.py Visa fil

@@ -9,27 +9,27 @@ from frappe.model.document import Document
class Todo(Document): class Todo(Document):
def validate(self): def validate(self):
if self.doc.is_new():
if self.is_new():
self.add_comment(frappe._("Assignment Added")) self.add_comment(frappe._("Assignment Added"))
else: else:
cur_status = frappe.db.get_value("ToDo", self.doc.name, "status")
if cur_status != self.doc.status:
cur_status = frappe.db.get_value("ToDo", self.name, "status")
if cur_status != self.status:
self.add_comment(frappe._("Assignment Status Changed")) self.add_comment(frappe._("Assignment Status Changed"))
def add_comment(self, text): def add_comment(self, text):
if not self.doc.reference_type and self.doc.reference_name:
if not self.reference_type and self.reference_name:
return return
comment = frappe.bean({ comment = frappe.bean({
"doctype":"Comment", "doctype":"Comment",
"comment_by": frappe.session.user, "comment_by": frappe.session.user,
"comment_doctype": self.doc.reference_type,
"comment_docname": self.doc.reference_name,
"comment_doctype": self.reference_type,
"comment_docname": self.reference_name,
"comment": """<div>{text}: "comment": """<div>{text}:
<a href='#Form/ToDo/{name}'>{status}: {description}</a></div>""".format(text=text, <a href='#Form/ToDo/{name}'>{status}: {description}</a></div>""".format(text=text,
status = frappe._(self.doc.status),
name = self.doc.name,
description = self.doc.description)
status = frappe._(self.status),
name = self.name,
description = self.description)
}).insert(ignore_permissions=True) }).insert(ignore_permissions=True)


+ 1
- 1
frappe/core/doctype/user/test_user.py Visa fil

@@ -12,7 +12,7 @@ class TestUser(unittest.TestCase):
delete_doc("Role","_Test Role 2") delete_doc("Role","_Test Role 2")
user = frappe.bean(copy=test_records[1]) user = frappe.bean(copy=test_records[1])
user.doc.email = "_test@example.com"
user.email = "_test@example.com"
user.insert() user.insert()
frappe.bean({"doctype": "ToDo", "description": "_Test"}).insert() frappe.bean({"doctype": "ToDo", "description": "_Test"}).insert()


+ 43
- 43
frappe/core/doctype/user/user.py Visa fil

@@ -15,43 +15,43 @@ class User(Document):
def autoname(self): def autoname(self):
"""set name as email id""" """set name as email id"""
if self.doc.name not in STANDARD_USERS:
self.doc.email = self.doc.email.strip()
self.doc.name = self.doc.email
if self.name not in STANDARD_USERS:
self.email = self.email.strip()
self.name = self.email
if frappe.db.exists("User", self.doc.name):
if frappe.db.exists("User", self.name):
throw(_("Name Exists")) throw(_("Name Exists"))


def validate(self): def validate(self):
self.in_insert = self.doc.fields.get("__islocal")
if self.doc.name not in STANDARD_USERS:
self.validate_email_type(self.doc.email)
self.in_insert = self.get("__islocal")
if self.name not in STANDARD_USERS:
self.validate_email_type(self.email)
self.add_system_manager_role() self.add_system_manager_role()
self.check_enable_disable() self.check_enable_disable()
self.update_gravatar() self.update_gravatar()


def check_enable_disable(self): def check_enable_disable(self):
# do not allow disabling administrator/guest # do not allow disabling administrator/guest
if not cint(self.doc.enabled) and self.doc.name in STANDARD_USERS:
if not cint(self.enabled) and self.name in STANDARD_USERS:
throw("{msg}: {name}".format(**{ throw("{msg}: {name}".format(**{
"msg": _("Hey! You cannot disable user"), "msg": _("Hey! You cannot disable user"),
"name": self.doc.name
"name": self.name
})) }))


if not cint(self.doc.enabled):
if not cint(self.enabled):
self.a_system_manager_should_exist() self.a_system_manager_should_exist()
# clear sessions if disabled # clear sessions if disabled
if not cint(self.doc.enabled) and getattr(frappe, "login_manager", None):
frappe.local.login_manager.logout(user=self.doc.name)
if not cint(self.enabled) and getattr(frappe, "login_manager", None):
frappe.local.login_manager.logout(user=self.name)
def add_system_manager_role(self): def add_system_manager_role(self):
# if adding system manager, do nothing # if adding system manager, do nothing
if not cint(self.doc.enabled) or ("System Manager" in [user_role.role for user_role in
if not cint(self.enabled) or ("System Manager" in [user_role.role for user_role in
self.get("user_roles")]): self.get("user_roles")]):
return return
if self.doc.user_type == "System User" and not self.get_other_system_managers():
if self.user_type == "System User" and not self.get_other_system_managers():
msgprint("""Adding System Manager Role as there must msgprint("""Adding System Manager Role as there must
be atleast one 'System Manager'.""") be atleast one 'System Manager'.""")
self.append("user_roles", { self.append("user_roles", {
@@ -61,27 +61,27 @@ class User(Document):
def email_new_password(self, new_password=None): def email_new_password(self, new_password=None):
if new_password and not self.in_insert: if new_password and not self.in_insert:
_update_password(self.doc.name, new_password)
_update_password(self.name, new_password)


self.password_update_mail(new_password) self.password_update_mail(new_password)
frappe.msgprint("New Password Emailed.") frappe.msgprint("New Password Emailed.")
def on_update(self): def on_update(self):
# owner is always name # owner is always name
frappe.db.set(self.doc, 'owner', self.doc.name)
frappe.db.set(self.doc, 'owner', self.name)
# clear new password # clear new password
new_password = self.doc.new_password
self.doc.set("new_password", "")
new_password = self.new_password
self.set("new_password", "")
frappe.clear_cache(user=self.doc.name)
frappe.clear_cache(user=self.name)
try: try:
if self.in_insert: if self.in_insert:
if self.doc.name not in STANDARD_USERS:
if self.name not in STANDARD_USERS:
if new_password: if new_password:
# new password given, no email required # new password given, no email required
_update_password(self.doc.name, new_password)
_update_password(self.name, new_password)
if not getattr(self, "no_welcome_mail", False): if not getattr(self, "no_welcome_mail", False):
self.send_welcome_mail() self.send_welcome_mail()
msgprint(_("Welcome Email Sent")) msgprint(_("Welcome Email Sent"))
@@ -94,15 +94,15 @@ class User(Document):


def update_gravatar(self): def update_gravatar(self):
import md5 import md5
if not self.doc.user_image:
self.doc.user_image = "https://secure.gravatar.com/avatar/" + md5.md5(self.doc.name).hexdigest() \
if not self.user_image:
self.user_image = "https://secure.gravatar.com/avatar/" + md5.md5(self.name).hexdigest() \
+ "?d=retro" + "?d=retro"
def reset_password(self): def reset_password(self):
from frappe.utils import random_string, get_url from frappe.utils import random_string, get_url


key = random_string(32) key = random_string(32)
frappe.db.set_value("User", self.doc.name, "reset_password_key", key)
frappe.db.set_value("User", self.name, "reset_password_key", key)
self.password_reset_mail(get_url("/update-password?key=" + key)) self.password_reset_mail(get_url("/update-password?key=" + key))
def get_other_system_managers(self): def get_other_system_managers(self):
@@ -110,12 +110,12 @@ class User(Document):
where role='System Manager' and docstatus<2 where role='System Manager' and docstatus<2
and parent not in ('Administrator', %s) and exists and parent not in ('Administrator', %s) and exists
(select * from `tabUser` user (select * from `tabUser` user
where user.name=user_role.parent and enabled=1)""", (self.doc.name,))
where user.name=user_role.parent and enabled=1)""", (self.name,))


def get_fullname(self): def get_fullname(self):
"""get first_name space last_name""" """get first_name space last_name"""
return (self.doc.first_name or '') + \
(self.doc.first_name and " " or '') + (self.doc.last_name or '')
return (self.first_name or '') + \
(self.first_name and " " or '') + (self.last_name or '')


def password_reset_mail(self, link): def password_reset_mail(self, link):
self.send_login_mail("Password Reset", "templates/emails/password_reset.html", {"link": link}) self.send_login_mail("Password Reset", "templates/emails/password_reset.html", {"link": link})
@@ -126,8 +126,8 @@ class User(Document):
def send_welcome_mail(self): def send_welcome_mail(self):
from frappe.utils import random_string, get_url from frappe.utils import random_string, get_url


self.doc.reset_password_key = random_string(32)
link = get_url("/update-password?key=" + self.doc.reset_password_key)
self.reset_password_key = random_string(32)
link = get_url("/update-password?key=" + self.reset_password_key)


self.send_login_mail("Verify Your Account", "templates/emails/new_user.html", {"link": link}) self.send_login_mail("Verify Your Account", "templates/emails/new_user.html", {"link": link})
@@ -144,8 +144,8 @@ class User(Document):
full_name = "Administrator" full_name = "Administrator"
args = { args = {
'first_name': self.doc.first_name or self.doc.last_name or "user",
'user': self.doc.name,
'first_name': self.first_name or self.last_name or "user",
'user': self.name,
'title': title, 'title': title,
'login_url': get_url(), 'login_url': get_url(),
'user_fullname': full_name 'user_fullname': full_name
@@ -155,7 +155,7 @@ class User(Document):
sender = frappe.session.user not in STANDARD_USERS and frappe.session.user or None sender = frappe.session.user not in STANDARD_USERS and frappe.session.user or None
frappe.sendmail(recipients=self.doc.email, sender=sender, subject=subject,
frappe.sendmail(recipients=self.email, sender=sender, subject=subject,
message=frappe.get_template(template).render(args)) message=frappe.get_template(template).render(args))
def a_system_manager_should_exist(self): def a_system_manager_should_exist(self):
@@ -163,36 +163,36 @@ class User(Document):
throw(_("Hey! There should remain at least one System Manager")) throw(_("Hey! There should remain at least one System Manager"))
def on_trash(self): def on_trash(self):
frappe.clear_cache(user=self.doc.name)
if self.doc.name in STANDARD_USERS:
frappe.clear_cache(user=self.name)
if self.name in STANDARD_USERS:
throw("{msg}: {name}".format(**{ throw("{msg}: {name}".format(**{
"msg": _("Hey! You cannot delete user"), "msg": _("Hey! You cannot delete user"),
"name": self.doc.name
"name": self.name
})) }))
self.a_system_manager_should_exist() self.a_system_manager_should_exist()
# disable the user and log him/her out # disable the user and log him/her out
self.doc.enabled = 0
self.enabled = 0
if getattr(frappe.local, "login_manager", None): if getattr(frappe.local, "login_manager", None):
frappe.local.login_manager.logout(user=self.doc.name)
frappe.local.login_manager.logout(user=self.name)
# delete their password # delete their password
frappe.db.sql("""delete from __Auth where user=%s""", (self.doc.name,))
frappe.db.sql("""delete from __Auth where user=%s""", (self.name,))
# delete todos # delete todos
frappe.db.sql("""delete from `tabToDo` where owner=%s""", (self.doc.name,))
frappe.db.sql("""delete from `tabToDo` where owner=%s""", (self.name,))
frappe.db.sql("""update tabToDo set assigned_by=null where assigned_by=%s""", frappe.db.sql("""update tabToDo set assigned_by=null where assigned_by=%s""",
(self.doc.name,))
(self.name,))
# delete events # delete events
frappe.db.sql("""delete from `tabEvent` where owner=%s frappe.db.sql("""delete from `tabEvent` where owner=%s
and event_type='Private'""", (self.doc.name,))
frappe.db.sql("""delete from `tabEvent User` where person=%s""", (self.doc.name,))
and event_type='Private'""", (self.name,))
frappe.db.sql("""delete from `tabEvent User` where person=%s""", (self.name,))
# delete messages # delete messages
frappe.db.sql("""delete from `tabComment` where comment_doctype='Message' frappe.db.sql("""delete from `tabComment` where comment_doctype='Message'
and (comment_docname=%s or owner=%s)""", (self.doc.name, self.doc.name))
and (comment_docname=%s or owner=%s)""", (self.name, self.name))
def before_rename(self, olddn, newdn, merge=False): def before_rename(self, olddn, newdn, merge=False):
frappe.clear_cache(user=olddn) frappe.clear_cache(user=olddn)


+ 2
- 2
frappe/core/doctype/userrole/userrole.py Visa fil

@@ -10,7 +10,7 @@ from frappe.model.document import Document
class Userrole(Document): class Userrole(Document):
def validate(self): def validate(self):
if cint(self.doc.fields.get("__islocal")) and frappe.db.exists("UserRole", {
"parent": self.doc.parent, "role": self.doc.role}):
if cint(self.get("__islocal")) and frappe.db.exists("UserRole", {
"parent": self.parent, "role": self.role}):
frappe.msgprint("Role Already Exists", raise_exception=True) frappe.msgprint("Role Already Exists", raise_exception=True)

+ 13
- 13
frappe/core/doctype/workflow/workflow.py Visa fil

@@ -14,26 +14,26 @@ class Workflow(Document):
self.update_default_workflow_status() self.update_default_workflow_status()
def on_update(self): def on_update(self):
frappe.clear_cache(doctype=self.doc.document_type)
frappe.clear_cache(doctype=self.document_type)
def create_custom_field_for_workflow_state(self): def create_custom_field_for_workflow_state(self):
frappe.clear_cache(doctype=self.doc.document_type)
meta = frappe.get_meta(self.doc.document_type)
if not meta.get_field(self.doc.workflow_state_field):
frappe.clear_cache(doctype=self.document_type)
meta = frappe.get_meta(self.document_type)
if not meta.get_field(self.workflow_state_field):
# create custom field # create custom field
frappe.bean([{ frappe.bean([{
"doctype":"Custom Field", "doctype":"Custom Field",
"dt": self.doc.document_type,
"dt": self.document_type,
"__islocal": 1, "__islocal": 1,
"fieldname": self.doc.workflow_state_field,
"label": self.doc.workflow_state_field.replace("_", " ").title(),
"fieldname": self.workflow_state_field,
"label": self.workflow_state_field.replace("_", " ").title(),
"hidden": 1, "hidden": 1,
"fieldtype": "Link", "fieldtype": "Link",
"options": "Workflow State", "options": "Workflow State",
}]).save() }]).save()
frappe.msgprint("Created Custom Field '%s' in '%s'" % (self.doc.workflow_state_field,
self.doc.document_type))
frappe.msgprint("Created Custom Field '%s' in '%s'" % (self.workflow_state_field,
self.document_type))


def update_default_workflow_status(self): def update_default_workflow_status(self):
docstatus_map = {} docstatus_map = {}
@@ -42,13 +42,13 @@ class Workflow(Document):
for d in self.doclist.get({"doctype": "Workflow Document State"}): for d in self.doclist.get({"doctype": "Workflow Document State"}):
if not d.doc_status in docstatus_map: if not d.doc_status in docstatus_map:
frappe.db.sql("""update `tab%s` set `%s` = %s where \ frappe.db.sql("""update `tab%s` set `%s` = %s where \
ifnull(`%s`, '')='' and docstatus=%s""" % (self.doc.document_type, self.doc.workflow_state_field,
'%s', self.doc.workflow_state_field, "%s"), (d.state, d.doc_status))
ifnull(`%s`, '')='' and docstatus=%s""" % (self.document_type, self.workflow_state_field,
'%s', self.workflow_state_field, "%s"), (d.state, d.doc_status))
docstatus_map[d.doc_status] = d.state docstatus_map[d.doc_status] = d.state
def set_active(self): def set_active(self):
if int(self.doc.is_active or 0):
if int(self.is_active or 0):
# clear all other # clear all other
frappe.db.sql("""update tabWorkflow set is_active=0 frappe.db.sql("""update tabWorkflow set is_active=0
where document_type=%s""", where document_type=%s""",
self.doc.document_type)
self.document_type)

+ 5
- 5
frappe/core/page/data_import_tool/data_import_tool.py Visa fil

@@ -403,15 +403,15 @@ def upload(rows = None, submit_after_import=None, ignore_encoding_errors=False,
bean.ignore_links = ignore_links bean.ignore_links = ignore_links
bean.doclist.update(doclist) bean.doclist.update(doclist)
bean.save() bean.save()
ret.append('Updated row (#%d) %s' % (row_idx + 1, getlink(bean.doc.doctype, bean.doc.name)))
ret.append('Updated row (#%d) %s' % (row_idx + 1, getlink(bean.doctype, bean.name)))
else: else:
bean = frappe.bean(doclist) bean = frappe.bean(doclist)
bean.ignore_links = ignore_links bean.ignore_links = ignore_links
bean.insert() bean.insert()
ret.append('Inserted row (#%d) %s' % (row_idx + 1, getlink(bean.doc.doctype, bean.doc.name)))
ret.append('Inserted row (#%d) %s' % (row_idx + 1, getlink(bean.doctype, bean.name)))
if submit_after_import: if submit_after_import:
bean.submit() bean.submit()
ret.append('Submitted row (#%d) %s' % (row_idx + 1, getlink(bean.doc.doctype, bean.doc.name)))
ret.append('Submitted row (#%d) %s' % (row_idx + 1, getlink(bean.doctype, bean.name)))
else: else:
check_record(doclist[0], parenttype, doctype_dl) check_record(doclist[0], parenttype, doctype_dl)


@@ -532,7 +532,7 @@ def import_doclist(path, overwrite=False, ignore_links=False, ignore_insert=Fals
b = frappe.bean(d) b = frappe.bean(d)
b.ignore_links = ignore_links b.ignore_links = ignore_links
if insert: if insert:
b.doc.fields["__islocal"] = True
b.set("__islocal", True)
try: try:
b.insert_or_update() b.insert_or_update()
except NameError: except NameError:
@@ -540,7 +540,7 @@ def import_doclist(path, overwrite=False, ignore_links=False, ignore_insert=Fals
pass pass
else: else:
raise raise
print "Imported: " + b.doc.doctype + " / " + b.doc.name
print "Imported: " + b.doctype + " / " + b.name
for f in files: for f in files:
if f.endswith(".json"): if f.endswith(".json"):


+ 2
- 2
frappe/model/__init__.py Visa fil

@@ -17,7 +17,7 @@ def insert(doclist):
if isinstance(d, dict): if isinstance(d, dict):
d["__islocal"] = 1 d["__islocal"] = 1
else: else:
d.fields["__islocal"] = 1
d.set("__islocal", 1)
wrapper = frappe.bean(doclist) wrapper = frappe.bean(doclist)
wrapper.save() wrapper.save()
@@ -40,7 +40,7 @@ def copytables(srctype, src, srcfield, tartype, tar, tarfield, srcfields, tarfie
newrow.idx = d.idx newrow.idx = d.idx
for i in range(len(srcfields)): for i in range(len(srcfields)):
newrow.fields[tarfields[i]] = d.fields[srcfields[i]]
newrow.set(tarfields[i], d.fields[srcfields[i]])
l.append(newrow) l.append(newrow)
return l return l


+ 6
- 1
frappe/model/base_document.py Visa fil

@@ -33,7 +33,12 @@ class BaseDocument(object):
def get(self, key=None, filters=None, limit=None, default=None): def get(self, key=None, filters=None, limit=None, default=None):
if key: if key:
if filters: if filters:
value = _filter(self.__dict__.get(key), filters, limit=limit)
if isinstance(filters, dict):
value = _filter(self.__dict__.get(key), filters, limit=limit)
else:
default = filters
filters = None
value = self.__dict__.get(key, default)
else: else:
value = self.__dict__.get(key, default) value = self.__dict__.get(key, default)


+ 4
- 4
frappe/model/code.py Visa fil

@@ -12,7 +12,7 @@ methods in following modules are imported for backward compatibility


* frappe.* * frappe.*
* frappe.utils.* * frappe.utils.*
* frappe.model.doc.*
* frappe.model.*
* frappe.model.bean.* * frappe.model.bean.*
""" """


@@ -26,14 +26,14 @@ def get_obj(dt = None, dn = None, doc=None, doclist=None, with_children = 0):
if dt: if dt:
if isinstance(dt, list): if isinstance(dt, list):
return get_server_obj(dt[0], dt) return get_server_obj(dt[0], dt)
if isinstance(dt, frappe.model.doc.Document):
if isinstance(dt, frappe.model.Document):
return get_server_obj(dt, [dt]) return get_server_obj(dt, [dt])
if not dn: if not dn:
dn = dt dn = dt
if with_children: if with_children:
doclist = frappe.model.doc.get(dt, dn, from_controller=1)
doclist = frappe.model.get(dt, dn, from_controller=1)
else: else:
doclist = frappe.model.doc.get(dt, dn, with_children = 0, from_controller=1)
doclist = frappe.model.get(dt, dn, with_children = 0, from_controller=1)
return get_server_obj(doclist[0], doclist) return get_server_obj(doclist[0], doclist)
else: else:
return get_server_obj(doc, doclist) return get_server_obj(doc, doclist)


+ 2
- 2
frappe/model/controller.py Visa fil

@@ -31,7 +31,7 @@ class DocListController(Document):
df = self.meta.get_field(fieldname, parent=doc.doctype) df = self.meta.get_field(fieldname, parent=doc.doctype)
val1 = doc.fields.get(fieldname)
val1 = doc.get(fieldname)
if df.fieldtype in ("Currency", "Float"): if df.fieldtype in ("Currency", "Float"):
val1 = flt(val1, self.precision(df.fieldname, doc.parentfield or None)) val1 = flt(val1, self.precision(df.fieldname, doc.parentfield or None))
@@ -67,7 +67,7 @@ class DocListController(Document):
"fieldtype": ["in", ["Currency", "Float"]]})] "fieldtype": ["in", ["Currency", "Float"]]})]
for fieldname in fieldnames: for fieldname in fieldnames:
doc.fields[fieldname] = flt(doc.fields.get(fieldname), self.precision(fieldname, doc.parentfield))
doc.set(fieldname, flt(doc.get(fieldname), self.precision(fieldname, doc.parentfield)))
def precision(self, fieldname, parentfield=None): def precision(self, fieldname, parentfield=None):
if not isinstance(parentfield, basestring): if not isinstance(parentfield, basestring):


+ 10
- 10
frappe/model/create_new.py Visa fil

@@ -36,14 +36,14 @@ def get_new_doc(doctype, parent_doc = None, parentfield = None):
if (d.fieldtype=="Link") and d.ignore_restrictions != 1 and (d.options in restrictions)\ if (d.fieldtype=="Link") and d.ignore_restrictions != 1 and (d.options in restrictions)\
and len(restrictions[d.options])==1: and len(restrictions[d.options])==1:
doc.fields[d.fieldname] = restrictions[d.options][0]
doc.set(d.fieldname, restrictions[d.options][0])
elif default: elif default:
doc.fields[d.fieldname] = default
elif d.fields.get("default"):
doc.set(d.fieldname, default)
elif d.get("default"):
if d.default == "__user": if d.default == "__user":
doc.fields[d.fieldname] = frappe.session.user
doc.set(d.fieldname, frappe.session.user)
elif d.default == "Today": elif d.default == "Today":
doc.fields[d.fieldname] = nowdate()
doc.set(d.fieldname, nowdate())


elif d.default.startswith(":"): elif d.default.startswith(":"):
ref_fieldname = d.default[1:].lower().replace(" ", "_") ref_fieldname = d.default[1:].lower().replace(" ", "_")
@@ -51,19 +51,19 @@ def get_new_doc(doctype, parent_doc = None, parentfield = None):
ref_docname = parent_doc.fields[ref_fieldname] ref_docname = parent_doc.fields[ref_fieldname]
else: else:
ref_docname = frappe.db.get_default(ref_fieldname) ref_docname = frappe.db.get_default(ref_fieldname)
doc.fields[d.fieldname] = frappe.db.get_value(d.default[1:],
doc.set(d.fieldname, frappe.db.get_value(d.default[1:], )
ref_docname, d.fieldname) ref_docname, d.fieldname)


else: else:
doc.fields[d.fieldname] = d.default
doc.set(d.fieldname, d.default)
# convert type of default # convert type of default
if d.fieldtype in ("Int", "Check"): if d.fieldtype in ("Int", "Check"):
doc.fields[d.fieldname] = cint(doc.fields[d.fieldname])
doc.set(d.fieldname, cint(doc.fields[d.fieldname]))
elif d.fieldtype in ("Float", "Currency"): elif d.fieldtype in ("Float", "Currency"):
doc.fields[d.fieldname] = flt(doc.fields[d.fieldname])
doc.set(d.fieldname, flt(doc.fields[d.fieldname]))
elif d.fieldtype == "Time": elif d.fieldtype == "Time":
doc.fields[d.fieldname] = nowtime()
doc.set(d.fieldname, nowtime())
return doc return doc

+ 8
- 8
frappe/model/mapper.py Visa fil

@@ -32,7 +32,7 @@ def get_mapped_doclist(from_doctype, from_docname, table_maps, target_doclist=No
else: else:
target_doc = frappe.new_doc(table_maps[from_doctype]["doctype"]) target_doc = frappe.new_doc(table_maps[from_doctype]["doctype"])
map_doc(source.doc, target_doc, table_maps[source.doc.doctype], source_meta, target_meta)
map_doc(source.doc, target_doc, table_maps[source.doctype], source_meta, target_meta)
if target_doclist: if target_doclist:
target_doclist[0] = target_doc target_doclist[0] = target_doc
else: else:
@@ -91,7 +91,7 @@ def map_doc(source_doc, target_doc, table_map, source_meta, target_meta, source_
if table_map.get("validation"): if table_map.get("validation"):
for key, condition in table_map["validation"].items(): for key, condition in table_map["validation"].items():
if condition[0]=="=": if condition[0]=="=":
if source_doc.fields.get(key) != condition[1]:
if source_doc.get(key) != condition[1]:
frappe.msgprint(_("Cannot map because following condition fails: ") frappe.msgprint(_("Cannot map because following condition fails: ")
+ key + "=" + cstr(condition[1]), raise_exception=frappe.ValidationError) + key + "=" + cstr(condition[1]), raise_exception=frappe.ValidationError)


@@ -99,9 +99,9 @@ def map_doc(source_doc, target_doc, table_map, source_meta, target_meta, source_
target_fields = target_meta.get({"doctype": "DocField", "parent": target_doc.doctype}) target_fields = target_meta.get({"doctype": "DocField", "parent": target_doc.doctype})
for key in [d.fieldname for d in target_fields]: for key in [d.fieldname for d in target_fields]:
if key not in no_copy_fields: if key not in no_copy_fields:
val = source_doc.fields.get(key)
val = source_doc.get(key)
if val not in (None, ""): if val not in (None, ""):
target_doc.fields[key] = val
target_doc.set(key, val)


# map other fields # map other fields
@@ -110,14 +110,14 @@ def map_doc(source_doc, target_doc, table_map, source_meta, target_meta, source_
if field_map: if field_map:
if isinstance(field_map, dict): if isinstance(field_map, dict):
for source_key, target_key in field_map.items(): for source_key, target_key in field_map.items():
val = source_doc.fields.get(source_key)
val = source_doc.get(source_key)
if val not in (None, ""): if val not in (None, ""):
target_doc.fields[target_key] = val
target_doc.set(target_key, val)
else: else:
for fmap in field_map: for fmap in field_map:
val = source_doc.fields.get(fmap[0])
val = source_doc.get(fmap[0])
if val not in (None, ""): if val not in (None, ""):
target_doc.fields[fmap[1]] = val
target_doc.set(fmap[1], val)


# map idx # map idx
if source_doc.idx: if source_doc.idx:


+ 4
- 4
frappe/model/meta.py Visa fil

@@ -165,8 +165,8 @@ def get_link_fields(doctype):
""" """
import frappe.model.doctype import frappe.model.doctype
doclist = frappe.model.doctype.get(doctype) doclist = frappe.model.doctype.get(doctype)
return [(d.fields.get('fieldname'), d.fields.get('options'), d.fields.get('label'))
for d in doclist.get_link_fields() if d.fields.get('fieldname')!='owner']
return [(d.get('fieldname'), d.get('options'), d.get('label'))
for d in doclist.get_link_fields() if d.get('fieldname')!='owner']


def get_table_fields(doctype): def get_table_fields(doctype):
child_tables = [[d[0], d[1]] for d in frappe.db.sql("""select options, fieldname child_tables = [[d[0], d[1]] for d in frappe.db.sql("""select options, fieldname
@@ -192,10 +192,10 @@ def get_field_currency(df, doc):
if ":" in cstr(df.options): if ":" in cstr(df.options):
split_opts = df.options.split(":") split_opts = df.options.split(":")
if len(split_opts)==3: if len(split_opts)==3:
currency = frappe.db.get_value(split_opts[0], doc.fields.get(split_opts[1]),
currency = frappe.db.get_value(split_opts[0], doc.get(split_opts[1]),
split_opts[2]) split_opts[2])
else: else:
currency = doc.fields.get(df.options)
currency = doc.get(df.options)


return currency return currency


+ 1
- 1
frappe/model/utils.py Visa fil

@@ -14,4 +14,4 @@ def set_default(doc, key):
frappe.db.sql("""update `tab%s` set `is_default`=0 frappe.db.sql("""update `tab%s` set `is_default`=0
where `%s`=%s and name!=%s""" % (doc.doctype, key, "%s", "%s"), where `%s`=%s and name!=%s""" % (doc.doctype, key, "%s", "%s"),
(doc.fields.get(key), doc.name))
(doc.get(key), doc.name))

+ 1
- 1
frappe/modules/__init__.py Visa fil

@@ -40,7 +40,7 @@ def export_doc(doctype, name, module=None):
import frappe.model.doc import frappe.model.doc


if not module: module = frappe.db.get_value(doctype, name, 'module') if not module: module = frappe.db.get_value(doctype, name, 'module')
write_document_file(frappe.model.doc.get(doctype, name), module)
write_document_file(frappe.model.get(doctype, name), module)


def get_doctype_module(doctype): def get_doctype_module(doctype):
return frappe.db.get_value('DocType', doctype, 'module') or "core" return frappe.db.get_value('DocType', doctype, 'module') or "core"


+ 11
- 11
frappe/templates/generators/web_page.py Visa fil

@@ -11,22 +11,22 @@ condition_field = "published"
def get_context(context): def get_context(context):
web_page = context.bean web_page = context.bean
if web_page.doc.slideshow:
web_page.doc.fields.update(get_slideshow(web_page))
if web_page.slideshow:
web_page.update(get_slideshow(web_page))
web_page.doc.meta_description = web_page.doc.description
web_page.meta_description = web_page.description
if web_page.doc.enable_comments:
web_page.doc.comment_list = frappe.db.sql("""select
if web_page.enable_comments:
web_page.comment_list = frappe.db.sql("""select
comment, comment_by_fullname, creation comment, comment_by_fullname, creation
from `tabComment` where comment_doctype="Web Page" from `tabComment` where comment_doctype="Web Page"
and comment_docname=%s order by creation""", web_page.doc.name, as_dict=1) or []
and comment_docname=%s order by creation""", web_page.name, as_dict=1) or []
web_page.doc.fields.update({
"style": web_page.doc.css or "",
"script": web_page.doc.javascript or ""
web_page.update({
"style": web_page.css or "",
"script": web_page.javascript or ""
}) })
web_page.doc.fields.update(context)
web_page.update(context)
return web_page.doc.fields
return web_page.fields

+ 5
- 5
frappe/templates/generators/website_group.py Visa fil

@@ -34,7 +34,7 @@ def get_context(context):
def get_group_context(group, view, context): def get_group_context(group, view, context):
cache_key = "website_group_context:{}:{}".format(group, view) cache_key = "website_group_context:{}:{}".format(group, view)


views = get_views(context.bean.doc.group_type)
views = get_views(context.bean.group_type)
view = frappe._dict(views.get(view)) view = frappe._dict(views.get(view))
if can_cache(view.no_cache): if can_cache(view.no_cache):
@@ -50,10 +50,10 @@ def get_group_context(group, view, context):
return group_context return group_context
def build_group_context(group, view, views, context): def build_group_context(group, view, views, context):
title = "{} - {}".format(context.bean.doc.group_title, view.get("label"))
title = "{} - {}".format(context.bean.group_title, view.get("label"))
group_context = frappe._dict({ group_context = frappe._dict({
"group": context.bean.doc.fields,
"group": context.bean.fields,
"view": view, "view": view,
"views": [v[1] for v in sorted(views.iteritems(), key=lambda (k, v): v.get("idx"))], "views": [v[1] for v in sorted(views.iteritems(), key=lambda (k, v): v.get("idx"))],
"title": title, "title": title,
@@ -87,7 +87,7 @@ def build_view_context(context):
def guess_group_view(context): def guess_group_view(context):
group = context.docname group = context.docname
view = frappe.form_dict.view or get_default_view(context.bean.doc.group_type)
view = frappe.form_dict.view or get_default_view(context.bean.group_type)
return group, view return group, view
def get_default_view(group_type): def get_default_view(group_type):
@@ -139,7 +139,7 @@ def clear_event_cache():
clear_unit_views(website_group=group) clear_unit_views(website_group=group)
def clear_cache_on_bean_event(bean, method, *args, **kwargs): def clear_cache_on_bean_event(bean, method, *args, **kwargs):
clear_cache(path=bean.doc.website_route, website_group=bean.doc.website_group)
clear_cache(path=bean.website_route, website_group=bean.website_group)
def get_pathname(group): def get_pathname(group):
return frappe.db.get_value("Website Route", {"ref_doctype": "Website Group", return frappe.db.get_value("Website Route", {"ref_doctype": "Website Group",


+ 6
- 6
frappe/templates/includes/comments.py Visa fil

@@ -40,9 +40,9 @@ def add_comment(args=None):
# notify commentors # notify commentors
commentors = [d[0] for d in frappe.db.sql("""select comment_by from tabComment where commentors = [d[0] for d in frappe.db.sql("""select comment_by from tabComment where
comment_doctype=%s and comment_docname=%s and comment_doctype=%s and comment_docname=%s and
ifnull(unsubscribed, 0)=0""", (comment.doc.comment_doctype, comment.doc.comment_docname))]
ifnull(unsubscribed, 0)=0""", (comment.comment_doctype, comment.comment_docname))]
owner = frappe.db.get_value(comment.doc.comment_doctype, comment.doc.comment_docname, "owner")
owner = frappe.db.get_value(comment.comment_doctype, comment.comment_docname, "owner")
recipients = commentors if owner=="Administrator" else list(set(commentors + [owner])) recipients = commentors if owner=="Administrator" else list(set(commentors + [owner]))
@@ -50,12 +50,12 @@ def add_comment(args=None):
send(recipients=recipients, send(recipients=recipients,
doctype='Comment', doctype='Comment',
email_field='comment_by', email_field='comment_by',
subject='New Comment on %s: %s' % (comment.doc.comment_doctype,
comment.doc.title or comment.doc.comment_docname),
subject='New Comment on %s: %s' % (comment.comment_doctype,
comment.title or comment.comment_docname),
message='%(comment)s<p>By %(comment_by_fullname)s</p>' % args, message='%(comment)s<p>By %(comment_by_fullname)s</p>' % args,
ref_doctype=comment.doc.comment_doctype, ref_docname=comment.doc.comment_docname)
ref_doctype=comment.comment_doctype, ref_docname=comment.comment_docname)
template = frappe.get_template("templates/includes/comment.html") template = frappe.get_template("templates/includes/comment.html")
return template.render({"comment": comment.doc.fields})
return template.render({"comment": comment.fields})

+ 4
- 4
frappe/templates/pages/contact.py Visa fil

@@ -9,15 +9,15 @@ from frappe.utils import now
def get_context(context): def get_context(context):
bean = frappe.bean("Contact Us Settings", "Contact Us Settings") bean = frappe.bean("Contact Us Settings", "Contact Us Settings")
query_options = filter(None, bean.doc.query_options.replace(",", "\n").split()) if \
bean.doc.query_options else ["Sales", "Support", "General"]
query_options = filter(None, bean.query_options.replace(",", "\n").split()) if \
bean.query_options else ["Sales", "Support", "General"]
address = frappe.bean("Address", bean.doc.address).doc if bean.doc.address else None
address = frappe.bean("Address", bean.address).doc if bean.address else None
out = { out = {
"query_options": query_options "query_options": query_options
} }
out.update(bean.doc.fields)
out.update(bean.fields)
return out return out


+ 5
- 5
frappe/templates/pages/login.py Visa fil

@@ -87,7 +87,7 @@ def get_oauth_keys(provider):
social = frappe.doc("Social Login Keys", "Social Login Keys") social = frappe.doc("Social Login Keys", "Social Login Keys")
keys = {} keys = {}
for fieldname in ("client_id", "client_secret"): for fieldname in ("client_id", "client_secret"):
value = social.fields.get("{provider}_{fieldname}".format(provider=provider, fieldname=fieldname))
value = social.get("{provider}_{fieldname}".format(provider=provider, fieldname=fieldname))
if not value: if not value:
keys = {} keys = {}
break break
@@ -198,17 +198,17 @@ def create_oauth_user(data, provider):
}) })
if provider=="facebook": if provider=="facebook":
user.doc.fields.update({
user.update({
"fb_username": data["username"], "fb_username": data["username"],
"fb_userid": data["id"], "fb_userid": data["id"],
"user_image": "https://graph.facebook.com/{username}/picture".format(username=data["username"]) "user_image": "https://graph.facebook.com/{username}/picture".format(username=data["username"])
}) })
elif provider=="google": elif provider=="google":
user.doc.google_userid = data["id"]
user.google_userid = data["id"]
elif provider=="github": elif provider=="github":
user.doc.github_userid = data["id"]
user.doc.github_username = data["login"]
user.github_userid = data["id"]
user.github_username = data["login"]
user.ignore_permissions = True user.ignore_permissions = True
user.get_controller().no_welcome_mail = True user.get_controller().no_welcome_mail = True


+ 2
- 2
frappe/templates/pages/style_settings.py Visa fil

@@ -28,8 +28,8 @@ def prepare(doc):
} }
for d in default_colours: for d in default_colours:
if not doc.fields.get(d):
doc.fields[d] = default_colours[d]
if not doc.get(d):
doc.set(d, default_colours[d])
if not doc.font_size: if not doc.font_size:
doc.font_size = "14px" doc.font_size = "14px"


+ 15
- 15
frappe/templates/website_group/post.py Visa fil

@@ -28,7 +28,7 @@ def get_post_context(context):
def get_parent_post_html(post, context): def get_parent_post_html(post, context):
user = frappe.bean("User", post.owner).doc user = frappe.bean("User", post.owner).doc
for fieldname in ("first_name", "last_name", "user_image", "location"): for fieldname in ("first_name", "last_name", "user_image", "location"):
post.fields[fieldname] = user.fields[fieldname]
post.set(fieldname, user.fields[fieldname])
return frappe.get_template("templates/includes/inline_post.html")\ return frappe.get_template("templates/includes/inline_post.html")\
.render({"post": post.fields, "view": context.view}) .render({"post": post.fields, "view": context.view})
@@ -76,11 +76,11 @@ def add_post(group, content, picture, picture_name, title=None, parent_post=None
if not parent_post: if not parent_post:
if group.group_type == "Tasks": if group.group_type == "Tasks":
post.doc.is_task = 1
post.doc.assigned_to = assigned_to
post.is_task = 1
post.assigned_to = assigned_to
elif group.group_type == "Events": elif group.group_type == "Events":
post.doc.is_event = 1
post.doc.event_datetime = event_datetime
post.is_event = 1
post.event_datetime = event_datetime
post.ignore_permissions = True post.ignore_permissions = True
post.insert() post.insert()
@@ -92,28 +92,28 @@ def add_post(group, content, picture, picture_name, title=None, parent_post=None
if parent_post: if parent_post:
post.run_method("send_email_on_reply") post.run_method("send_email_on_reply")
return post.doc.parent_post or post.doc.name
return post.parent_post or post.name
@frappe.whitelist(allow_guest=True) @frappe.whitelist(allow_guest=True)
def save_post(post, content, picture=None, picture_name=None, title=None, def save_post(post, content, picture=None, picture_name=None, title=None,
assigned_to=None, status=None, event_datetime=None): assigned_to=None, status=None, event_datetime=None):
post = frappe.bean("Post", post) post = frappe.bean("Post", post)
access = get_access(get_pathname(post.doc.website_group))
access = get_access(get_pathname(post.website_group))
if not access.get("write"): if not access.get("write"):
raise frappe.PermissionError raise frappe.PermissionError
# TODO improve error message # TODO improve error message
if frappe.session.user != post.doc.owner:
if frappe.session.user != post.owner:
for fieldname in ("title", "content"): for fieldname in ("title", "content"):
if post.doc.fields.get(fieldname) != locals().get(fieldname):
if post.get(fieldname) != locals().get(fieldname):
frappe.throw("You cannot change: {}".format(fieldname.title())) frappe.throw("You cannot change: {}".format(fieldname.title()))
if picture and picture_name: if picture and picture_name:
frappe.throw("You cannot change: Picture") frappe.throw("You cannot change: Picture")
post.doc.fields.update({
post.update({
"title": (title or "").title(), "title": (title or "").title(),
"content": content, "content": content,
"assigned_to": assigned_to, "assigned_to": assigned_to,
@@ -126,15 +126,15 @@ def save_post(post, content, picture=None, picture_name=None, title=None,
if picture_name and picture: if picture_name and picture:
process_picture(post, picture_name, picture) process_picture(post, picture_name, picture)
return post.doc.parent_post or post.doc.name
return post.parent_post or post.name
def process_picture(post, picture_name, picture): def process_picture(post, picture_name, picture):
from frappe.templates.generators.website_group import clear_cache from frappe.templates.generators.website_group import clear_cache
file_data = save_file(picture_name, picture, "Post", post.doc.name, decode=True)
post.doc.picture_url = file_data.file_name or file_data.file_url
frappe.db.set_value("Post", post.doc.name, "picture_url", post.doc.picture_url)
clear_cache(website_group=post.doc.website_group)
file_data = save_file(picture_name, picture, "Post", post.name, decode=True)
post.picture_url = file_data.file_name or file_data.file_url
frappe.db.set_value("Post", post.name, "picture_url", post.picture_url)
clear_cache(website_group=post.website_group)
@frappe.whitelist() @frappe.whitelist()
def suggest_user(group, term): def suggest_user(group, term):


+ 3
- 3
frappe/templates/website_group/settings.py Visa fil

@@ -44,7 +44,7 @@ def add_sitemap_permission(group, user):
}) })
permission.insert(ignore_permissions=True) permission.insert(ignore_permissions=True)
user = permission.doc.fields
user = permission.fields
user.update(frappe.db.get_value("User", user.user, user.update(frappe.db.get_value("User", user.user,
["name", "first_name", "last_name", "user_image", "location"], as_dict=True)) ["name", "first_name", "last_name", "user_image", "location"], as_dict=True))
@@ -59,7 +59,7 @@ def update_permission(group, user, perm, value):
raise frappe.PermissionError raise frappe.PermissionError
permission = frappe.bean("Website Route Permission", {"website_route": pathname, "user": user}) permission = frappe.bean("Website Route Permission", {"website_route": pathname, "user": user})
permission.doc.fields[perm] = int(value)
permission.set(perm, int(value))
permission.save(ignore_permissions=True) permission.save(ignore_permissions=True)
# send email # send email
@@ -80,7 +80,7 @@ def update_description(group, description):
raise frappe.PermissionError raise frappe.PermissionError


group = frappe.bean("Website Group", group) group = frappe.bean("Website Group", group)
group.doc.group_description = description
group.group_description = description
group.save(ignore_permissions=True) group.save(ignore_permissions=True)
@frappe.whitelist() @frappe.whitelist()


+ 7
- 7
frappe/test_runner.py Visa fil

@@ -143,23 +143,23 @@ def make_test_objects(doctype, test_records, verbose=None):
doclist[0]["doctype"] = doctype doclist[0]["doctype"] = doctype
d = frappe.bean(copy=doclist) d = frappe.bean(copy=doclist)
if frappe.local.test_objects.get(d.doc.doctype):
if frappe.local.test_objects.get(d.doctype):
# do not create test records, if already exists # do not create test records, if already exists
return [] return []
if has_field(d.doc.doctype, "naming_series"):
if not d.doc.naming_series:
d.doc.naming_series = "_T-" + d.doc.doctype + "-"
if has_field(d.doctype, "naming_series"):
if not d.naming_series:
d.naming_series = "_T-" + d.doctype + "-"


# submit if docstatus is set to 1 for test record # submit if docstatus is set to 1 for test record
docstatus = d.doc.docstatus
docstatus = d.docstatus
d.doc.docstatus = 0
d.docstatus = 0
d.insert() d.insert()


if docstatus == 1: if docstatus == 1:
d.submit() d.submit()
records.append(d.doc.name)
records.append(d.name)
return records return records


def print_mandatory_fields(doctype): def print_mandatory_fields(doctype):


+ 2
- 2
frappe/utils/datautils.py Visa fil

@@ -130,7 +130,7 @@ def import_doc(d, doctype, overwrite, row_idx, submit=False, ignore_links=False)
if overwrite: if overwrite:
bean = frappe.bean(doctype, d['name']) bean = frappe.bean(doctype, d['name'])
bean.ignore_links = ignore_links bean.ignore_links = ignore_links
bean.doc.fields.update(d)
bean.update(d)
if d.get("docstatus") == 1: if d.get("docstatus") == 1:
bean.update_after_submit() bean.update_after_submit()
else: else:
@@ -148,7 +148,7 @@ def import_doc(d, doctype, overwrite, row_idx, submit=False, ignore_links=False)
bean.submit() bean.submit()
return 'Inserted row (#%d) %s' % (row_idx + 1, getlink(doctype, return 'Inserted row (#%d) %s' % (row_idx + 1, getlink(doctype,
bean.doc.fields['name']))
bean.fields['name']))
def getlink(doctype, name): def getlink(doctype, name):
return '<a href="#Form/%(doctype)s/%(name)s">%(name)s</a>' % locals() return '<a href="#Form/%(doctype)s/%(name)s">%(name)s</a>' % locals()

+ 3
- 3
frappe/utils/file_manager.py Visa fil

@@ -55,7 +55,7 @@ def save_url(file_url, dt, dn):
try: try:
f.insert(); f.insert();
except frappe.DuplicateEntryError: except frappe.DuplicateEntryError:
return frappe.doc("File Data", f.doc.duplicate_entry)
return frappe.doc("File Data", f.duplicate_entry)
return f.doc return f.doc


def get_uploaded_content(): def get_uploaded_content():
@@ -85,7 +85,7 @@ def extract_images_from_html(doc, fieldname):
if content: if content:
content = re.sub('<img\s*src=\s*["\'](data:[^"\']*)["\']', _save_file, content) content = re.sub('<img\s*src=\s*["\'](data:[^"\']*)["\']', _save_file, content)
if frappe.flags.has_dataurl: if frappe.flags.has_dataurl:
doc.fields[fieldname] = content
doc.set(fieldname, content)
def save_file(fname, content, dt, dn, decode=False): def save_file(fname, content, dt, dn, decode=False):
if decode: if decode:
@@ -151,7 +151,7 @@ def save_file(fname, content, dt, dn, decode=False):
try: try:
f.insert(); f.insert();
except frappe.DuplicateEntryError: except frappe.DuplicateEntryError:
return frappe.doc("File Data", f.doc.duplicate_entry)
return frappe.doc("File Data", f.duplicate_entry)


return f.doc return f.doc




+ 20
- 20
frappe/utils/nestedset.py Visa fil

@@ -26,7 +26,7 @@ def update_nsm(doc_obj):
# get fields, data from the DocType # get fields, data from the DocType
opf = 'old_parent' opf = 'old_parent'


if str(doc_obj.__class__)=='frappe.model.doc.Document':
if str(doc_obj.__class__)=='frappe.model.Document':
# passed as a Document object # passed as a Document object
d = doc_obj d = doc_obj
pf = "parent_" + frappe.scrub(d.doctype) pf = "parent_" + frappe.scrub(d.doctype)
@@ -40,7 +40,7 @@ def update_nsm(doc_obj):
if hasattr(doc_obj,'nsm_oldparent_field'): if hasattr(doc_obj,'nsm_oldparent_field'):
opf = doc_obj.nsm_oldparent_field opf = doc_obj.nsm_oldparent_field


p, op = d.fields.get(pf) or None, d.fields.get(opf) or None
p, op = d.get(pf) or None, d.get(opf) or None
# has parent changed (?) or parent is None (root) # has parent changed (?) or parent is None (root)
if not d.lft and not d.rgt: if not d.lft and not d.rgt:
@@ -49,7 +49,7 @@ def update_nsm(doc_obj):
update_move_node(d, pf) update_move_node(d, pf)


# set old parent # set old parent
d.fields[opf] = p
d.set(opf, p)
frappe.db.set_value(d.doctype, d.name, opf, p or '') frappe.db.set_value(d.doctype, d.name, opf, p or '')


# reload # reload
@@ -92,7 +92,7 @@ def update_add_node(doc, parent, parent_field):




def update_move_node(doc, parent_field): def update_move_node(doc, parent_field):
parent = doc.fields.get(parent_field)
parent = doc.get(parent_field)
if parent: if parent:
new_parent = frappe.db.sql("""select lft, rgt from `tab%s` new_parent = frappe.db.sql("""select lft, rgt from `tab%s`
@@ -196,47 +196,47 @@ class DocTypeNestedSet(Document):
def on_trash(self): def on_trash(self):
if not self.nsm_parent_field: if not self.nsm_parent_field:
self.nsm_parent_field = frappe.scrub(self.doc.doctype) + "_parent"
self.nsm_parent_field = frappe.scrub(self.doctype) + "_parent"
parent = self.doc.fields[self.nsm_parent_field]
parent = self.fields[self.nsm_parent_field]
if not parent: if not parent:
msgprint(_("Root ") + self.doc.doctype + _(" cannot be deleted."), raise_exception=1)
msgprint(_("Root ") + self.doctype + _(" cannot be deleted."), raise_exception=1)
# cannot delete non-empty group # cannot delete non-empty group
has_children = frappe.db.sql("""select count(name) from `tab{doctype}` has_children = frappe.db.sql("""select count(name) from `tab{doctype}`
where `{nsm_parent_field}`=%s""".format(doctype=self.doc.doctype, nsm_parent_field=self.nsm_parent_field),
(self.doc.name,))[0][0]
where `{nsm_parent_field}`=%s""".format(doctype=self.doctype, nsm_parent_field=self.nsm_parent_field),
(self.name,))[0][0]
if has_children: if has_children:
frappe.throw("{cannot_delete}. {children_exist}: {name}.".format( frappe.throw("{cannot_delete}. {children_exist}: {name}.".format(
children_exist=_("Children exist for"), name=self.doc.name,
children_exist=_("Children exist for"), name=self.name,
cannot_delete=_("Cannot delete")), NestedSetChildExistsError) cannot_delete=_("Cannot delete")), NestedSetChildExistsError)


self.doc.fields[self.nsm_parent_field] = ""
self.set(self.nsm_parent_field, "")
update_nsm(self) update_nsm(self)
def before_rename(self, olddn, newdn, merge=False, group_fname="is_group"): def before_rename(self, olddn, newdn, merge=False, group_fname="is_group"):
if merge: if merge:
is_group = frappe.db.get_value(self.doc.doctype, newdn, group_fname)
if self.doc.fields[group_fname] != is_group:
is_group = frappe.db.get_value(self.doctype, newdn, group_fname)
if self.fields[group_fname] != is_group:
frappe.throw(_("""Merging is only possible between Group-to-Group or frappe.throw(_("""Merging is only possible between Group-to-Group or
Ledger-to-Ledger"""), NestedSetInvalidMergeError) Ledger-to-Ledger"""), NestedSetInvalidMergeError)
def after_rename(self, olddn, newdn, merge=False): def after_rename(self, olddn, newdn, merge=False):
if merge: if merge:
parent_field = "parent_" + self.doc.doctype.replace(" ", "_").lower()
rebuild_tree(self.doc.doctype, parent_field)
parent_field = "parent_" + self.doctype.replace(" ", "_").lower()
rebuild_tree(self.doctype, parent_field)
def validate_one_root(self): def validate_one_root(self):
if not self.doc.fields[self.nsm_parent_field]:
if not self.fields[self.nsm_parent_field]:
if frappe.db.sql("""select count(*) from `tab%s` where if frappe.db.sql("""select count(*) from `tab%s` where
ifnull(%s, '')=''""" % (self.doc.doctype, self.nsm_parent_field))[0][0] > 1:
ifnull(%s, '')=''""" % (self.doctype, self.nsm_parent_field))[0][0] > 1:
frappe.throw(_("""Multiple root nodes not allowed."""), NestedSetMultipleRootsError) frappe.throw(_("""Multiple root nodes not allowed."""), NestedSetMultipleRootsError)


def validate_ledger(self, group_identifier="is_group"): def validate_ledger(self, group_identifier="is_group"):
if self.doc.fields.get(group_identifier) == "No":
if self.get(group_identifier) == "No":
if frappe.db.sql("""select name from `tab%s` where %s=%s and docstatus!=2""" % if frappe.db.sql("""select name from `tab%s` where %s=%s and docstatus!=2""" %
(self.doc.doctype, self.nsm_parent_field, '%s'), (self.doc.name)):
frappe.throw(self.doc.doctype + ": " + self.doc.name +
(self.doctype, self.nsm_parent_field, '%s'), (self.name)):
frappe.throw(self.doctype + ": " + self.name +
_(" can not be marked as a ledger as it has existing child")) _(" can not be marked as a ledger as it has existing child"))


def get_root_of(doctype): def get_root_of(doctype):


+ 1
- 1
frappe/utils/response.py Visa fil

@@ -107,7 +107,7 @@ def json_handler(obj):
return unicode(obj) return unicode(obj)
elif isinstance(obj, LocalProxy): elif isinstance(obj, LocalProxy):
return unicode(obj) return unicode(obj)
elif isinstance(obj, frappe.model.doc.Document):
elif isinstance(obj, frappe.model.Document):
return obj.fields return obj.fields
elif isinstance(obj, frappe.model.document.Document): elif isinstance(obj, frappe.model.document.Document):
return obj.as_dict() return obj.as_dict()


+ 1
- 1
frappe/utils/user.py Visa fil

@@ -200,7 +200,7 @@ def add_role(user, role):
def add_system_manager(email, first_name=None, last_name=None): def add_system_manager(email, first_name=None, last_name=None):
# add user # add user
user = frappe.new_bean("User") user = frappe.new_bean("User")
user.doc.fields.update({
user.update({
"name": email, "name": email,
"email": email, "email": email,
"enabled": 1, "enabled": 1,


+ 2
- 2
frappe/website/doctype/blog_category/blog_category.py Visa fil

@@ -10,10 +10,10 @@ class BlogCategory(WebsiteGenerator):
def autoname(self): def autoname(self):
# to override autoname of WebsiteGenerator # to override autoname of WebsiteGenerator
self.doc.name = self.doc.category_name
self.name = self.category_name
def get_page_title(self): def get_page_title(self):
return self.doc.title or self.doc.name
return self.title or self.name
def on_update(self): def on_update(self):
WebsiteGenerator.on_update(self) WebsiteGenerator.on_update(self)


+ 11
- 11
frappe/website/doctype/blog_post/blog_post.py Visa fil

@@ -14,26 +14,26 @@ class BlogPost(WebsiteGenerator):
self.save_versions = True self.save_versions = True
def get_page_title(self): def get_page_title(self):
return self.doc.title
return self.title
def validate(self): def validate(self):
if not self.doc.blog_intro:
self.doc.blog_intro = self.doc.content[:140]
re.sub("\<[^>]*\>", "", self.doc.blog_intro)
if not self.blog_intro:
self.blog_intro = self.content[:140]
re.sub("\<[^>]*\>", "", self.blog_intro)
if self.doc.blog_intro:
self.doc.blog_intro = self.doc.blog_intro[:140]
if self.blog_intro:
self.blog_intro = self.blog_intro[:140]
if self.doc.published and not self.doc.published_on:
self.doc.published_on = today()
if self.published and not self.published_on:
self.published_on = today()


self.doc.parent_website_route = frappe.db.get_value("Website Route",
{"ref_doctype": "Blog Category", "docname": self.doc.blog_category})
self.parent_website_route = frappe.db.get_value("Website Route",
{"ref_doctype": "Blog Category", "docname": self.blog_category})


# update posts # update posts
frappe.db.sql("""update tabBlogger set posts=(select count(*) from `tabBlog Post` frappe.db.sql("""update tabBlogger set posts=(select count(*) from `tabBlog Post`
where ifnull(blogger,'')=tabBlogger.name) where ifnull(blogger,'')=tabBlogger.name)
where name=%s""", (self.doc.blogger,))
where name=%s""", (self.blogger,))


def on_update(self): def on_update(self):


+ 1
- 1
frappe/website/doctype/blog_post/test_blog_post.py Visa fil

@@ -166,7 +166,7 @@ class TestBlogPost(unittest.TestCase):
blog_post = frappe.get_meta("Blog Post") blog_post = frappe.get_meta("Blog Post")
blog_post.get_field("title").set_only_once = 1 blog_post.get_field("title").set_only_once = 1
bean = frappe.bean("Blog Post", "_test-blog-post-1") bean = frappe.bean("Blog Post", "_test-blog-post-1")
bean.doc.title = "New"
bean.title = "New"
self.assertRaises(frappe.CannotChangeConstantError, bean.save) self.assertRaises(frappe.CannotChangeConstantError, bean.save)
blog_post.get_field("title").set_only_once = 0 blog_post.get_field("title").set_only_once = 0

+ 3
- 3
frappe/website/doctype/blogger/blogger.py Visa fil

@@ -17,9 +17,9 @@ class Blogger(Document):
from frappe.website.doctype.blog_post.blog_post import clear_blog_cache from frappe.website.doctype.blog_post.blog_post import clear_blog_cache
clear_blog_cache() clear_blog_cache()
if self.doc.user:
if self.user:
for blog in frappe.db.sql_list("""select name from `tabBlog Post` where owner=%s for blog in frappe.db.sql_list("""select name from `tabBlog Post` where owner=%s
and ifnull(blogger,'')=''""", self.doc.user):
and ifnull(blogger,'')=''""", self.user):
b = frappe.bean("Blog Post", blog) b = frappe.bean("Blog Post", blog)
b.doc.blogger = self.doc.name
b.blogger = self.name
b.save() b.save()

+ 30
- 30
frappe/website/doctype/post/post.py Visa fil

@@ -15,51 +15,51 @@ from frappe.model.document import Document
class Post(Document): class Post(Document):
def validate(self): def validate(self):
if not self.doc.parent_post and not self.doc.title:
if not self.parent_post and not self.title:
frappe.throw("Please enter title!") frappe.throw("Please enter title!")
self.assigned_to = frappe.db.get_value(self.doc.doctype, self.doc.name, "assigned_to")
if self.doc.is_task:
if not self.doc.status:
self.doc.status = "Open"
if self.doc.assigned_to:
if not self.doc.assigned_to_fullname:
self.doc.assigned_to_fullname = get_fullname(self.doc.assigned_to)
self.assigned_to = frappe.db.get_value(self.doctype, self.name, "assigned_to")
if self.is_task:
if not self.status:
self.status = "Open"
if self.assigned_to:
if not self.assigned_to_fullname:
self.assigned_to_fullname = get_fullname(self.assigned_to)
else: else:
self.doc.assigned_to_fullname = None
self.assigned_to_fullname = None
else: else:
self.doc.assigned_to = self.doc.assigned_to_fullname = self.doc.status = None
self.assigned_to = self.assigned_to_fullname = self.status = None
if self.doc.is_event:
if not self.doc.event_datetime:
if self.is_event:
if not self.event_datetime:
frappe.throw("Please specify Event's Date and Time") frappe.throw("Please specify Event's Date and Time")
else: else:
self.doc.event_datetime = None
self.event_datetime = None
def on_update(self): def on_update(self):
from frappe.templates.website_group.post import clear_post_cache from frappe.templates.website_group.post import clear_post_cache
from frappe.templates.generators.website_group import clear_cache from frappe.templates.generators.website_group import clear_cache


clear_cache(website_group=self.doc.website_group)
clear_post_cache(self.doc.parent_post or self.doc.name)
clear_cache(website_group=self.website_group)
clear_post_cache(self.parent_post or self.name)


if self.doc.assigned_to and self.doc.assigned_to != self.assigned_to \
and frappe.session.user != self.doc.assigned_to:
if self.assigned_to and self.assigned_to != self.assigned_to \
and frappe.session.user != self.assigned_to:
# send assignment email # send assignment email
sendmail(recipients=[self.doc.assigned_to],
subject="You have been assigned this Task by {}".format(get_fullname(self.doc.modified_by)),
msg=self.get_reply_email_message(self.doc.name, get_fullname(self.doc.owner)))
sendmail(recipients=[self.assigned_to],
subject="You have been assigned this Task by {}".format(get_fullname(self.modified_by)),
msg=self.get_reply_email_message(self.name, get_fullname(self.owner)))
def send_email_on_reply(self): def send_email_on_reply(self):
owner_fullname = get_fullname(self.doc.owner)
owner_fullname = get_fullname(self.owner)
parent_post = frappe.bean("Post", self.doc.parent_post).doc
parent_post = frappe.bean("Post", self.parent_post).doc
message = self.get_reply_email_message(self.doc.name, owner_fullname)
message = self.get_reply_email_message(self.name, owner_fullname)
# send email to the owner of the post, if he/she is different # send email to the owner of the post, if he/she is different
if parent_post.owner != self.doc.owner:
if parent_post.owner != self.owner:
send(recipients=[parent_post.owner], send(recipients=[parent_post.owner],
subject="{someone} replied to your post".format(someone=owner_fullname), subject="{someone} replied to your post".format(someone=owner_fullname),
message=message, message=message,
@@ -69,12 +69,12 @@ class Post(Document):
email_field='owner', email_field='owner',
# for tracking sent status # for tracking sent status
ref_doctype=self.doc.doctype, ref_docname=self.doc.name)
ref_doctype=self.doctype, ref_docname=self.name)
# send email to members who part of the conversation # send email to members who part of the conversation
participants = frappe.db.sql("""select owner, name from `tabPost` participants = frappe.db.sql("""select owner, name from `tabPost`
where parent_post=%s and owner not in (%s, %s) order by creation asc""", where parent_post=%s and owner not in (%s, %s) order by creation asc""",
(self.doc.parent_post, parent_post.owner, self.doc.owner), as_dict=True)
(self.parent_post, parent_post.owner, self.owner), as_dict=True)
send(recipients=[p.owner for p in participants], send(recipients=[p.owner for p in participants],
subject="{someone} replied to a post by {other}".format(someone=owner_fullname, subject="{someone} replied to a post by {other}".format(someone=owner_fullname,
@@ -86,13 +86,13 @@ class Post(Document):
email_field='owner', email_field='owner',
# for tracking sent status # for tracking sent status
ref_doctype=self.doc.doctype, ref_docname=self.doc.name)
ref_doctype=self.doctype, ref_docname=self.name)
def get_reply_email_message(self, post_name, owner_fullname=None): def get_reply_email_message(self, post_name, owner_fullname=None):
message = self.doc.content
if self.doc.picture_url:
message = self.content
if self.picture_url:
message += """<div><img src="{url}" style="max-width: 100%"></div>"""\ message += """<div><img src="{url}" style="max-width: 100%"></div>"""\
.format(url=self.doc.picture_url)
.format(url=self.picture_url)
message += "<p>By {fullname}</p>".format(fullname=owner_fullname) message += "<p>By {fullname}</p>".format(fullname=owner_fullname)
message += "<p><a href='/post/{post_name}'>Click here to view the post</a></p>".format(fullname=owner_fullname, message += "<p><a href='/post/{post_name}'>Click here to view the post</a></p>".format(fullname=owner_fullname,
post_name=post_name) post_name=post_name)


+ 4
- 4
frappe/website/doctype/style_settings/style_settings.py Visa fil

@@ -16,13 +16,13 @@ class StyleSettings(Document):
self.validate_colors() self.validate_colors()
def validate_colors(self): def validate_colors(self):
if (self.doc.page_background or self.doc.page_text) and \
self.doc.page_background==self.doc.page_text:
if (self.page_background or self.page_text) and \
self.page_background==self.page_text:
frappe.msgprint(_("Page text and background is same color. Please change."), frappe.msgprint(_("Page text and background is same color. Please change."),
raise_exception=1) raise_exception=1)


if (self.doc.top_bar_background or self.doc.top_bar_foreground) and \
self.doc.top_bar_background==self.doc.top_bar_foreground:
if (self.top_bar_background or self.top_bar_foreground) and \
self.top_bar_background==self.top_bar_foreground:
frappe.msgprint(_("Top Bar text and background is same color. Please change."), frappe.msgprint(_("Top Bar text and background is same color. Please change."),
raise_exception=1) raise_exception=1)


+ 5
- 5
frappe/website/doctype/user_vote/user_vote.py Visa fil

@@ -11,9 +11,9 @@ class UserVote(Document):
def validate(self): def validate(self):
# if new # if new
if self.doc.fields.get("__islocal"):
if frappe.db.get_value("User Vote", {"ref_doctype": self.doc.ref_doctype,
"ref_name": self.doc.ref_name, "owner": frappe.session.user}):
if self.get("__islocal"):
if frappe.db.get_value("User Vote", {"ref_doctype": self.ref_doctype,
"ref_name": self.ref_name, "owner": frappe.session.user}):
raise frappe.DuplicateEntryError raise frappe.DuplicateEntryError
@@ -25,8 +25,8 @@ class UserVote(Document):


def update_ref_count(self, cnt=0): def update_ref_count(self, cnt=0):
count = frappe.db.sql("""select count(*) from `tabUser Vote` where ref_doctype=%s and ref_name=%s""", count = frappe.db.sql("""select count(*) from `tabUser Vote` where ref_doctype=%s and ref_name=%s""",
(self.doc.ref_doctype, self.doc.ref_name))[0][0]
frappe.db.set_value(self.doc.ref_doctype, self.doc.ref_name, "upvotes", count + cnt)
(self.ref_doctype, self.ref_name))[0][0]
frappe.db.set_value(self.ref_doctype, self.ref_name, "upvotes", count + cnt)
def on_doctype_update(): def on_doctype_update():
frappe.db.add_index("User Vote", ["ref_doctype", "ref_name"]) frappe.db.add_index("User Vote", ["ref_doctype", "ref_name"])


+ 4
- 4
frappe/website/doctype/web_page/test_web_page.py Visa fil

@@ -61,14 +61,14 @@ class TestWebPage(unittest.TestCase):
def test_check_rename(self): def test_check_rename(self):
web_page = frappe.bean("Web Page", "test-web-page-1") web_page = frappe.bean("Web Page", "test-web-page-1")
web_page.doc.parent_website_route = "test-web-page-4"
web_page.parent_website_route = "test-web-page-4"
web_page.save() web_page.save()


self.assertEquals(frappe.db.get_value("Website Route", self.assertEquals(frappe.db.get_value("Website Route",
{"ref_doctype":"Web Page", "docname": "test-web-page-2"}), {"ref_doctype":"Web Page", "docname": "test-web-page-2"}),
"test-web-page-4/test-web-page-1/test-web-page-2") "test-web-page-4/test-web-page-1/test-web-page-2")
web_page.doc.parent_website_route = ""
web_page.parent_website_route = ""
web_page.save() web_page.save()


self.assertEquals(frappe.db.get_value("Website Route", self.assertEquals(frappe.db.get_value("Website Route",
@@ -77,7 +77,7 @@ class TestWebPage(unittest.TestCase):
def test_check_move(self): def test_check_move(self):
web_page = frappe.bean("Web Page", "test-web-page-3") web_page = frappe.bean("Web Page", "test-web-page-3")
web_page.doc.parent_website_route = "test-web-page-4"
web_page.parent_website_route = "test-web-page-4"
web_page.save() web_page.save()
self.assertEquals(frappe.db.get_value("Website Route", self.assertEquals(frappe.db.get_value("Website Route",
@@ -90,7 +90,7 @@ class TestWebPage(unittest.TestCase):
{"ref_doctype":"Web Page", "docname": "test-web-page-5"}, 'idx'), 1) {"ref_doctype":"Web Page", "docname": "test-web-page-5"}, 'idx'), 1)
web_page = frappe.bean("Web Page", "test-web-page-3") web_page = frappe.bean("Web Page", "test-web-page-3")
web_page.doc.parent_website_route = "test-web-page-1"
web_page.parent_website_route = "test-web-page-1"
web_page.save() web_page.save()

+ 3
- 3
frappe/website/doctype/website_group/website_group.py Visa fil

@@ -10,11 +10,11 @@ from frappe.model.naming import make_autoname
class WebsiteGroup(WebsiteGenerator): class WebsiteGroup(WebsiteGenerator):
def get_page_title(self): def get_page_title(self):
return self.doc.group_title
return self.group_title
def on_update(self): def on_update(self):
WebsiteGenerator.on_update(self) WebsiteGenerator.on_update(self)
clear_cache(website_group=self.doc.name)
clear_cache(website_group=self.name)
def after_insert(self): def after_insert(self):
clear_cache(path=self.doc.parent_website_route)
clear_cache(path=self.parent_website_route)

+ 49
- 49
frappe/website/doctype/website_route/website_route.py Visa fil

@@ -14,37 +14,37 @@ class WebsiteRoute(DocTypeNestedSet):
self.nsm_parent_field = "parent_website_route" self.nsm_parent_field = "parent_website_route"
def autoname(self): def autoname(self):
self.doc.name = self.get_url()
self.name = self.get_url()


def get_url(self): def get_url(self):
url = self.doc.page_name
if self.doc.parent_website_route:
url = self.doc.parent_website_route + "/" + url
url = self.page_name
if self.parent_website_route:
url = self.parent_website_route + "/" + url
return url return url
def validate(self): def validate(self):
if self.get_url() != self.doc.name:
if self.get_url() != self.name:
self.rename() self.rename()
self.check_if_page_name_is_unique() self.check_if_page_name_is_unique()
self.make_private_if_parent_is_private() self.make_private_if_parent_is_private()
if not self.doc.is_new():
if not self.is_new():
self.renumber_if_moved() self.renumber_if_moved()
self.set_idx() self.set_idx()


def renumber_if_moved(self): def renumber_if_moved(self):
current_parent = frappe.db.get_value("Website Route", self.doc.name, "parent_website_route")
if current_parent and current_parent != self.doc.parent_website_route:
current_parent = frappe.db.get_value("Website Route", self.name, "parent_website_route")
if current_parent and current_parent != self.parent_website_route:
# move-up # move-up
# sitemap # sitemap
frappe.db.sql("""update `tabWebsite Route` set idx=idx-1 frappe.db.sql("""update `tabWebsite Route` set idx=idx-1
where parent_website_route=%s and idx>%s""", (current_parent, self.doc.idx))
where parent_website_route=%s and idx>%s""", (current_parent, self.idx))
# source table # source table
frappe.db.sql("""update `tab{0}` set idx=idx-1 frappe.db.sql("""update `tab{0}` set idx=idx-1
where parent_website_route=%s and idx>%s""".format(self.doc.ref_doctype),
(current_parent, self.doc.idx))
self.doc.idx = None
where parent_website_route=%s and idx>%s""".format(self.ref_doctype),
(current_parent, self.idx))
self.idx = None
def on_update(self): def on_update(self):
if not frappe.flags.in_rebuild_config: if not frappe.flags.in_rebuild_config:
@@ -52,36 +52,36 @@ class WebsiteRoute(DocTypeNestedSet):
self.clear_cache() self.clear_cache()


def set_idx(self): def set_idx(self):
if self.doc.parent_website_route:
if self.doc.idx == None:
if self.parent_website_route:
if self.idx == None:
self.set_idx_as_last() self.set_idx_as_last()
else: else:
self.validate_previous_idx_exists() self.validate_previous_idx_exists()
def set_idx_as_last(self): def set_idx_as_last(self):
# new, append # new, append
self.doc.idx = int(frappe.db.sql("""select ifnull(max(ifnull(idx, -1)), -1)
self.idx = int(frappe.db.sql("""select ifnull(max(ifnull(idx, -1)), -1)
from `tabWebsite Route` from `tabWebsite Route`
where ifnull(parent_website_route, '')=%s and name!=%s""", where ifnull(parent_website_route, '')=%s and name!=%s""",
(self.doc.parent_website_route or '',
self.doc.name))[0][0]) + 1
(self.parent_website_route or '',
self.name))[0][0]) + 1
def validate_previous_idx_exists(self): def validate_previous_idx_exists(self):
self.doc.idx = cint(self.doc.idx)
self.idx = cint(self.idx)
previous_idx = frappe.db.sql("""select max(idx) previous_idx = frappe.db.sql("""select max(idx)
from `tab{}` where ifnull(parent_website_route, '')=%s from `tab{}` where ifnull(parent_website_route, '')=%s
and ifnull(idx, -1) < %s""".format(self.doc.ref_doctype),
(self.doc.parent_website_route, self.doc.idx))[0][0]
and ifnull(idx, -1) < %s""".format(self.ref_doctype),
(self.parent_website_route, self.idx))[0][0]
if previous_idx and previous_idx != self.doc.idx - 1:
if previous_idx and previous_idx != self.idx - 1:
frappe.throw("{}: {}, {}".format( frappe.throw("{}: {}, {}".format(
_("Sitemap Ordering Error. Index missing"), self.doc.name, self.doc.idx-1))
_("Sitemap Ordering Error. Index missing"), self.name, self.idx-1))


def rename(self): def rename(self):
self.old_name = self.doc.name
self.doc.name = self.get_url()
self.old_name = self.name
self.name = self.get_url()
frappe.db.sql("""update `tabWebsite Route` set name=%s where name=%s""", frappe.db.sql("""update `tabWebsite Route` set name=%s where name=%s""",
(self.doc.name, self.old_name))
(self.name, self.old_name))
self.rename_links() self.rename_links()
self.rename_descendants() self.rename_descendants()
self.clear_cache(self.old_name) self.clear_cache(self.old_name)
@@ -91,80 +91,80 @@ class WebsiteRoute(DocTypeNestedSet):
fieldname='parent_website_route' and options='Website Route'"""): fieldname='parent_website_route' and options='Website Route'"""):
for name in frappe.db.sql_list("""select name from `tab{}` for name in frappe.db.sql_list("""select name from `tab{}`
where parent_website_route=%s""".format(doctype), self.old_name): where parent_website_route=%s""".format(doctype), self.old_name):
frappe.db.set_value(doctype, name, "parent_website_route", self.doc.name)
frappe.db.set_value(doctype, name, "parent_website_route", self.name)
def rename_descendants(self): def rename_descendants(self):
# rename children # rename children
for name in frappe.db.sql_list("""select name from `tabWebsite Route` for name in frappe.db.sql_list("""select name from `tabWebsite Route`
where parent_website_route=%s""", self.doc.name):
where parent_website_route=%s""", self.name):
child = frappe.bean("Website Route", name) child = frappe.bean("Website Route", name)
child.doc.parent_website_route = self.doc.name
child.parent_website_route = self.name
child.save() child.save()
def check_if_page_name_is_unique(self): def check_if_page_name_is_unique(self):
exists = False exists = False
if self.doc.page_or_generator == "Page":
if self.page_or_generator == "Page":
# for a page, name and website sitemap config form a unique key # for a page, name and website sitemap config form a unique key
exists = frappe.db.sql("""select name from `tabWebsite Route` exists = frappe.db.sql("""select name from `tabWebsite Route`
where name=%s and website_template!=%s""", (self.doc.name, self.doc.website_template))
where name=%s and website_template!=%s""", (self.name, self.website_template))
else: else:
# for a generator, name, ref_doctype and docname make a unique key # for a generator, name, ref_doctype and docname make a unique key
exists = frappe.db.sql("""select name from `tabWebsite Route` exists = frappe.db.sql("""select name from `tabWebsite Route`
where name=%s and (ifnull(ref_doctype, '')!=%s or ifnull(docname, '')!=%s)""", where name=%s and (ifnull(ref_doctype, '')!=%s or ifnull(docname, '')!=%s)""",
(self.doc.name, self.doc.ref_doctype, self.doc.docname))
(self.name, self.ref_doctype, self.docname))
if exists: if exists:
frappe.throw("{}: {}. {}.".format(_("A Website Page already exists with the Page Name"), frappe.throw("{}: {}. {}.".format(_("A Website Page already exists with the Page Name"),
self.doc.name, _("Please change it to continue")))
self.name, _("Please change it to continue")))
def make_private_if_parent_is_private(self): def make_private_if_parent_is_private(self):
if self.doc.parent_website_route:
parent_pubic_read = frappe.db.get_value("Website Route", self.doc.parent_website_route,
if self.parent_website_route:
parent_pubic_read = frappe.db.get_value("Website Route", self.parent_website_route,
"public_read") "public_read")
if not parent_pubic_read: if not parent_pubic_read:
self.doc.public_read = self.doc.public_write = 0
self.public_read = self.public_write = 0
def on_trash(self): def on_trash(self):
# remove website sitemap permissions # remove website sitemap permissions
to_remove = frappe.db.sql_list("""select name from `tabWebsite Route Permission` to_remove = frappe.db.sql_list("""select name from `tabWebsite Route Permission`
where website_route=%s""", (self.doc.name,))
where website_route=%s""", (self.name,))
frappe.delete_doc("Website Route Permission", to_remove, ignore_permissions=True) frappe.delete_doc("Website Route Permission", to_remove, ignore_permissions=True)
self.clear_cache() self.clear_cache()
def clear_cache(self, name=None): def clear_cache(self, name=None):
from frappe.website.render import clear_cache from frappe.website.render import clear_cache
clear_cache(name or self.doc.name)
if self.doc.parent_website_route:
clear_cache(self.doc.parent_website_route)
clear_cache(name or self.name)
if self.parent_website_route:
clear_cache(self.parent_website_route)
def add_to_sitemap(options): def add_to_sitemap(options):
bean = frappe.new_bean("Website Route") bean = frappe.new_bean("Website Route")


for key in sitemap_fields: for key in sitemap_fields:
bean.doc.fields[key] = options.get(key)
if not bean.doc.page_name:
bean.doc.page_name = options.get("link_name")
bean.doc.website_template = options.get("link_name")
bean.set(key, options.get(key))
if not bean.page_name:
bean.page_name = options.get("link_name")
bean.website_template = options.get("link_name")


bean.insert(ignore_permissions=True) bean.insert(ignore_permissions=True)
return bean.doc.idx
return bean.idx
def update_sitemap(website_route, options): def update_sitemap(website_route, options):
bean = frappe.bean("Website Route", website_route) bean = frappe.bean("Website Route", website_route)
for key in sitemap_fields: for key in sitemap_fields:
bean.doc.fields[key] = options.get(key)
bean.set(key, options.get(key))
if not bean.doc.page_name:
if not bean.page_name:
# for pages # for pages
bean.doc.page_name = options.get("link_name")
bean.page_name = options.get("link_name")
bean.doc.website_template = options.get("link_name")
bean.website_template = options.get("link_name")
bean.save(ignore_permissions=True) bean.save(ignore_permissions=True)


return bean.doc.idx
return bean.idx
def remove_sitemap(page_name=None, ref_doctype=None, docname=None): def remove_sitemap(page_name=None, ref_doctype=None, docname=None):
if page_name: if page_name:


+ 1
- 1
frappe/website/doctype/website_route_permission/website_route_permission.py Visa fil

@@ -12,5 +12,5 @@ class WebsiteRoutePermission(Document):
def on_update(self): def on_update(self):
remove_empty_permissions() remove_empty_permissions()
clear_permissions(self.doc.user)
clear_permissions(self.user)

+ 3
- 3
frappe/website/doctype/website_settings/website_settings.py Visa fil

@@ -15,8 +15,8 @@ class WebsiteSettings(DocListController):
self.validate_home_page() self.validate_home_page()
def validate_home_page(self): def validate_home_page(self):
if self.doc.home_page and \
not frappe.db.get_value("Website Route", {"name": self.doc.home_page}):
if self.home_page and \
not frappe.db.get_value("Website Route", {"name": self.home_page}):
frappe.throw(_("Invalid Home Page") + " (Standard pages - index, login, products, blog, about, contact)") frappe.throw(_("Invalid Home Page") + " (Standard pages - index, login, products, blog, about, contact)")
def validate_top_bar_items(self): def validate_top_bar_items(self):
@@ -85,7 +85,7 @@ def get_website_settings():
"favicon", "facebook_share", "google_plus_one", "twitter_share", "linked_in_share", "favicon", "facebook_share", "google_plus_one", "twitter_share", "linked_in_share",
"disable_signup"]: "disable_signup"]:
if k in settings.fields: if k in settings.fields:
context[k] = settings.fields.get(k)
context[k] = settings.get(k)
if not context.get("favicon"): if not context.get("favicon"):
context["favicon"] = "/assets/frappe/images/favicon.ico" context["favicon"] = "/assets/frappe/images/favicon.ico"


+ 2
- 2
frappe/website/doctype/website_slideshow/website_slideshow.py Visa fil

@@ -16,9 +16,9 @@ class WebsiteSlideshow(Document):
clear_cache() clear_cache()
def get_slideshow(bean): def get_slideshow(bean):
slideshow = frappe.bean("Website Slideshow", bean.doc.slideshow)
slideshow = frappe.bean("Website Slideshow", bean.slideshow)
return { return {
"slides": slideshow.doclist.get({"doctype":"Website Slideshow Item"}), "slides": slideshow.doclist.get({"doctype":"Website Slideshow Item"}),
"slideshow_header": slideshow.doc.header or ""
"slideshow_header": slideshow.header or ""
} }

+ 9
- 9
frappe/website/doctype/website_template/website_template.py Visa fil

@@ -16,11 +16,11 @@ from frappe.model.document import Document
class WebsiteTemplate(Document): class WebsiteTemplate(Document):
def after_insert(self): def after_insert(self):
if self.doc.page_or_generator == "Page":
if self.page_or_generator == "Page":
website_route = frappe.db.get_value("Website Route", website_route = frappe.db.get_value("Website Route",
{"website_template": self.doc.name, "page_or_generator": "Page"})
{"website_template": self.name, "page_or_generator": "Page"})
opts = self.doc.fields.copy()
opts = self.copy()
opts.update({"public_read": 1}) opts.update({"public_read": 1})
if website_route: if website_route:
@@ -30,17 +30,17 @@ class WebsiteTemplate(Document):
else: else:
condition = "" condition = ""
if self.doc.condition_field:
condition = " where ifnull(%s, 0)=1" % self.doc.condition_field
if self.condition_field:
condition = " where ifnull(%s, 0)=1" % self.condition_field
for name in frappe.db.sql_list("""select name from `tab{doctype}` for name in frappe.db.sql_list("""select name from `tab{doctype}`
{condition} order by idx asc, {sort_field} {sort_order}""".format( {condition} order by idx asc, {sort_field} {sort_order}""".format(
doctype = self.doc.ref_doctype,
doctype = self.ref_doctype,
condition = condition, condition = condition,
sort_field = self.doc.sort_field or "name",
sort_order = self.doc.sort_order or "asc"
sort_field = self.sort_field or "name",
sort_order = self.sort_order or "asc"
)): )):
bean = frappe.bean(self.doc.ref_doctype, name)
bean = frappe.bean(self.ref_doctype, name)
# regenerate route # regenerate route
bean.run_method("on_update") bean.run_method("on_update")


+ 1
- 1
frappe/website/page/sitemap_browser/sitemap_browser.py Visa fil

@@ -66,7 +66,7 @@ def update_parent(name, new_parent):
generator = frappe.bean(sitemap.ref_doctype, sitemap.docname) generator = frappe.bean(sitemap.ref_doctype, sitemap.docname)
if not generator.meta.has_field("parent_website_route"): if not generator.meta.has_field("parent_website_route"):
frappe.throw("Does not allow moving.") frappe.throw("Does not allow moving.")
generator.doc.parent_website_route = new_parent
generator.parent_website_route = new_parent
generator.save() generator.save()
else: else:
frappe.msgprint("Template Pages cannot be moved.") frappe.msgprint("Template Pages cannot be moved.")


+ 10
- 10
frappe/website/statics.py Visa fil

@@ -119,29 +119,29 @@ class sync(object):
"parent_website_route": parent_website_route "parent_website_route": parent_website_route
}) })
page.doc.fields.update(get_static_content(fpath, page_name))
page.update(get_static_content(fpath, page_name))


try: try:
page.insert() page.insert()
except NameError: except NameError:
# page exists, if deleted static, delete it and try again # page exists, if deleted static, delete it and try again
old_route = frappe.doc("Website Route", {"ref_doctype":"Web Page", old_route = frappe.doc("Website Route", {"ref_doctype":"Web Page",
"docname": page.doc.name})
"docname": page.name})
if old_route.static_file_timestamp and not os.path.exists(os.path.join(self.statics_path, if old_route.static_file_timestamp and not os.path.exists(os.path.join(self.statics_path,
old_route.name)): old_route.name)):
frappe.delete_doc("Web Page", page.doc.name)
frappe.delete_doc("Web Page", page.name)
page.insert() # retry page.insert() # retry
# update timestamp # update timestamp
route_bean = frappe.bean("Website Route", {"ref_doctype": "Web Page", route_bean = frappe.bean("Website Route", {"ref_doctype": "Web Page",
"docname": page.doc.name})
route_bean.doc.static_file_timestamp = cint(os.path.getmtime(fpath))
"docname": page.name})
route_bean.static_file_timestamp = cint(os.path.getmtime(fpath))
route_bean.save() route_bean.save()


self.updated += 1 self.updated += 1
print route_bean.doc.name + " inserted"
print route_bean.name + " inserted"
self.synced.append(route) self.synced.append(route)
def update_web_page(self, route_details, fpath, priority, parent_website_route): def update_web_page(self, route_details, fpath, priority, parent_website_route):
@@ -149,15 +149,15 @@ class sync(object):
or (cint(route_details.idx) != cint(priority) and (priority is not None)): or (cint(route_details.idx) != cint(priority) and (priority is not None)):


page = frappe.bean("Web Page", route_details.docname) page = frappe.bean("Web Page", route_details.docname)
page.doc.fields.update(get_static_content(fpath, route_details.docname))
page.doc.idx = priority
page.update(get_static_content(fpath, route_details.docname))
page.idx = priority
page.save() page.save()


route_bean = frappe.bean("Website Route", route_details.name) route_bean = frappe.bean("Website Route", route_details.name)
route_bean.doc.static_file_timestamp = cint(os.path.getmtime(fpath))
route_bean.static_file_timestamp = cint(os.path.getmtime(fpath))
route_bean.save() route_bean.save()


print route_bean.doc.name + " updated"
print route_bean.name + " updated"
self.updated += 1 self.updated += 1
self.synced.append(route_details.name) self.synced.append(route_details.name)


+ 23
- 23
frappe/website/website_generator.py Visa fil

@@ -14,27 +14,27 @@ def call_website_generator(bean, method, *args, **kwargs):


class WebsiteGenerator(DocListController): class WebsiteGenerator(DocListController):
def autoname(self): def autoname(self):
self.doc.name = self.get_page_name()
self.doc.append_number_if_name_exists()
self.name = self.get_page_name()
self.append_number_if_name_exists()


def set_page_name(self): def set_page_name(self):
"""set page name based on parent page_name and title""" """set page name based on parent page_name and title"""
page_name = cleanup_page_name(self.get_page_title()) page_name = cleanup_page_name(self.get_page_title())


if self.doc.is_new():
self.doc.fields[self.website_template.page_name_field] = page_name
if self.is_new():
self.set(self.website_template.page_name_field, page_name)
else: else:
frappe.db.set(self.doc, self.website_template.page_name_field, page_name) frappe.db.set(self.doc, self.website_template.page_name_field, page_name)
return page_name return page_name


def get_parent_website_route(self): def get_parent_website_route(self):
return self.doc.parent_website_route
return self.parent_website_route


def setup_generator(self): def setup_generator(self):
if not hasattr(self, "website_template"): if not hasattr(self, "website_template"):
self.website_template = frappe.db.get_values("Website Template", self.website_template = frappe.db.get_values("Website Template",
{"ref_doctype": self.doc.doctype}, "*")[0]
{"ref_doctype": self.doctype}, "*")[0]


def on_update(self): def on_update(self):
self.update_sitemap() self.update_sitemap()
@@ -43,23 +43,23 @@ class WebsiteGenerator(DocListController):
def after_rename(self, olddn, newdn, merge): def after_rename(self, olddn, newdn, merge):
frappe.db.sql("""update `tabWebsite Route` frappe.db.sql("""update `tabWebsite Route`
set docname=%s where ref_doctype=%s and docname=%s""", (newdn, self.doc.doctype, olddn))
set docname=%s where ref_doctype=%s and docname=%s""", (newdn, self.doctype, olddn))
if merge: if merge:
self.setup_generator() self.setup_generator()
remove_sitemap(ref_doctype=self.doc.doctype, docname=olddn)
remove_sitemap(ref_doctype=self.doctype, docname=olddn)
def on_trash(self): def on_trash(self):
self.setup_generator() self.setup_generator()
remove_sitemap(ref_doctype=self.doc.doctype, docname=self.doc.name)
remove_sitemap(ref_doctype=self.doctype, docname=self.name)
def update_sitemap(self): def update_sitemap(self):
self.setup_generator() self.setup_generator()
if self.website_template.condition_field and \ if self.website_template.condition_field and \
not self.doc.fields.get(self.website_template.condition_field):
not self.get(self.website_template.condition_field):
# condition field failed, remove and return! # condition field failed, remove and return!
remove_sitemap(ref_doctype=self.doc.doctype, docname=self.doc.name)
remove_sitemap(ref_doctype=self.doctype, docname=self.name)
return return
self.add_or_update_sitemap() self.add_or_update_sitemap()
@@ -67,19 +67,19 @@ class WebsiteGenerator(DocListController):
def add_or_update_sitemap(self): def add_or_update_sitemap(self):
page_name = self.get_page_name() page_name = self.get_page_name()
existing_site_map = frappe.db.get_value("Website Route", {"ref_doctype": self.doc.doctype,
"docname": self.doc.name})
existing_site_map = frappe.db.get_value("Website Route", {"ref_doctype": self.doctype,
"docname": self.name})
if self.doc.modified:
lastmod = frappe.utils.get_datetime(self.doc.modified).strftime("%Y-%m-%d")
if self.modified:
lastmod = frappe.utils.get_datetime(self.modified).strftime("%Y-%m-%d")
else: else:
lastmod = now() lastmod = now()
opts = frappe._dict({ opts = frappe._dict({
"page_or_generator": "Generator", "page_or_generator": "Generator",
"ref_doctype":self.doc.doctype,
"idx": self.doc.idx,
"docname": self.doc.name,
"ref_doctype":self.doctype,
"idx": self.idx,
"docname": self.name,
"page_name": page_name, "page_name": page_name,
"link_name": self.website_template.name, "link_name": self.website_template.name,
"lastmod": lastmod, "lastmod": lastmod,
@@ -95,13 +95,13 @@ class WebsiteGenerator(DocListController):
else: else:
idx = add_to_sitemap(opts) idx = add_to_sitemap(opts)


if idx!=None and self.doc.idx != idx:
if idx!=None and self.idx != idx:
frappe.db.set(self.doc, "idx", idx) frappe.db.set(self.doc, "idx", idx)
def update_permissions(self, opts): def update_permissions(self, opts):
if self.meta.get_field("public_read"): if self.meta.get_field("public_read"):
opts.public_read = self.doc.public_read
opts.public_write = self.doc.public_write
opts.public_read = self.public_read
opts.public_write = self.public_write
else: else:
opts.public_read = 1 opts.public_read = 1
@@ -115,9 +115,9 @@ class WebsiteGenerator(DocListController):
def _get_page_name(self): def _get_page_name(self):
self.setup_generator() self.setup_generator()
if self.meta.has_field(self.website_template.page_name_field): if self.meta.has_field(self.website_template.page_name_field):
return self.doc.fields.get(self.website_template.page_name_field)
return self.get(self.website_template.page_name_field)
else: else:
return cleanup_page_name(self.get_page_title()) return cleanup_page_name(self.get_page_title())
def get_page_title(self): def get_page_title(self):
return self.doc.title or (self.doc.name.replace("-", " ").replace("_", " ").title())
return self.title or (self.name.replace("-", " ").replace("_", " ").title())

+ 2
- 2
frappe/widgets/calendar.py Visa fil

@@ -12,7 +12,7 @@ def update_event(args, field_map):
args = frappe._dict(json.loads(args)) args = frappe._dict(json.loads(args))
field_map = frappe._dict(json.loads(field_map)) field_map = frappe._dict(json.loads(field_map))
w = frappe.bean(args.doctype, args.name) w = frappe.bean(args.doctype, args.name)
w.doc.fields[field_map.start] = args[field_map.start]
w.doc.fields[field_map.end] = args[field_map.end]
w.set(field_map.start, args[field_map.start])
w.set(field_map.end, args[field_map.end])
w.save() w.save()



+ 1
- 1
frappe/widgets/event.py Visa fil

@@ -39,7 +39,7 @@ def get_cal_events(m_st, m_end):
doclist, rl = [], [] doclist, rl = [], []
for r in res1 + res2 + res3 + res4: for r in res1 + res2 + res3 + res4:
if not r in rl: if not r in rl:
doclist += frappe.model.doc.get('Event', r[0])
doclist += frappe.model.get('Event', r[0])
rl.append(r) rl.append(r)
return doclist return doclist

+ 2
- 2
frappe/widgets/form/assign_to.py Visa fil

@@ -80,7 +80,7 @@ def add(args=None):
def remove(doctype, name, assign_to): def remove(doctype, name, assign_to):
"""remove from todo""" """remove from todo"""
todo = frappe.bean("ToDo", {"reference_type":doctype, "reference_name":name, "owner":assign_to, "status":"Open"}) todo = frappe.bean("ToDo", {"reference_type":doctype, "reference_name":name, "owner":assign_to, "status":"Open"})
todo.doc.status = "Closed"
todo.status = "Closed"
todo.save(ignore_permissions=True) todo.save(ignore_permissions=True)
# clear assigned_to if field exists # clear assigned_to if field exists
@@ -88,7 +88,7 @@ def remove(doctype, name, assign_to):
if has_field(doctype, "assigned_to"): if has_field(doctype, "assigned_to"):
frappe.db.set_value(doctype, name, "assigned_to", None) frappe.db.set_value(doctype, name, "assigned_to", None)


notify_assignment(todo.doc.assigned_by, todo.doc.owner, todo.doc.reference_type, todo.doc.reference_name)
notify_assignment(todo.assigned_by, todo.owner, todo.reference_type, todo.reference_name)


return get({"doctype": doctype, "name": name}) return get({"doctype": doctype, "name": name})


+ 1
- 1
frappe/widgets/form/run_method.py Visa fil

@@ -39,7 +39,7 @@ def runserverobj():
if r: if r:
#build output as csv #build output as csv
if cint(frappe.form_dict.get('as_csv')): if cint(frappe.form_dict.get('as_csv')):
make_csv_output(r, so.doc.doctype)
make_csv_output(r, so.doctype)
else: else:
frappe.response['message'] = r frappe.response['message'] = r


+ 2
- 2
frappe/widgets/query_report.py Visa fil

@@ -17,9 +17,9 @@ def get_report_doc(report_name):
if not bean.has_read_perm(): if not bean.has_read_perm():
raise frappe.PermissionError("You don't have access to: {report}".format(report=report_name)) raise frappe.PermissionError("You don't have access to: {report}".format(report=report_name))
if not frappe.has_permission(bean.doc.ref_doctype, "report"):
if not frappe.has_permission(bean.ref_doctype, "report"):
raise frappe.PermissionError("You don't have access to get a report on: {doctype}".format( raise frappe.PermissionError("You don't have access to get a report on: {doctype}".format(
doctype=bean.doc.ref_doctype))
doctype=bean.ref_doctype))
return bean.doc return bean.doc




Laddar…
Avbryt
Spara