Python 应用程序引擎型号,获取或插入问题w.r.t主键和复合键

Python 应用程序引擎型号,获取或插入问题w.r.t主键和复合键,python,google-app-engine,Python,Google App Engine,A]问题摘要: 我在模型之间有1到多个层次关系 国家(1)->城市(许多) 城市(1)-->状态(多个) 因此,一个国家只能有一个独特的国家,一个国家只能有一个独特的城市,一个城市可以有许多身份 我计划使用“get_或_insert”方法来确保在数据库中维护唯一的记录 B]代码摘录: 1] 模型结构-- 2] 用于存储从HTML表单检索的数据的代码: 问题: 1] 从google搜索中,似乎“get_或_insert”需要一个键,在我的“UserReportedCountry”模型中,我希望国家

A]问题摘要:

我在模型之间有1到多个层次关系

国家(1)->城市(许多)
城市(1)-->状态(多个)

因此,一个国家只能有一个独特的国家,一个国家只能有一个独特的城市,一个城市可以有许多身份

我计划使用“get_或_insert”方法来确保在数据库中维护唯一的记录

B]代码摘录:

1] 模型结构--

2] 用于存储从HTML表单检索的数据的代码:

问题:

1] 从google搜索中,似乎“get_或_insert”需要一个键,在我的“UserReportedCountry”模型中,我希望国家的名称是主键 在“UserReportedCity”模型中,我希望国家名称+城市名称的组合是关键。我该怎么做呢

2] 有没有一种方法可以在不指定密钥的情况下使用“get_或_insert”,我在stackoverflow上看到了下面的帖子(http://stackoverflow.com/questions/4308002/google-app-engine-datastore-get-or-insert-key-name-confusion),并尝试了这个想法,但没有成功

谢谢你的阅读

[编辑#1]

根据@Josh Smeaton给出的回复总结变更

1] 现在,代码检查数据库中是否存在用户报告的国家/地区。如果用户报告的国家/地区不存在,则代码将创建UserReportedCountry、UserReportedCity并为其附加新状态

2] 如果国家/地区存在,则代码检查给定国家/地区是否存在用户报告的城市

如果找不到该城市,则创建一个城市记录并将其与找到的国家/地区关联,并附加一个状态记录

如果找到该城市,则将状态记录附加到该城市

请求:

我将非常感谢,如果有人能做一个代码审查,让我知道如果我犯了任何错误

谢谢

代码摘录:

#this method will be used to parse the data the user provided in the html form and store it in the database models
#while maintaing the relationship between UserReportedCountry, UserReportedCity and UserReportedStatus
#BUG, there needs to be error checking to make sure the country , city and status data is invalid or not
#if the data is invalid, then error message needs to be reported and then redirection back to the main page
def store_user_data(self):
    #method call to find out the completly filled out UserReportedCity model
    user_reported_city = self.find_or_create_user_reported_country_and_city(
                                self.request.get('selCountry'), self.request.get('city'))

    #status is always unique for a user entry, so create a brand new UserReportedStatus everytime.
    user_reported_status = UserReportedStatus(status = self.get_user_reported_status(), city = user_reported_city)
    user_reported_status.put()            

#Here the code needs to find out if there is an existing country/city for the user selection
#1] If the user reported country doesnt exist, create a new country record, create a new city record and return the city record
#2] If the user reported country exists, check if the user reported city is associated with the country. 
#if the city exists, then return it. If the city doesnt exists, then create a new city and return it  
#example: if the user chooses USA, there needs to be a check if USA is already present or not, 
#so that we dont create an additonal USA record
def find_or_create_user_reported_country_and_city(self, country_name, city_name):
    country_query_result = db.GqlQuery("SELECT * FROM UserReportedCountry WHERE name = :country_name_value" 
                                       ,country_name_value = country_name).get()

    if (country_query_result == None):
        #since the country doesnt exists, create and save the country
        user_reported_country = self.create_and_save_user_country_record(country_name)

        #Since the country doesnt exist, there cannot be a city record for the given country, so blindly create the record
        return self.create_and_save_user_city_record(city_name, user_reported_country)
    else:
        #Since we found a country, now we need to find whether the user selected city exists for the given country
        return self.find_or_create_city_for_country(country_query_result, city_name)

#Check wheter the user selectred city exists in the country
#1] if the city exists return the record back 
#2] if the city doesnt exist creaty the city record and return it   
def find_or_create_city_for_country(self, country_record, city_name):
    city_query_result = db.GqlQuery("SELECT * FROM UserReportedCity WHERE name = :city_name_value AND country =:country_value"
                                     ,city_name_value = city_name, country_value = country_record ).get()

    if (city_query_result == None):
        #Since the city doesnt exist for the given country, 
        #create the city record, associated it with the country and return the record back
        return self.create_and_save_user_city_record(city_name, country_record)
    else:
        #since the city was found, return the record back 
        return city_query_result    

#method to create a UserReportedCountry record for a given country name 
def create_and_save_user_country_record(self, country_name):
    user_reported_country = UserReportedCountry(name= country_name)
    user_reported_country.put()
    return user_reported_country

#method to create a UserReportedCity record for a given city name and a given country record
def create_and_save_user_city_record (self, city_name, country_record):
    user_reported_city = UserReportedCity(name = city_name, country = country_record)
    user_reported_city.put()
    return user_reported_city
[编辑#2]

在html表单中,保存数据的调用使用“post”完成。你认为这仍然是个问题吗

<div id="userDataForm">
    <form method="post" action="/UserReporting">
      <p> Select Country: </p>
      <select name="selCountry" id="country">
      <!-- By default, we will select users country -->
      <script type="text/javascript" language="JavaScript">
            document.write("<option value=\"" + geoip_country_name() + "\" selected>"
      </script>
      :
      :
      :
      <p> Select City: </p>
      <div>
        <input type="text" name="city" id="city"> 

        <!-- By default, we will select users city -->
        <script type="text/javascript" language="JavaScript">
            document.getElementById("city").value = geoip_city()
        </script>

      </div>    

      <input type="submit" name="report_down" value="Report Down">
      <input type="submit" name="report_up" value="Report Up"> 
    </form>
<div>           

选择国家:

文件。写(“”) : : : 选择城市:

document.getElementById(“城市”).value=geoip_city()

最初我尝试使用Djangoforms,但我被阻止了,因为我不知道如何使用javascript在djangoform中选择一个值,我不知道GAE是否使用了内部元类,但在django中,我将使用
unique
字段参数作为国家定义的国家名称,并一起使用
unique\u
城市定义中“('country','name')的元元组。如果您碰巧忘记了get\u或\u insert正确的咒语,这将强制执行完整性


否则,对名称进行查找(get操作),如果它还不存在,则进行插入。基本上,在您自己的代码中模拟get_或_插入。

我不知道GAE是否使用内部元类,但在django中,我将使用
unique
字段参数作为国家定义的国家名称,并将
unique_一起作为“('country',name'的
元组)在城市定义中。这将在任何情况下强制执行完整性,如果您碰巧忘记了“获取”或“插入”正确的咒语


否则,对名称进行查找(get操作),如果名称还不存在,则进行插入。基本上,在您自己的代码中模拟get_或_插入。

按顺序解决您的问题:

1] 在谷歌搜索中,它出现了 “获取或插入”需要密钥,在我的 “UserReportedCountry”中的案例 模特,我要国家的名字 作为主键并在 “UserReportedCity”模型,我想要 国家名称+城市组合 名字是钥匙,我该怎么办 这样做

只需指定国家的名称,并将国家和城市(如“USA/San Francisco”)连接起来作为传递给
get\u或\u insert
的关键名称。另外,
get\u或\u insert
仅是以下内容的语法糖:

def get_or_insert(cls, key_name, **kwargs):
  def _tx():
    obj = cls.get_by_key_name(key_name)
    if obj is None:
      return cls(key_name, **kwargs)
    else:
      return obj
  return db.run_in_transaction(_tx)
2] 有什么方法可以使用它吗 “获取或插入”而不指定 凯伊,我是从下面经过的 在stackoverflow上过帐 (http://stackoverflow.com/questions/4308002/google-app-engine-datastore-get-or-insert-key-name-confusion), 并尝试了这个想法,但没有成功


这样做真的没有意义。键是App Engine中模型的唯一唯一字段,并且您不能在App Engine中执行跨实体组查询,因此除非您指定一个,否则无法执行事务性的获取或插入操作。不过,根据您的要求,使用国家名和城市名作为键名应该是可行的很好。

按顺序回答您的问题:

1] 在谷歌搜索中,它出现了 “获取或插入”需要密钥,在我的 “UserReportedCountry”中的案例 模特,我要国家的名字 作为主键并在 “UserReportedCity”模型,我想要 国家名称+城市组合 名字是钥匙,我该怎么办 这样做

只需指定国家的名称,并将国家和城市(如“USA/San Francisco”)连接起来作为传递给
get\u或\u insert
的关键名称。另外,
get\u或\u insert
仅是以下内容的语法糖:

def get_or_insert(cls, key_name, **kwargs):
  def _tx():
    obj = cls.get_by_key_name(key_name)
    if obj is None:
      return cls(key_name, **kwargs)
    else:
      return obj
  return db.run_in_transaction(_tx)
2] 有什么方法可以使用它吗 “获取或插入”而不指定 凯伊,我是从下面经过的 在stackoverflow上过帐 (http://stackoverflow.com/questions/4308002/google-app-engine-datastore-get-or-insert-key-name-confusion), 并尝试了这个想法,但没有成功

它没有
def get_or_insert(cls, key_name, **kwargs):
  def _tx():
    obj = cls.get_by_key_name(key_name)
    if obj is None:
      return cls(key_name, **kwargs)
    else:
      return obj
  return db.run_in_transaction(_tx)