def get_doc(arg1, arg2=None): """returns a frappe.model.Document object. :param arg1: Document dict or DocType name. :param arg2: [optional] document name. There are two ways to call `get_doc` # will fetch the latest user object (with child table) from the database user = get_doc("User", "*****@*****.**") # create a new object user = get_doc({ "doctype":"User" "email_id": "*****@*****.**", "user_roles: [ {"role": "System Manager"} ] }) """ if isinstance(arg1, BaseDocument): return arg1 elif isinstance(arg1, basestring): doctype = arg1 else: doctype = arg1.get("doctype") controller = get_controller(doctype) if controller: return controller(arg1, arg2) raise ImportError, arg1
def import_doc(docdict, force=False, data_import=False, pre_process=None, ignore_version=None, reset_permissions=False, path=None): frappe.flags.in_import = True docdict["__islocal"] = 1 controller = get_controller(docdict["doctype"]) if controller and hasattr(controller, "prepare_for_import") and callable(getattr(controller, "prepare_for_import")): controller.prepare_for_import(docdict) doc = frappe.get_doc(docdict) reset_tree_properties(doc) load_code_properties(doc, path) doc.run_method("before_import") doc.flags.ignore_version = ignore_version if pre_process: pre_process(doc) if frappe.db.exists(doc.doctype, doc.name): delete_old_doc(doc, reset_permissions) doc.flags.ignore_links = True if not data_import: doc.flags.ignore_validate = True doc.flags.ignore_permissions = True doc.flags.ignore_mandatory = True doc.insert() frappe.flags.in_import = False return doc
def load_desktop_data(bootinfo): from frappe.config import get_modules_from_all_apps_for_user from frappe.desk.desktop import get_desk_sidebar_items bootinfo.allowed_modules = get_modules_from_all_apps_for_user() bootinfo.allowed_workspaces = get_desk_sidebar_items(flatten=True, cache=False) bootinfo.module_page_map = get_controller("Desk Page").get_module_page_map() bootinfo.dashboards = frappe.get_all("Dashboard")
def load_desktop_data(bootinfo): from frappe.desk.desktop import get_desk_sidebar_items bootinfo.allowed_workspaces = get_desk_sidebar_items() bootinfo.module_page_map = get_controller( "Workspace").get_module_page_map() bootinfo.dashboards = frappe.get_all("Dashboard")
def get(): args = get_form_params() # If virtual doctype get data from controller het_list method if frappe.db.get_value("DocType", filters={"name": args.doctype}, fieldname="is_virtual"): controller = get_controller(args.doctype) data = compress(controller(args.doctype).get_list(args)) else: data = compress(execute(**args), args=args) return data
def get(): args = get_form_params() # If virtual doctype get data from controller het_list method if is_virtual_doctype(args.doctype): controller = get_controller(args.doctype) data = compress(controller(args.doctype).get_list(args)) else: data = compress(execute(**args), args=args) return data
def import_doc(docdict, force=False, data_import=False, pre_process=None, ignore_version=None, reset_permissions=False): frappe.flags.in_import = True docdict["__islocal"] = 1 controller = get_controller(docdict['doctype']) if controller and hasattr(controller, 'prepare_for_import') and callable( getattr(controller, 'prepare_for_import')): controller.prepare_for_import(docdict) doc = frappe.get_doc(docdict) doc.run_method("before_import") doc.flags.ignore_version = ignore_version if pre_process: pre_process(doc) ignore = [] if frappe.db.exists(doc.doctype, doc.name): old_doc = frappe.get_doc(doc.doctype, doc.name) if doc.doctype in ignore_values: # update ignore values for key in ignore_values.get(doc.doctype) or []: doc.set(key, old_doc.get(key)) # update ignored docs into new doc for df in doc.meta.get_table_fields(): if df.options in ignore_doctypes and not reset_permissions: doc.set(df.fieldname, []) ignore.append(df.options) # delete old frappe.delete_doc(doc.doctype, doc.name, force=1, ignore_doctypes=ignore, for_reload=True) doc.flags.ignore_children_type = ignore doc.flags.ignore_links = True if not data_import: doc.flags.ignore_validate = True doc.flags.ignore_permissions = True doc.flags.ignore_mandatory = True doc.insert() frappe.flags.in_import = False
def validate_website(self): """Ensure that website generator has field 'route'""" from frappe.model.base_document import get_controller try: controller = get_controller(self.name) except: controller = None if controller and getattr(controller, 'website', None): if not 'route' in [d.fieldname for d in self.fields]: frappe.throw('Field "route" is mandatory for Website Generator pages', title='Missing Field')
def get_list(): args = get_form_params() if is_virtual_doctype(args.doctype): controller = get_controller(args.doctype) data = controller(args.doctype).get_list(args) else: # uncompressed (refactored from frappe.model.db_query.get_list) data = execute(**args) return data
def get_sidebar_stats(stats, doctype, filters=None): if filters is None: filters = [] if is_virtual_doctype(doctype): controller = get_controller(doctype) args = {"stats": stats, "filters": filters} data = controller(doctype).get_stats(args) else: data = get_stats(stats, doctype, filters) return {"stats": data}
def get_doc(*args, **kwargs): """returns a frappe.model.Document object. :param arg1: Document dict or DocType name. :param arg2: [optional] document name. :param for_update: [optional] select document for update. There are multiple ways to call `get_doc` # will fetch the latest user object (with child table) from the database user = get_doc("User", "*****@*****.**") # create a new object user = get_doc({ "doctype":"User" "email_id": "*****@*****.**", "roles: [ {"role": "System Manager"} ] }) # create new object with keyword arguments user = get_doc(doctype='User', email_id='*****@*****.**') # select a document for update user = get_doc("User", "*****@*****.**", for_update=True) """ if args: if isinstance(args[0], BaseDocument): # already a document return args[0] elif isinstance(args[0], string_types): doctype = args[0] elif isinstance(args[0], dict): # passed a dict kwargs = args[0] else: raise ValueError('First non keyword argument must be a string or dict') if len(args) < 2 and kwargs: if 'doctype' in kwargs: doctype = kwargs['doctype'] else: raise ValueError('"doctype" is a required key') controller = get_controller(doctype) if controller: return controller(*args, **kwargs) raise ImportError(doctype)
def get_count(): args = get_form_params() if is_virtual_doctype(args.doctype): controller = get_controller(args.doctype) data = controller(args.doctype).get_count(args) else: distinct = "distinct " if args.distinct == "true" else "" args.fields = [ f"count({distinct}`tab{args.doctype}`.name) as total_count" ] data = execute(**args)[0].get("total_count") return data
def validate_naming(doc): autoname = frappe.get_meta(doctype).autoname if autoname: if autoname[0:5] == 'field': autoname = autoname[6:] elif autoname == 'naming_series:': autoname = 'naming_series' else: return True if (autoname not in doc) or (not doc[autoname]): from frappe.model.base_document import get_controller if not hasattr(get_controller(doctype), "autoname"): frappe.throw(_("{0} is a mandatory field".format(autoname))) return True
def validate_naming(doc): autoname = frappe.get_meta(doctype).autoname if autoname: if autoname[0:5] == 'field': autoname = autoname[6:] elif autoname == 'naming_series:': autoname = 'naming_series' else: return True if (autoname not in doc) or (not doc[autoname]): from frappe.model.base_document import get_controller if not hasattr(get_controller(doctype), "autoname"): frappe.throw(_("{0} is a mandatory field").format(autoname)) return True
def get_doc(*args, **kwargs): """returns a frappe.model.Document object. :param arg1: Document dict or DocType name. :param arg2: [optional] document name. There are multiple ways to call `get_doc` # will fetch the latest user object (with child table) from the database user = get_doc("User", "*****@*****.**") # create a new object user = get_doc({ "doctype":"User" "email_id": "*****@*****.**", "roles: [ {"role": "System Manager"} ] }) # create new object with keyword arguments user = get_doc(doctype='User', email_id='*****@*****.**') """ if args: if isinstance(args[0], BaseDocument): # already a document return args[0] elif isinstance(args[0], string_types): doctype = args[0] elif isinstance(args[0], dict): # passed a dict kwargs = args[0] else: raise ValueError('First non keyword argument must be a string or dict') if kwargs: if 'doctype' in kwargs: doctype = kwargs['doctype'] else: raise ValueError('"doctype" is a required key') controller = get_controller(doctype) if controller: return controller(*args, **kwargs) raise ImportError(doctype)
def update_routes(doctypes): """Patch old routing system""" for d in doctypes: frappe.reload_doctype(d) c = get_controller(d) condition = '' if c.website.condition_field: condition = 'where {0}=1'.format(c.website.condition_field) try: frappe.db.sql("""update ignore `tab{0}` set route = concat(ifnull(parent_website_route, ""), if(ifnull(parent_website_route, "")="", "", "/"), page_name) {1}""".format(d, condition)) except Exception as e: if e.args[0]!=1054: raise
def test_rename_controllers(self): """Rename doctypes with controller code paths""" # check if module exists exists; # if custom, get_controller will return Document class # if not custom, a different class will be returned self.assertNotEqual(get_controller(self.doctype.old), frappe.model.document.Document) old_doctype_path = get_doc_path("Custom", "DocType", self.doctype.old) # rename doc via wrapper API accessible via /desk frappe.rename_doc("DocType", self.doctype.old, self.doctype.new) # check if database and controllers are updated self.assertTrue(frappe.db.exists("DocType", self.doctype.new)) self.assertFalse(frappe.db.exists("DocType", self.doctype.old)) self.assertFalse(os.path.exists(old_doctype_path))
def validate_field_name_conflicts(self): """Check if field names dont conflict with controller properties and methods""" core_doctypes = [ "Custom DocPerm", "DocPerm", "Custom Field", "Customize Form Field", "DocField", ] if self.name in core_doctypes: return try: controller = get_controller(self.name) except ImportError: controller = Document available_objects = {x for x in dir(controller) if isinstance(x, str)} property_set = { x for x in available_objects if isinstance(getattr(controller, x, None), property) } method_set = { x for x in available_objects if x not in property_set and callable(getattr(controller, x, None)) } for docfield in self.get("fields") or []: if docfield.fieldtype in no_value_fields: continue conflict_type = None field = docfield.fieldname field_label = docfield.label or docfield.fieldname if docfield.fieldname in method_set: conflict_type = "controller method" if docfield.fieldname in property_set: conflict_type = "class property" if conflict_type: frappe.throw( _("Fieldname '{0}' conflicting with a {1} of the name {2} in {3}") .format(field_label, conflict_type, field, self.name) )
def import_doc( docdict, force=False, data_import=False, pre_process=None, ignore_version=None, reset_permissions=False, path=None, ): frappe.flags.in_import = True docdict["__islocal"] = 1 controller = get_controller(docdict["doctype"]) if ( controller and hasattr(controller, "prepare_for_import") and callable(getattr(controller, "prepare_for_import")) ): controller.prepare_for_import(docdict) doc = frappe.get_doc(docdict) # Note on Tree DocTypes: # The tree structure is maintained in the database via the fields "lft" and # "rgt". They are automatically set and kept up-to-date. Importing them # would destroy any existing tree structure. if getattr(doc.meta, "is_tree", None) and any([doc.lft, doc.rgt]): print('Ignoring values of `lft` and `rgt` for {} "{}"'.format(doc.doctype, doc.name)) doc.lft = None doc.rgt = None doc.run_method("before_import") doc.flags.ignore_version = ignore_version if pre_process: pre_process(doc) ignore = [] if frappe.db.exists(doc.doctype, doc.name): old_doc = frappe.get_doc(doc.doctype, doc.name) if doc.doctype in ignore_values: # update ignore values for key in ignore_values.get(doc.doctype) or []: doc.set(key, old_doc.get(key)) # update ignored docs into new doc for df in doc.meta.get_table_fields(): if df.options in ignore_doctypes and not reset_permissions: doc.set(df.fieldname, []) ignore.append(df.options) # delete old frappe.delete_doc(doc.doctype, doc.name, force=1, ignore_doctypes=ignore, for_reload=True) doc.flags.ignore_children_type = ignore doc.flags.ignore_links = True if not data_import: doc.flags.ignore_validate = True doc.flags.ignore_permissions = True doc.flags.ignore_mandatory = True doc.insert() frappe.flags.in_import = False
def rebuild_for_doctype(doctype): '''Rebuild entries of doctype's documents in __global_search on change of searchable fields :param doctype: Doctype ''' def _get_filters(): filters = frappe._dict({ "docstatus": ["!=", 2] }) if meta.has_field("enabled"): filters.enabled = 1 if meta.has_field("disabled"): filters.disabled = 0 return filters meta = frappe.get_meta(doctype) if cint(meta.istable) == 1: parent_doctypes = frappe.get_all("DocField", fields="parent", filters={ "fieldtype": "Table", "options": doctype }) for p in parent_doctypes: rebuild_for_doctype(p.parent) return # Delete records delete_global_search_records_for_doctype(doctype) parent_search_fields = meta.get_global_search_fields() fieldnames = get_selected_fields(meta, parent_search_fields) # Get all records from parent doctype table all_records = frappe.get_all(doctype, fields=fieldnames, filters=_get_filters()) # Children data all_children, child_search_fields = get_children_data(doctype, meta) all_contents = [] for doc in all_records: content = [] for field in parent_search_fields: value = doc.get(field.fieldname) if value: content.append(get_formatted_value(value, field)) # get children data for child_doctype, records in all_children.get(doc.name, {}).items(): for field in child_search_fields.get(child_doctype): for r in records: if r.get(field.fieldname): content.append(get_formatted_value(r.get(field.fieldname), field)) if content: # if doctype published in website, push title, route etc. published = 0 title, route = "", "" try: if hasattr(get_controller(doctype), "is_website_published") and meta.allow_guest_to_view: d = frappe.get_doc(doctype, doc.name) published = 1 if d.is_website_published() else 0 title = d.get_title() route = d.get("route") except ImportError: # some doctypes has been deleted via future patch, hence controller does not exists pass all_contents.append({ "doctype": frappe.db.escape(doctype), "name": frappe.db.escape(doc.name), "content": frappe.db.escape(' ||| '.join(content or '')), "published": published, "title": frappe.db.escape(title or ''), "route": frappe.db.escape(route or '') }) if all_contents: insert_values_for_multiple_docs(all_contents)