简体   繁体   English

我需要在Google Appengine中使用交易吗

[英]Do I need to use transactions in google appengine

update 0 My def post() code has changed dramatically because originally it was base on a digital form which included both checkboxes and text entry fields, not just text entry fields, which is the current design to be more paper-like. 更新0我的def post()代码发生了巨大变化,因为它最初是基于数字形式的,它既包含复选框又包含文本输入字段,而不仅仅是文本输入字段,而当前的设计更像纸张。 However, as a result I have other problems which may be solved by one of the proposed solutions, but I cannot exactly follow that proposed solution, so let me try to explain new design and the problems. 但是,结果,我还有一个其他问题可以通过建议的解决方案之一解决,但是我不能完全遵循该建议的解决方案,所以让我尝试解释一下新的设计和问题。

The smaller problem is the inefficiency of my implementation because in the def post() I create a distinct name for each input timeslot which is a long string <courtname><timeslotstarthour><timeslotstartminute> . 较小的问题是我的实现效率低下,因为在def post()我为每个输入时隙创建了一个不同的name ,该name是一个长字符串<courtname><timeslotstarthour><timeslotstartminute> In my code this name is read in a nested for loop with the following snippet [very inefficient, I imagine]. 在我的代码中,此name是在嵌套的for循环中读取的,其中包含以下代码段(我想这效率很低)。

tempreservation=courtname+str(time[0])+str(time[1])
name = self.request.get('tempreservation',None)

The more serious immediate problem is that my def post() code is never read and I cannot figure out why (and maybe it wasn't being read before, either, but I had not tested that far). 更为严重的紧迫问题是,我的def post()代码从未被读取,而且我也无法弄清楚为什么(也许以前也没有被读取,但是我还没有进行过如此广泛的测试)。 I wonder if the problem is that for now I want both the post and the get to "finish" the same way. 我想知道问题是否在于现在我是否希望职位和职位都以相同的方式“完成”。 The first line below is for the post() and the second is for the get(). 下面的第一行用于post(),第二行用于get()。

return webapp2.redirect("/read/%s" % location_id)
self.render_template('read.html', {'courts': courts,'location': location, ... etc ...}

My new post() is as follows. 我的新post()如下。 Notice I have left in the code the logging.info to see if I ever get there. 注意,我在代码中保留了logging.info以查看是否到达那里。

class MainPageCourt(BaseHandler):

    def post(self, location_id):
        logging.info("in MainPageCourt post  ")
        startTime = self.request.get('startTime')
        endTime = self.request.get('endTime')
        day = self.request.get('day')
        weekday = self.request.get('weekday')
        nowweekday = self.request.get('nowweekday')
        year = self.request.get('year')
        month = self.request.get('month')
        nowmonth = self.request.get('nowmonth')
        courtnames = self.request.get_all('court')
        for c in courtnames:
            logging.info("courtname: %s " % c)
        times=intervals(startTime,endTime)
        for courtname in courtnames:
            for time in times:
                tempreservation=courtname+str(time[0])+str(time[1])
                name = self.request.get('tempreservation',None)
                if name:
                    iden = courtname
                    court = db.Key.from_path('Locations',location_id,'Courts', iden)
                    reservation = Reservations(parent=court) 
                    reservation.name = name
                    reservation.starttime = time
                    reservation.year = year
                    reservation.nowmonth = int(nowmonth)
                    reservation.day = int(day)
                    reservation.nowweekday = int(nowweekday)
                    reservation.put()
        return webapp2.redirect("/read/%s" % location_id)

Eventually I want to add checking/validating to the above get() code by comparing the existing Reservations data in the datastore with the implied new reservations, and kick out to an alert which tells the user of any potential problems which she can address. 最终,我想通过将数据存储区中的现有Reservations数据与隐含的新保留进行比较,来对上述get()代码进行检查/验证,并踢出一个警报,告知用户她可以解决的任何潜在问题。

I would also appreciate any comments on these two problems. 对于这两个问题的任何评论,我也将不胜感激。

end of update 0 更新结束0

My app is for a community tennis court. 我的应用程序用于社区网球场。 I want to replace the paper sign up sheet with an online digital sheet that mimics a paper sheet. 我想用模拟纸页的在线数字纸代替纸注册纸。 As unlikely as it seems there may be "transactional" conflicts where two tennis appointments collide. 看起来不太可能发生两次网球约会相撞的“交易”冲突。 So how do I give the second appointment maker a heads up to the conflict but also give the successful party the opportunity to alter her appointment like she would on paper (with an eraser). 因此,我该如何让第二位约会制作者直面冲突,又如何让成功的聚会有机会像在纸上(用橡皮擦)那样更改约会。

Each half hour is a time slot on the form. 每半小时是表格上的一个时隙。 People normally sign up for multiple half hours at one time before "submitting". 人们通常在“提交”之前一次注册多个半小时。

So in my code within a loop I do a get_all. 因此,在循环代码中,我执行了get_all。 If any get succeeds I want to give the user control over whether to accept the put() or not. 如果任何获取成功,我想让用户控制是否接受put()。 I am still thinking the put() would be an all or nothing, not selective. 我仍然认为put()是全有还是全无,不是选择性的。

So my question is, do I need to make part of the code use an explicit "transaction"? 所以我的问题是,我是否需要使代码的一部分使用显式的“事务”?

class MainPageCourt(BaseHandler):

    def post(self, location_id):
        reservations = self.request.get_all('reservations')
        day = self.request.get('day')
        weekday = self.request.get('weekday')
        nowweekday = self.request.get('nowweekday')
        year = self.request.get('year')
        month = self.request.get('month')
        nowmonth = self.request.get('nowmonth')
        if not reservations:
            for r in reservations:
                r=r.split()
                iden = r[0]
                temp = iden+' '+r[1]+' '+r[2]
                court = db.Key.from_path('Locations',location_id,'Courts', iden)
                reservation = Reservations(parent=court) 
                reservation.starttime = [int(r[1]),int(r[2])]
                reservation.year = int(r[3])
                reservation.nowmonth = int(r[4])
                reservation.day = int(r[5])
                reservation.nowweekday = int(nowweekday)
                reservation.name = self.request.get(temp)
                reservation.put()
            return webapp2.redirect("/read/%s" % location_id)
        else:
            ... this important code is not written, pending ...
            return webapp2.redirect("/adjust/%s" % location_id)

You can check for the availability of the time slots in a given Court , and write the corresponding Reservations child entities only if their stat_time don't conflict. 您可以检查给定Court时隙的可用性,并仅在其stat_time不冲突时编写相应的Reservations子实体。

Here is how you would do it for 1 single reservation using a ancestor Query: 这是使用祖先查询进行1次单个预订的方法:

@ndb.transactional
def make_reservation(court_id, start_time):
  court = Court(id=court_id)
  existing = Reservation.query(Reservation.start_time == start_time,
                               ancestor=court.key).fetch(2, keys_only=True)
  if len(existing):
    return False, existing[0]
  return True, Reservation(start_time=start_time, parent=court.key).put()

Alternativly, if you make the slot part of the Reservation id, you can remove the query and construct the Reservation entity keys to check if they already exists: 或者,如果将插槽作为保留标识的一部分,则可以删除查询并构造保留实体键以检查它们是否已存在:

@ndb.transactional
def make_reservations(court_id, slots): 
  court = Court(id=court_id)
  rs = [Reservation(id=s, parent=court.key) for s in slots]
  existing = ndb.get_multi(r.key for r in rs)
  if any(existing):
    return False, existing
  return True, ndb.put_multi(rs)

I think you should always use transactions, but I don't think your concerns are best addressed by transactions. 我认为您应该始终使用事务,但是我认为事务不能最好地解决您的顾虑。

I think you should implement a two-stage reservation system - which is what you see on most shopping bags and ticketing companies. 我认为您应该实施两阶段的预订系统-这是大多数购物袋和票务公司所看到的。

  1. Posting the form creates a "reservation request" , which blocks out the time(s) as "in someone else's shopping bag" for 5-15 minutes 发布表格会创建一个“预订请求”,将“在其他人的购物袋中”的时间限制为5-15分钟
  2. Users must submit again on an approval screen to confirm the times. 用户必须在批准屏幕上再次提交以确认时间。 You can give them the ability to update the conflicts on that screen too, and reset the 'reservation lock' on the timeslots as long as possible. 您也可以使他们能够更新该屏幕上的冲突,并尽可能长地重置时隙上的“保留锁定”。
  3. A cronjob - or a faked one that is triggered by a request coming in at a certain window - clears out expired reservation locks and returns the times back to the pool of available slots. 一项cronjob(或由在某个窗口进入的请求触发的伪造的cronjob)会清除过期的预留锁,并将时间返回到可用插槽池。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用适用于Google Appengine的Python SDK? - How do I use the Python SDK for Google Appengine? 如何在Google AppEngine的djangoforms.ModelForm中使用ListProperty(users.user)? - How do I use a ListProperty(users.user) in a djangoforms.ModelForm on Google AppEngine? 在AppEngine项目之外使用Google AppEngine数据存储区 - Use Google AppEngine datastore outside of AppEngine project 如何在Google AppEngine中导入AST模块 - How do i import ast module in google appengine 如何在Google Appengine,Python中调用请求处理程序 - How do I call request handler in google appengine, python 如何在google appengine / python上为模型大量分配属性? - How do I mass assign attributes to model on google appengine / python? 我如何在Google Appengine应用程序的数据库中验证用户(任何人都可以推荐对Google Appengine应用程序进行用户身份验证的最佳方法)? - How do i verify user in database in google appengine app ( can anyone recommend the best way to do user authentication for google appengine app)? 我需要使用模拟吗? - Do I need to use mocks? 可以在Google AppEngine上使用django Piston吗? - Is it possible to use django Piston on Google AppEngine? 如何在Google AppEngine上进行反向引用? - How to do a back-reference on Google AppEngine?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM