【问题标题】:How to query the last element in a database class in Gql (Google Query Language)?如何在 Gql(谷歌查询语言)中查询数据库类中的最后一个元素?
【发布时间】:2026-02-19 13:30:01
【问题描述】:

我在 GAE 中有这个数据库:

class Contract(db.Model): # I renamed "Act" as "Contract"
    book_number = db.IntegerProperty(required = True)
    initial_page = db.IntegerProperty(required = True)
    final_page = db.IntegerProperty(required = True)
    date = db.DateProperty(auto_now_add=True)

我想查询这个数据库来选择这个数据库中最后添加的元素的 book_number、initial_page 和 final_page 的值,将每个值放在一个变量中。在 MySQL 中,我会这样做:

SELECT MAX(book_number) AS Last FROM Contracts;

但是我如何在 GAE (GglQuery) 中做到这一点?我在哪里可以找到 Gql 中的所有命令? (我没找到herehere

我正在使用 Python 2.7 GAE。

这是我的完整代码:

# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
#!/usr/bin/env python
#
# Copyright 2007 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

import os

import webapp2

import jinja2

jinja_environment = jinja2.Environment(autoescape=True,
    loader=jinja2.FileSystemLoader(os.path.join(os.path.dirname(__file__), 'templates')))

import re

from google.appengine.ext import db

USER_RE = re.compile(r"^[a-zA-Z0-9_ -]{3,20}$")
def valid_person(person):
    return USER_RE.match(person)

PASS_RE = re.compile(r"^.{3,20}$")
def valid_SSN(SSN):
    return PASS_RE.match(SSN)

EMAIL_RE = re.compile(r"^[\S]+@[\S]+\.[\S]+$")
def valid_email(email):
    return EMAIL_RE.match(email)

import time

import datetime


##def getNumBookPg():
##    doc = open("numbookpg.txt")
##    numBookPg = []
##    numbers = doc.read().split()
##    for n in numbers:
##        numBookPg.append(n)
##    return numBookPg
##
##numBookPage = getNumBookPg()

##def updateNumBookPg(b, fp):
##    newNumBookPg = b + ' ' + str(int(fp) + 1) + ' ' + str(int(fp) + 1)
##    doc = open("numbookpg.txt", "w")
##    doc.write(newNumBookPg)

def dateToday():
    today = datetime.datetime.today()
    todayDay = str(today.day)
    todayMonth = str(today.month)
    monthExt = {'1':' January ', '2':'February', '3':' March ', '4':'April', '5':'May', '6':'June', '7':' July ', '8':'August', '9':'September', '10':'October', '11':'November ', '12':'December'}
    todayYear = str(today.year)
    return(todayDay + ' of  ' + monthExt[todayMonth] + ' of ' + todayYear)

class MainHandler(webapp2.RequestHandler):
    def get(self):
        q = db.GqlQuery("SELECT * FROM Contract ORDER BY date DESC")
        contract = q.get() # return only the first entity
        numBook = contract.book_number
        numInitialPage = contract.initial_page
        numFinalPage = contract.final_page
        template_values = {"person": "",
                                       "nacionality": "",
                                       "SSN": "",
                                       "driverLicense": "",
                                       "email":"",
                                       "person_error": "",
                                       "SSN_error": "",
                                       "driverLicense_error": "",
                                       "address": "",
                                       "email_error": "",
                                       "numBook": numBook,
                                       "numInitialPage": numInitialPage,
                                       "numFinalPage": numFinalPage,
                                       }
        template = jinja_environment.get_template('index.html')
        self.response.out.write(template.render(template_values))

##    def write_form(self, text_write):
##        self.response.out.write(text_write)

    def post(self):
        person_name = self.request.get("person")
        user_nacionality = self.request.get('nacionality')
        user_profession = self.request.get('profession')
        user_maritalStatus = self.request.get('maritalStatus')
        user_SSN = self.request.get('SSN')
        user_email = self.request.get('email')
        user_driverLicense = self.request.get('driverLicense')
        person_error = ""
        SSN_error = ""
        driverLicense_error = ""
        geted_email_error = ""
        address = self.request.get('address')
        contractType = self.request.get("contractType")
        owner = self.request.get("owner")
        witness = self.request.get("witness")
        numBook = self.request.get("numBook")
        numInitialPage = self.request.get("numInitialPage")
        numFinalPage = self.request.get("numFinalPage")

        if (person_name and valid_person(person_name)) and (user_SSN and valid_SSN(user_SSN)) and ((not user_email) or (user_email and valid_email(user_email))):
            a = Person(firstName = person_name,
                                   nacionality = user_nacionality,
                                   maritalStatus = user_maritalStatus,
                                   profession = user_profession,
                                   SSN = int(user_SSN),
                                   driverLicense = int(user_driverLicense)
                                   #address = user_address
                                   )
            a.put()
            self.redirect('/your_contract?person=%s&nacionality=%s&profession=%s&maritalStatus=%s&SSN=%s&driverLicense=%s&email=%s&witness=%s&owner=%s&contractType=%s&address=%s&numBook=%s&numInitialPage=%s&numFinalPage=%s' % (person_name, user_nacionality, user_profession, user_maritalStatus, user_SSN, user_driverLicense, user_email,
witness, owner, contractType, address, numBook, numInitialPage, numFinalPage))

        else:
            if not person_name or not valid_person(person_name):
                person_error = "Oh no!!! this person name isn't valid!"
            if not user_SSN or not valid_SSN(user_SSN):
                SSN_error = "Oh no!!! SSN isn't valid!"
            if user_email and not valid_email(user_email):
                geted_email_error = "Oh no!!! e-mail isn't valid!"
            template_values = {"person": person_name,
                                "nacionality": user_nacionality,
                                "maritalStatus": user_maritalStatus,
                                "profession": user_profession,
                                "SSN": user_SSN,
                                "driverLicense": user_driverLicense,
                                "email": user_email,
                                "person_error": person_error,
                                "SSN_error": SSN_error,
                                "driverLicense_error": user_driverLicense,
                                "address": address,
                                "email_error": geted_email_error}
            template = jinja_environment.get_template('index.html')
            self.response.out.write(template.render(template_values))

class your_contractHandler(webapp2.RequestHandler):
    def get(self):
        geted_person_name = self.request.get('person')
        geted_user_nacionality = self.request.get("nacionality")
        geted_user_profession = self.request.get("profession")
        geted_user_maritalStatus = self.request.get("maritalStatus")
        geted_user_SSN = self.request.get('SSN')
        geted_user_email = self.request.get('email')
        geted_user_driverLicense = self.request.get('driverLicense')
        geted_person_error = ""
        geted_SSN_error = ""
        geted_driverLicense_error = ""
        geted_address = self.request.get('address')
        geted_owner = self.request.get("owner")
        geted_witness = self.request.get("witness")
        geted_contractType = self.request.get("contractType")
        geted_dateToday = dateToday()
        your_contract = jinja_environment.get_template('your_contract.html')
        geted_numBook = self.request.get('numBook')
        geted_numInitialPage = self.request.get('numInitialPage')
        geted_numFinalPage = self.request.get('numFinalPage')

        contract = Contract(book_number = geted_numBook, initial_page = geted_numInitialPage, final_page = geted_numFinalPage)
        contract.put()

        your_contract_values = {"person":geted_person_name,
                                "nacionality":geted_user_nacionality,
                                "maritalStatus": geted_user_maritalStatus,
                                "profession": geted_user_profession,
                                "SSN":geted_user_SSN,
                                "driverLicense":geted_user_driverLicense,
                                "address":geted_address,
                                "email":geted_user_email,
                                "contractType":geted_contractType,
                                "dateContract":geted_dateToday,
                                "numBook":geted_numBook,
                                "numInitialPage":geted_numInitialPage,
                                "numFinalPage":geted_numInitialPage,
                                }
        template = jinja_environment.get_template('index.html')
        self.response.out.write(your_contract.render(your_contract_values))

class Person(db.Model):
    firstName = db.StringProperty(required = True)
#    lastName = db.StringProperty(required = True)
    nacionality = db.StringProperty(required = True)
    maritalStatus = db.StringProperty(required = True)
    profession = db.StringProperty(required = True)
    SSN = db.IntegerProperty(required = True)
    driverLicense = db.IntegerProperty(required = True)
#    address = db.PostalAdressProperty(required = True)
#    condition = db.StringProperty(required = False, choices=set(["buyer", "seller", "renter", "owner", "witness"]))

class Contract(db.Model):
    book_number = db.IntegerProperty(required = True)
    initial_page = db.IntegerProperty(required = True)
    final_page = db.IntegerProperty(required = True)
    date = db.DateTimeProperty(auto_now_add=True)
#    firstPart = db.StringProperty(required = True)
#   secondPart = db.StringProperty(required = True)
#    contractDraft = db.TextProperty(required = True)

app = webapp2.WSGIApplication([('/', MainHandler), ('/your_contract', your_contractHandler)],
                              debug=True)

【问题讨论】:

    标签: python google-app-engine gql gqlquery


    【解决方案1】:

    gql 参考是here,查询文档是here

    试试这个:

    q = db.GqlQuery("SELECT * FROM Act ORDER BY date DESC")
    act = q.get() # return only the first entity
    a = act.book_number
    b = act.initial_page
    c = act.final_page
    

    【讨论】:

    • 谢谢,@presveva,但现在我收到此错误消息:“文件“C:\Users\CG\Documents\udacity\contract\main.py”,第 77 行,在获取 numBook = contract.book_number AttributeError: 'NoneType' 对象没有属性 'book_number'" 你知道为什么吗? ("我已经用契约替换了类名 Act)
    • 使用 DateTimeProperty 而不是 DateProperty。如果您在同一天添加了多个项目,您可能无法获得最新的。您的示例 SQL 也没有反映您的问题。您的 SQL 示例获取 column1 整个表的最小值和最大值,但您要求“此数据库中最后添加元素的 book_number、initial_page 和 final_page”
    • 您并没有在 appengine 文档中寻找 GQL 参考 developers.google.com/appengine/docs/python/datastore/… - 它在 appengine 的 Python 文档索引中列出。
    • 感谢您的批评,@Tim,我会努力改进我的问题。 SQL 示例是为了表明我已经知道如何在 SQL 中执行查询。我在 GQL 参考中搜索命令列表(如那些可用于 SQL 的命令列表)。但你是对的,我没有看起来太难。尽管如此,我认为我的问题不值得-1。
    • 如果您阅读了 appengine 的基本概述,那么您在过去几天中的很多(几乎所有)问题都会很容易得到解答。诸如“您关于无法写入文件系统的问题”之类的事情。正如我之前提到的,如果您确实花一些时间查看 appengine 的介绍,您将节省大量时间。我还建议您阅读所有 Nick Johnson 的 appengine 博客文章。 blog.notdot.net/tag/app-engine 他在 appengine 团队工作,对如何做事提供了深刻的见解。