Python手动查询构建:如何在列表推导中的MySQL where子句构建中转义字符串?
我正在用Django搭建一个网站,但我不能使用Django的ORM(对象关系映射),因为它不支持用户动态选择的多个数据库之间的连接。如果可以的话,我真希望能用上。
现在我只能手动构建查询,看看我用列表推导式做的这个小把戏:
def buildQuery(self, pagedata, num_per_page) :
given_fields = {k:v for k,v in self.entity.FIELDS.items() if k in pagedata.iterkeys()}
where_clauses = [(given_fields[k] % pagedata) for k in given_fields if pagedata[k].strip() != '']
if where_clauses:
self.queryparts['whereclause'] = 'WHERE ' + ' AND '.join(where_clauses)
else:
self.queryparts['whereclause'] = ''
if pagedata.get('sort_by', '1') != '':
self.queryparts['sortby'] = 'ORDER BY %s %s' % (pagedata.get('sort_by','1'), pagedata.get('sort_dir','asc'))
else:
self.queryparts['sortby'] = ''
self.queryparts ['limit'] = 'LIMIT ' + self.buildLimit(pagedata.get('page',1), num_per_page)
return self.entity.QUERY % self.queryparts
上面的代码是从页面的GET字段和类字段中找交集。一个示例“实体”看起来像这样:
class event:
FIELDS = {'keyword': "(rmt.title LIKE '%(keyword)s' OR rmt.episode_name LIKE '%(keyword)s') ",
'service_name': "(s.short_name LIKE '%(service_name)s' OR rch.aliases LIKE '%(service_name)s')",
'puid': "ime.program_unique_id LIKE '%(puid)s%%'",
'ims_theme': "",
'content_type': "rmt.types IN ('%(content_type)s')",
'genre': "rmt.genres LIKE ('%(genre)s')",
'service_uid': "s.service_uid IN (%(service_uid)s)"}
QUERY = '''SELECT rme.image_path image, rmt.title title, ime.program_unique_id PUID, s.short_name service_name, s.service_id sid, ime.begin_time, ime.ims_event_id FROM %(imsdb)s.service s JOIN %(imsdb)s.event ime ON ime.service_uid = s.service_uid LEFT JOIN %(rmsdb)s.event rme ON ime.eit_id = rme.event_id AND rme.service_uid = ime.service_uid LEFT JOIN %(rmsdb)s.text_data rmt ON rmt.text_id = rme.text_id LEFT JOIN %(rmsdb)s.channellogo rch ON rch.suid = s.service_uid %(whereclause)s %(sortby)s %(limit)s'''
我唯一遇到的问题是这一行:
where_clauses = [(given_fields[k] % pagedata) for k in given_fields if pagedata[k].strip() != '']
我该如何处理字段中的撇号?
在可预见的未来,数据库将始终使用MySQL。
为了更完整地说明这是如何“使用”的,这就是我的Django视图的样子:
def index(request):
cursor = connection.cursor()
q = QueryBuilder(entity=QueryBuilder.event, rmsdb=sources.getCurrentRMSDB(request), imsdb=sources.getCurrentIMSDB(request))
SQL = q.buildQuery(request.GET, num_per_page)
return HttpResponse(SQL)
cursor.execute(SQL)
return render(request, 'rma/event.html', {'results' : dictfetchall(cursor)})
1 个回答
0
这个问题大家都知道,解决方法在PEP249里有说明:连接模块的paramstyle
定义了如何传递字符串,而不需要手动处理转义字符。一般来说,MySQL的驱动程序中,paramstyle
是"qmark"
,但它也能理解pyformat
的格式。
你也可以手动格式化这些字符串常量,不过由于SQL的特殊性,这个方法很依赖于具体的数据库管理系统(DBMS)。