[fix] fetch values server side for link fields

This commit is contained in:
Rushabh Mehta 2016-11-18 14:49:27 +05:30
parent 819983a7b6
commit 349e803bd1
4 changed files with 97 additions and 7 deletions

View file

@ -9,4 +9,8 @@ import unittest
# test_records = frappe.get_test_records('ToDo')
class TestToDo(unittest.TestCase):
pass
def test_fetch(self):
todo = frappe.get_doc(dict(doctype='ToDo', description='test todo',
assigned_by='Administrator')).insert()
self.assertEquals(todo.assigned_by_full_name,
frappe.db.get_value('User', todo.assigned_by, 'full_name'))

View file

@ -23,6 +23,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "",
@ -51,6 +52,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Status",
@ -80,6 +82,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Priority",
@ -110,6 +113,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
@ -136,6 +140,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Due Date",
@ -165,6 +170,7 @@
"ignore_user_permissions": 1,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Allocated To",
@ -193,6 +199,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "",
@ -221,6 +228,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Description",
@ -252,6 +260,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Reference",
@ -279,6 +288,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Reference Type",
@ -309,6 +319,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Reference Name",
@ -339,6 +350,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
@ -365,6 +377,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Role",
@ -395,6 +408,7 @@
"ignore_user_permissions": 1,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Assigned By",
@ -412,6 +426,36 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "assigned_by_full_name",
"fieldtype": "Read Only",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Assigned By Full Name",
"length": 0,
"no_copy": 0,
"options": "assigned_by.full_name",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
@ -423,6 +467,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Sender",
@ -452,7 +497,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2016-11-07 05:29:56.682890",
"modified": "2016-11-18 14:45:27.214657",
"modified_by": "Administrator",
"module": "Desk",
"name": "ToDo",

View file

@ -426,6 +426,7 @@ class BaseDocument(object):
return missing
def get_invalid_links(self, is_submittable=False):
'''Returns list of invalid links and also updates fetch values if not set'''
def get_msg(df, docname):
if self.parentfield:
return "{} #{}: {}: {}".format(_("Row"), self.idx, _(df.label), docname)
@ -434,6 +435,7 @@ class BaseDocument(object):
invalid_links = []
cancelled_links = []
for df in (self.meta.get_link_fields()
+ self.meta.get("fields", {"fieldtype":"Dynamic Link"})):
docname = self.get(df.fieldname)
@ -449,15 +451,38 @@ class BaseDocument(object):
frappe.throw(_("{0} must be set first").format(self.meta.get_label(df.options)))
# MySQL is case insensitive. Preserve case of the original docname in the Link Field.
value = frappe.db.get_value(doctype, docname, "name", cache=True)
if frappe.get_meta(doctype).issingle:
value = doctype
setattr(self, df.fieldname, value)
# get a map of values ot fetch along with this link query
# that are mapped as link_fieldname.source_fieldname in Options of
# Readonly or Data or Text type fields
fields_to_fetch = [
_df for _df in self.meta.get_fields_to_fetch(df.fieldname)
if not self.get(_df.fieldname)
]
if not fields_to_fetch:
# cache a single value type
values = frappe._dict(name=frappe.db.get_value(doctype, docname,
'name', cache=True))
else:
values_to_fetch = ['name'] + [_df.options.split('.')[-1]
for _df in fields_to_fetch]
# don't cache if fetching other values too
values = frappe.db.get_value(doctype, docname,
values_to_fetch, as_dict=True)
if frappe.get_meta(doctype).issingle:
values.name = doctype
setattr(self, df.fieldname, values.name)
for _df in fields_to_fetch:
setattr(self, _df.fieldname, values[_df.options.split('.')[-1]])
notify_link_count(doctype, docname)
if not value:
if not values.name:
invalid_links.append((df.fieldname, docname, get_msg(df, docname)))
elif (df.fieldname != "amended_from"

View file

@ -155,6 +155,22 @@ class Meta(Document):
return search_fields
def get_fields_to_fetch(self, link_fieldname):
'''Returns a list of docfield objects for fields whose values
are to be fetched and updated for a particular link field
These fields are of type Data, Link, Text, Readonly and their
options property is set as `link_fieldname`.`source_fieldname`'''
out = []
for df in self.fields:
if df.fieldtype in ('Data', 'Read Only', 'Text', 'Small Text',
'Text Editor', 'Code') and df.options and \
df.options.startswith(link_fieldname + '.'):
out.append(df)
return out
def get_list_fields(self):
list_fields = ["name"] + [d.fieldname \
for d in self.fields if (d.in_list_view and d.fieldtype in type_map)]