0

update 0def post()元はテキスト入力フィールドだけでなく、チェックボックスとテキスト入力フィールドの両方を含むデジタルフォームに基づいていたため、 私のコードは劇的に変更されました。現在のデザインはより紙に似ています。ただし、結果として、提案された解決策の 1 つによって解決される可能性のある他の問題がありますが、その提案された解決策を正確に実行することはできません。そのため、新しい設計と問題について説明してみます。

小さい問題は、実装の非効率性です。これは、長い文字列である入力タイムスロットごとdef post()に個別に作成するためです。私のコードでは、これは次のスニペットを含むネストされたループで読み取られます [非常に非効率的だと思います]。name<courtname><timeslotstarthour><timeslotstartminute>namefor

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

差し迫ったより深刻な問題は、def post()コードがまったく読み取られず、その理由を理解できないことです (以前は読み取られていなかったのかもしれませんが、そこまでテストしていませんでした)。問題は、今のところ投稿と取得の両方を同じ方法で「終了」させたいということでしょうか。以下の最初の行は post() 用で、2 番目の行は get() 用です。

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

私の新しい投稿()は次のとおりです。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)

最終的には、上記の get() コードに、データストア内の既存の予約データを暗黙の新しい予約と比較してチェック/検証を追加し、対処できる潜在的な問題をユーザーに通知するアラートを開始したいと考えています。

また、この 2 つの問題についてコメントをいただければ幸いです。

更新終了 0

私のアプリはコミュニティ テニス コート用です。紙のサインアップ シートを、紙を模したオンラインのデジタル シートに置き換えたい。2 つのテニスの予定が衝突する「トランザクション上の」競合が発生する可能性は低いと思われます。では、どうすれば 2 番目のアポイントメント作成者に競合に注意を向けさせながら、成功したパーティーにも紙の上で行うように (消しゴムを使って) アポイントメントを変更する機会を与えることができるでしょうか。

各 30 分は、フォームの時間枠です。人々は通常、「送信」する前に、一度に複数の半時間サインアップします。

したがって、ループ内のコードで get_all を実行します。get が成功した場合、put() を受け入れるかどうかをユーザーが制御できるようにしたいと考えています。私はまだ put() が選択的ではなく、オールオアナッシングになると考えています。

私の質問は、コードの一部で明示的な「トランザクション」を使用する必要があるかどうかです。

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)
4

3 に答える 3

1

楽観的同時実行制御をご覧ください: http://en.wikipedia.org/wiki/Optimistic_concurrency_control

于 2012-09-04T18:18:14.227 に答える
0

常にトランザクションを使うべきだと思いますが、あなたの懸念がトランザクションによって最もよく対処されるとは思いません。

ほとんどの買い物袋や発券会社に見られるような2段階の予約システムを実装する必要があると思います。

  1. フォームを投稿すると、「予約リクエスト」が作成され、「他の人の買い物袋に入っている」として5〜15分間時間がブロックされます。
  2. ユーザーは、時間を確認するために承認画面で再度送信する必要があります。その画面の競合を更新する機能を提供し、タイムスロットの「予約ロック」を可能な限りリセットすることもできます。
  3. cronジョブ(または特定のウィンドウで着信する要求によってトリガーされる偽のジョブ)は、期限切れの予約ロックをクリアし、使用可能なスロットのプールに時間を戻します。
于 2012-09-05T17:20:11.920 に答える
0

特定の でタイムスロットが利用可能かどうかを確認し、競合しない場合にのみ、対応する子エンティティCourtを書き込むことができます。Reservationsstat_time

祖先クエリを使用して 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()

または、予約 ID のスロット部分を作成する場合は、クエリを削除し、予約エンティティ キーを作成して、それらが既に存在するかどうかを確認できます。

@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)
于 2012-09-05T16:43:48.753 に答える