So, I’m working on a script that maps tables stored in a SQL Express database to DocTypes, which the script creates if they don’t exist yet (or updates if they do).
Now, I need to know how to make sure that the script works with the currently running site.
Here’s the problem, fellas: so, I’ve been encountering an error that occurs when the interpreter hits the line that calls and passes a dictionary object to frappe.get_doc. The error, the traceback for which I’ll provide later once I’ll be on the computer, is RuntimeError('no object bound to %s' % self.__name__)
According to one source, “associating” the script with your site should solve the problem like so:
frappe.init_site(sitename) frappe.connect()
Sadly, of course, this doesn’t work for me. I get some error that says AttributeError: conf.
Please help. I have invested so much this and want my family to be happy, including kids who aren’t even mine (I forgive you, Hannah…)
Alright. Let me wipe the snot off my sleeve and think about something good for once—like someone being nice enough to come here and save the day for some erratic stranger who seems to be unable to do something as simple as map data together. Jesus Lord Mother of God have mercy…
Alright, so the AttributeError is gone (for now)… At the beginning of the file I have frappe.init_site('frappe.local.erptest')
When I run the script, which I’ll paste once I’m on my computer, I get that pesky “no object bound to db” error again, and the traceback starts with the line that calls get_doc.
What’s really goddamned weird is that when I call frappe.connect(‘frappe.local.erptest’), I’m told that the site doesn’t exist (even though there are no complaints about init_site). Interesting…
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "sql2doctype.py", line 49, in sync
add_doc(fields)
File "sql2doctype.py", line 17, in add_doc
doc = frappe.get_doc(fields, fields['LAST_NAME'])
File "/home/vongol/frappe-bench/apps/frappe/frappe/__init__.py", line 622, in get_doc
return frappe.model.document.get_doc(arg1, arg2)
File "/home/vongol/frappe-bench/apps/frappe/frappe/model/document.py", line 49, in get_doc
controller = get_controller(doctype)
File "/home/vongol/frappe-bench/apps/frappe/frappe/model/base_document.py", line 29, in get_controller
module_name, custom = frappe.db.get_value("DocType", doctype, ["module", "custom"]) \
File "/home/vongol/frappe-bench/env/local/lib/python2.7/site-packages/werkzeug/local.py", line 347, in __getattr__
return getattr(self._get_current_object(), name)
File "/home/vongol/frappe-bench/env/local/lib/python2.7/site-packages/werkzeug/local.py", line 310, in _get_current_object
raise RuntimeError('no object bound to %s' % self.__name__)
RuntimeError: no object bound to db
And here’s what happens when I try to “solve” that “no object bound to db” problem by including frappe.connect() at the beginning of the script:
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "sql2doctype.py", line 6, in <module>
frappe.connect()
File "/home/vongol/frappe-bench/apps/frappe/frappe/__init__.py", line 170, in connect
local.db = Database(user=db_name or local.conf.db_name)
File "/home/vongol/frappe-bench/env/local/lib/python2.7/site-packages/werkzeug/local.py", line 72, in __getattr__
raise AttributeError(name)
AttributeError: conf
import frappe
from frappe.model.document import Document
import pyodbc
frappe.init_site('frappe.local.test')
frappe.connect()
### Initialize connection and cursor ###
cnxn = pyodbc.connect('DRIVER={ODBC Driver 13 For SQL Server}; SERVER=localhost; DATABASE=testdb; UID=SA; PWD=xyzzy209!')
cursor = cnxn.cursor()
### Query functions ###
# Add a DocType by passing a dictionary to the get_doc function.
def add_doc(fields):
doc = frappe.get_doc(fields, fields['LAST_NAME'])
doc.insert()
# "Synchronize" function. Maps SQL data in table to DocTypes, adding new DocTypes and/or upgrading them when applicable.
def sync(query):
#query = 'SELECT * FROM \"%s\"' % table
#cursor.execute(query, table)
cursor.execute(query)
doctypes = []
records = []
columns = [column[0] for column in cursor.description]
# Iterate through each row and pass a dictionary containing its column names as keys and respective values to add_doc.
# Use id field to designate each SQL table and ease searching and updating.
for row in cursor.fetchall():
count = 0
fields = (dict(zip(columns, row)))
'''
if doctypes is not None:
for doctype in doctypes:
if fields["ID"] == doctype["ID"] and fields != doctype:
for field in fields:
doc_field = getattr(doctype, field)
db_field = fields[field]
if doc_field != db_field:
pass
else:
'''
add_doc(fields)
count += 1
print("Added %d doc" % count)
So, I managed to finally circumvent this problem by figuring out how to execute the script via bench. But, since frappe is no fun without constant errors around every corner, I gotta deal with a new AttributeError: