python列表神秘地设置为django/活塞处理程序中的某些内容
注意:(从前两条建议开始,我已经更新了这篇文章……你可以在这里查看txt格式的旧文章:)。我所做的更新是为了更好地了解出了什么问题——现在我至少知道发生了什么,但我不知道如何修复它 无论如何,使用Django和活塞,我已经建立了一个名为BaseApiHandler的新BaseHandler类,它完成了我在所有处理程序中所做的大部分工作。这非常有效,直到我添加了限制应用于结果的过滤器的功能(例如“仅提供第一个结果”) 示例(必须删除):“因为我无法提交更多URL): -http//localhost/api/hours\u detail/empid/22提供了员工#22中的所有hours\u detail行 -http//localhost/api/hours\u detail/empid/22/limit/first提供了employee#22中的第一个hours\u detail行 发生的情况是,当我连续运行/limit/first几次时,第一个示例就被破坏了,假装它是/limit/url,而不是 现在我正在存储它是否是一个限制以及限制在一个新类中是什么-在这个stackoverflow编辑之前,我只是使用一个包含两个条目的列表(初始化时限制=[],设置时限制=[0,1])。在此stackoverflow编辑之前,一旦您发送垃圾邮件/limit/first,当转到第一个示例时,“limit”将被预先设置为[0,1],然后处理程序将因此限制查询。使用我添加的调试数据,我可以肯定地说列表是预先设置的,在代码执行期间没有设置 我正在将调试信息添加到响应中,以便查看发生了什么。现在,当您第一次询问示例1的url时,您会得到以下正确的statusmsg响应:python列表神秘地设置为django/活塞处理程序中的某些内容,python,django,django-piston,Python,Django,Django Piston,注意:(从前两条建议开始,我已经更新了这篇文章……你可以在这里查看txt格式的旧文章:)。我所做的更新是为了更好地了解出了什么问题——现在我至少知道发生了什么,但我不知道如何修复它 无论如何,使用Django和活塞,我已经建立了一个名为BaseApiHandler的新BaseHandler类,它完成了我在所有处理程序中所做的大部分工作。这非常有效,直到我添加了限制应用于结果的过滤器的功能(例如“仅提供第一个结果”) 示例(必须删除):“因为我无法提交更多URL): -http//localhos
"statusmsg": "2 hours_detail found with query: {'empid':'22','datestamp':'2009-03-02',}",
"statusmsg": "1 hours_detail found with query: {'empid':'22','datestamp':'2009-03-02','limit','first',with limit[0,1](limit,None... limit set 1 times),}",
当您询问示例2的url时,您会得到以下正确的statusmsg响应:
"statusmsg": "2 hours_detail found with query: {'empid':'22','datestamp':'2009-03-02',}",
"statusmsg": "1 hours_detail found with query: {'empid':'22','datestamp':'2009-03-02','limit','first',with limit[0,1](limit,None... limit set 1 times),}",
但是,如果刷新多次,限制集的值开始增加(我的一个朋友建议增加这个值,看看这个变量是否以某种方式保持不变)
一旦该数字超过“1倍”,您就可以开始尝试获取示例1的url。现在每次刷新示例1,都会得到奇怪的结果。下面是来自不同刷新的3条不同状态消息(注意,在islimit的实际值徘徊在8和10之间时,kwarg的调试输出中正确地缺少了每一条“limit”:“first”:
因此,该对象似乎正在被缓存。在将“limit”从一个列表更改为一个类之前,“limit”的列表版本似乎也被缓存了,因为在转到示例2的url之后,我有时会将[0,1]作为限制
以下是更新后的代码片段(请记住,您可以在此处查看第一篇帖子:bennyland.com/old-2554127.txt)
url.PY-在“urlpatterns=patterns”中('
#hours\u detail/id/{id}/empid/{empid}/projid/{projid}/datestamp/{datestamp}/daterange/{fromdate}到{todate}
#empid是必需的
url(r'^api/hours\u detail/(?:')+\
r'(?:[/]?id/(?P\d+)))'+\
r'(?:[/]?empid/(?P\d+)))'+\
r'(?:[/]?项目/(?P\d+)))'+\
r'(?:[/]?日期戳/(?P\d{4,}[-/\.]\d{2,}[-/\.]\d{2,}))?'\
r'(?:[/]?daterange/(?:\d{4,}[-/\.]\d{2,}[-/\.]\d{2,})(?:to{124;/-)(?:\ d{4,}[-/\.]\d{2,}[-/\.]\d{2,}))?+\
r')+'+\
r'(?:/limit/(?P(?:first | last)))?'+\
r'(?:/(?Pexact))?$,小时数/详细信息/资源),
1.PY
class ResponseLimit(object):
def __init__(self):
self._min = 0
self._max = 0
self._islimit = 0
@property
def min(self):
if self.islimit == 0:
raise LookupError("trying to access min when no limit has been set")
return self._min
@property
def max(self):
if self.islimit == 0:
raise LookupError("trying to access max when no limit has been set")
return self._max
@property
def islimit(self):
return self._islimit
def setlimit(self, min, max):
self._min = min
self._max = max
# incrementing _islimit instead of using a bool so I can try and see why it's broken
self._islimit += 1
class BaseApiHandler(BaseHandler):
limit = ResponseLimit()
def __init__(self):
self._post_name = 'base'
@property
def post_name(self):
return self._post_name
@post_name.setter
def post_name(self, value):
self._post_name = value
def process_kwarg_read(self, key, value, d_post, b_exact):
"""
this should be overridden in the derived classes to process kwargs
"""
pass
# override 'read' so we can better handle our api's searching capabilities
def read(self, request, *args, **kwargs):
d_post = {'status':0,'statusmsg':'Nothing Happened'}
try:
# setup the named response object
# select all employees then filter - querysets are lazy in django
# the actual query is only done once data is needed, so this may
# seem like some memory hog slow beast, but it's actually not.
d_post[self.post_name] = self.queryset(request)
s_query = ''
b_exact = False
if 'exact' in kwargs and kwargs['exact'] <> None:
b_exact = True
s_query = '\'exact\':True,'
for key,value in kwargs.iteritems():
# the regex url possibilities will push None into the kwargs dictionary
# if not specified, so just continue looping through if that's the case
if value is None or key == 'exact':
continue
# write to the s_query string so we have a nice error message
s_query = '%s\'%s\':\'%s\',' % (s_query, key, value)
# now process this key/value kwarg
self.process_kwarg_read(key=key, value=value, d_post=d_post, b_exact=b_exact)
# end of the kwargs for loop
else:
if self.limit.islimit > 0:
s_query = '%swith limit[%s,%s](limit,%s... limit set %s times),' % (s_query, self.limit.min, self.limit.max, kwargs['limit'],self.limit.islimit)
d_post[self.post_name] = d_post[self.post_name][self.limit.min:self.limit.max]
if d_post[self.post_name].count() == 0:
d_post['status'] = 0
d_post['statusmsg'] = '%s not found with query: {%s}' % (self.post_name, s_query)
else:
d_post['status'] = 1
d_post['statusmsg'] = '%s %s found with query: {%s}' % (d_post[self.post_name].count(), self.post_name, s_query)
except:
e = sys.exc_info()[1]
d_post['status'] = 0
d_post['statusmsg'] = 'error: %s %s' % (e, traceback.format_exc())
d_post[self.post_name] = []
return d_post
class HoursDetailHandler(BaseApiHandler):
#allowed_methods = ('GET', 'PUT', 'POST', 'DELETE',)
model = HoursDetail
exclude = ()
def __init__(self):
BaseApiHandler.__init__(self)
self._post_name = 'hours_detail'
def process_kwarg_read(self, key, value, d_post, b_exact):
# each query is handled slightly differently... when keys are added
# handle them in here. python doesn't have switch statements, this
# could theoretically be performed using a dictionary with lambda
# expressions, however I was affraid it would mess with the way the
# filters on the queryset work so I went for the less exciting
# if/elif block instead
# querying on a specific row
if key == 'id':
d_post[self.post_name] = d_post[self.post_name].filter(pk=value)
# filter based on employee id - this is guaranteed to happen once
# per query (see read(...))
elif key == 'empid':
d_post[self.post_name] = d_post[self.post_name].filter(emp__id__exact=value)
# look for a specific project by id
elif key == 'projid':
d_post[self.post_name] = d_post[self.post_name].filter(proj__id__exact=value)
elif key == 'datestamp' or key == 'daterange':
d_from = None
d_to = None
# first, regex out the times in the case of range vs stamp
if key == 'daterange':
m = re.match('(?P<daterangefrom>\d{4,}[-/\.]\d{2,}[-/\.]\d{2,})(?:to|/-)(?P<daterangeto>\d{4,}[-/\.]\d{2,}[-/\.]\d{2,})', \
value)
d_from = datetime.strptime(m.group('daterangefrom'), '%Y-%m-%d')
d_to = datetime.strptime(m.group('daterangeto'), '%Y-%m-%d')
else:
d_from = datetime.strptime(value, '%Y-%m-%d')
d_to = datetime.strptime(value, '%Y-%m-%d')
# now min/max to get midnight on day1 through just before midnight on day2
# note: this is a hack because as of the writing of this app,
# __date doesn't yet exist as a queryable field thus any
# timestamps not at midnight were incorrectly left out
d_from = datetime.combine(d_from, time.min)
d_to = datetime.combine(d_to, time.max)
d_post[self.post_name] = d_post[self.post_name].filter(clock_time__gte=d_from)
d_post[self.post_name] = d_post[self.post_name].filter(clock_time__lte=d_to)
elif key == 'limit':
order_by = 'clock_time'
if value == 'last':
order_by = '-clock_time'
d_post[self.post_name] = d_post[self.post_name].order_by(order_by)
self.limit.setlimit(0, 1)
else:
raise NameError
def read(self, request, *args, **kwargs):
# empid is required, so make sure it exists before running BaseApiHandler's read method
if not('empid' in kwargs and kwargs['empid'] <> None and kwargs['empid'] >= 0):
return {'status':0,'statusmsg':'empid cannot be empty'}
else:
return BaseApiHandler.read(self, request, *args, **kwargs)
类响应限制(对象):
定义初始化(自):
自最小值=0
自身最大值=0
self.\u islimit=0
@财产
def最小值(自身):
如果self.islimit==0:
raise LookupError(“未设置限制时尝试访问最小值”)
返回自我。\u min
@财产
def最大值(自身):
如果self.islimit==0:
raise LookupError(“未设置限制时尝试访问max”)
返回自我。\u max
@财产
def islimit(自我):
返回自我限制
def设置限制(自身、最小值、最大值):
自。_min=min
自身最大值=最大值
#递增,而不是使用bool,这样我就可以试着看看它为什么会坏
自我限制+=1
类BaseApiHandler(BaseHandler):
限制=响应限制()
定义初始化(自):
self.\u post\u name='base'
@财产
def post_名称(自身):
返回自我。\u帖子\u姓名
@post_name.setter
def post_名称(自身、值):
self.\u post\u name=值
def过程读取(自身、键、值、d_post、b_精确):
"""
这应该在派生类中重写以处理KWARG
"""
通过
#重写“读取”,以便更好地处理api的搜索功能
def读取(自身、请求、*args、**kwargs):
d_post={'status':0,'statusmsg':'Nothing'
尝试:
#设置命名的响应对象
#选择所有员工,然后筛选-查询集在django中是惰性的
#实际查询只在需要数据时执行,因此这可能会导致
#看起来像是个慢性子,但实际上不是。
d_post[self.post_name]=self.queryset(请求)
s_查询=“”
b_精确=错误
如果kwargs中的“精确”和kwargs[“精确”]无:
b_精确=真
s_query='\'精确\':True,'
对于键,使用kwargs.iteritems()表示的值:
#正则表达式url可能不会将任何内容推入kwargs字典
#如果没有指定,那么继续循环
如果值为None或key==“精确”:
持续
#写入s_查询字符串,这样我们就有了一条很好的错误消息
SU查询='%s\'%s\':\'%s\','%(SU查询,键,值)
#现在处理这个键/值
class ResponseLimit(object):
def __init__(self):
self._min = 0
self._max = 0
self._islimit = 0
@property
def min(self):
if self.islimit == 0:
raise LookupError("trying to access min when no limit has been set")
return self._min
@property
def max(self):
if self.islimit == 0:
raise LookupError("trying to access max when no limit has been set")
return self._max
@property
def islimit(self):
return self._islimit
def setlimit(self, min, max):
self._min = min
self._max = max
# incrementing _islimit instead of using a bool so I can try and see why it's broken
self._islimit += 1
class BaseApiHandler(BaseHandler):
limit = ResponseLimit()
def __init__(self):
self._post_name = 'base'
@property
def post_name(self):
return self._post_name
@post_name.setter
def post_name(self, value):
self._post_name = value
def process_kwarg_read(self, key, value, d_post, b_exact):
"""
this should be overridden in the derived classes to process kwargs
"""
pass
# override 'read' so we can better handle our api's searching capabilities
def read(self, request, *args, **kwargs):
d_post = {'status':0,'statusmsg':'Nothing Happened'}
try:
# setup the named response object
# select all employees then filter - querysets are lazy in django
# the actual query is only done once data is needed, so this may
# seem like some memory hog slow beast, but it's actually not.
d_post[self.post_name] = self.queryset(request)
s_query = ''
b_exact = False
if 'exact' in kwargs and kwargs['exact'] <> None:
b_exact = True
s_query = '\'exact\':True,'
for key,value in kwargs.iteritems():
# the regex url possibilities will push None into the kwargs dictionary
# if not specified, so just continue looping through if that's the case
if value is None or key == 'exact':
continue
# write to the s_query string so we have a nice error message
s_query = '%s\'%s\':\'%s\',' % (s_query, key, value)
# now process this key/value kwarg
self.process_kwarg_read(key=key, value=value, d_post=d_post, b_exact=b_exact)
# end of the kwargs for loop
else:
if self.limit.islimit > 0:
s_query = '%swith limit[%s,%s](limit,%s... limit set %s times),' % (s_query, self.limit.min, self.limit.max, kwargs['limit'],self.limit.islimit)
d_post[self.post_name] = d_post[self.post_name][self.limit.min:self.limit.max]
if d_post[self.post_name].count() == 0:
d_post['status'] = 0
d_post['statusmsg'] = '%s not found with query: {%s}' % (self.post_name, s_query)
else:
d_post['status'] = 1
d_post['statusmsg'] = '%s %s found with query: {%s}' % (d_post[self.post_name].count(), self.post_name, s_query)
except:
e = sys.exc_info()[1]
d_post['status'] = 0
d_post['statusmsg'] = 'error: %s %s' % (e, traceback.format_exc())
d_post[self.post_name] = []
return d_post
class HoursDetailHandler(BaseApiHandler):
#allowed_methods = ('GET', 'PUT', 'POST', 'DELETE',)
model = HoursDetail
exclude = ()
def __init__(self):
BaseApiHandler.__init__(self)
self._post_name = 'hours_detail'
def process_kwarg_read(self, key, value, d_post, b_exact):
# each query is handled slightly differently... when keys are added
# handle them in here. python doesn't have switch statements, this
# could theoretically be performed using a dictionary with lambda
# expressions, however I was affraid it would mess with the way the
# filters on the queryset work so I went for the less exciting
# if/elif block instead
# querying on a specific row
if key == 'id':
d_post[self.post_name] = d_post[self.post_name].filter(pk=value)
# filter based on employee id - this is guaranteed to happen once
# per query (see read(...))
elif key == 'empid':
d_post[self.post_name] = d_post[self.post_name].filter(emp__id__exact=value)
# look for a specific project by id
elif key == 'projid':
d_post[self.post_name] = d_post[self.post_name].filter(proj__id__exact=value)
elif key == 'datestamp' or key == 'daterange':
d_from = None
d_to = None
# first, regex out the times in the case of range vs stamp
if key == 'daterange':
m = re.match('(?P<daterangefrom>\d{4,}[-/\.]\d{2,}[-/\.]\d{2,})(?:to|/-)(?P<daterangeto>\d{4,}[-/\.]\d{2,}[-/\.]\d{2,})', \
value)
d_from = datetime.strptime(m.group('daterangefrom'), '%Y-%m-%d')
d_to = datetime.strptime(m.group('daterangeto'), '%Y-%m-%d')
else:
d_from = datetime.strptime(value, '%Y-%m-%d')
d_to = datetime.strptime(value, '%Y-%m-%d')
# now min/max to get midnight on day1 through just before midnight on day2
# note: this is a hack because as of the writing of this app,
# __date doesn't yet exist as a queryable field thus any
# timestamps not at midnight were incorrectly left out
d_from = datetime.combine(d_from, time.min)
d_to = datetime.combine(d_to, time.max)
d_post[self.post_name] = d_post[self.post_name].filter(clock_time__gte=d_from)
d_post[self.post_name] = d_post[self.post_name].filter(clock_time__lte=d_to)
elif key == 'limit':
order_by = 'clock_time'
if value == 'last':
order_by = '-clock_time'
d_post[self.post_name] = d_post[self.post_name].order_by(order_by)
self.limit.setlimit(0, 1)
else:
raise NameError
def read(self, request, *args, **kwargs):
# empid is required, so make sure it exists before running BaseApiHandler's read method
if not('empid' in kwargs and kwargs['empid'] <> None and kwargs['empid'] >= 0):
return {'status':0,'statusmsg':'empid cannot be empty'}
else:
return BaseApiHandler.read(self, request, *args, **kwargs)
s_query = '%swith limit[%s,%s](limit,%s > traceback:%s),' %
(s_query, self.limit[0], self.limit[1], kwargs['limit'],
self.limit[2])
if self.has_limit():
s_query += 'with limit[%s,%s]' % self.limit[0:1]
if 'limit' in kwargs and len(self.limit) > 2:
s_query += '(limit,%s > traceback:%s),' %
(kwargs['limit'], self.limit[2])
def get_limit(self):
return self._limit[:]