在一对多的Django模型和ModelForm中使用获取或插入功能
A] 概述:
在Django模型中使用获取或插入的功能,检查在添加新记录之前,是否已经存在某个记录或关系。
B] 详细信息:
1] 我有一个Django模型结构,国家(一个)和城市(多个)之间的关系。
2] 我使用ModelForm在网页上显示表单。这些表单作为模板值传递,然后在网页上渲染出来。
3] 当收到POST请求时,代码会提取国家和城市的表单数据,检查数据是否有效,然后保存。
C] 我需要帮助的地方:
1] 我想在国家和城市的关系中使用获取或插入的功能。
2] 基本上,我想检查用户选择的国家在数据库中是否已经存在记录。
2.1] 如果国家存在,接着检查这个国家是否有对应的城市记录。
2.1.1] 如果城市记录存在,那就没问题,不需要再添加新的记录。
2.1.2] 如果城市记录不存在,就创建这个城市记录,并将其与国家关联起来。
2.2] 如果国家不存在,就创建国家记录,创建城市记录,并将城市记录与国家记录关联。
C] 代码片段:
1] 模型和表单 --
class UserReportedCountry(db.Model):
country_name = db.StringProperty( required=True,
choices=['Afghanistan','Aring land Islands']
)
class UserReportedCity(db.Model):
country = db.ReferenceProperty(UserReportedCountry, collection_name='cities')
city_name = db.StringProperty(required=True)
class UserCountryForm(djangoforms.ModelForm):
class Meta:
model = UserReportedCountry
class UserCityForm(djangoforms.ModelForm):
class Meta:
model = UserReportedCity
exclude = ('country', )
2] 打印表单的代码 --
user_country_form和user_city_form是从Python代码作为模板值传递过来的。
__TEMPLATE_USER_COUNTRY_FORM = 'user_country_form'
__TEMPLATE_USER_CITY_FORM = 'user_city_form'
def get(self):
template_values = {
self.__TEMPLATE_USER_COUNTRY_FORM: UserCountryForm(),
self.__TEMPLATE_USER_CITY_FORM: UserCityForm()
}
#rendering the html page and passing the template_values
self.response.out.write(template.render(self.__MAIN_HTML_PAGE, template_values))
3] 显示模板值的HTML代码片段 --
<div id="userDataForm">
<form method="POST" action="/UserReporting">
<table>
<!-- Printing the forms for users country, city -->
{{ user_country_form }}
{{ user_city_form }}
</table>
<input type="submit" name="submit" value= "submit">
</form>
</div>
3] 保存数据的代码片段 --
def post(self):
self.store_user_data()
self.redirect('/')
#method to save users data in the models UserReportedCountry, UserReportedCity
def store_user_data(self):
#getting user's country and city
user_reported_country = UserCountryForm(self.request.POST)
user_reported_city = UserCityForm(self.request.POST)
if (user_reported_country.is_valid() and user_reported_city.is_valid()):
#save the country data
country_entity = user_reported_country.save()
#save the city data, and relate county with city
city_entity = user_reported_city.save(commit=False)
city_entity.country = country_entity
city_entity.put()
return
else:
return
感谢阅读。
[编辑#1]
@ Torsten,您的帖子让我注意到了get_or_insert,我随后在StackOverflow上找到了一个帖子(http://stackoverflow.com/questions/4812832/get-or-create-matching-key-and-user-python-app-engine),并实现了key_name功能来使用get_or_insert。
保存记录的代码如下:
def store_user_data(self):
#getting user's country and city
user_reported_country = UserCountryForm(self.request.POST)
user_reported_city = UserCityForm(self.request.POST)
if (user_reported_country.is_valid() and user_reported_city.is_valid()):
#save the country and city data
country_record = self.store_country_data()
city_record = self.store_city_data(country_record)
return
else:
return
def store_country_data(self):
user_reported_country_name = self.request.POST['country_name']
key_name = self.sanitize_key_name(user_reported_country_name)
country_entity = UserReportedCountry.get_or_insert(key_name, country_name = user_reported_country_name)
country_entity.put()
return country_entity
def store_city_data(self, country_record):
user_reported_city_name = self.request.POST['city_name']
key_name = self.sanitize_key_name("%s:%s" % (country_record.country_name, str(user_reported_city_name)) )
city_entity = UserReportedCity.get_or_insert(key_name,
city_name = user_reported_city_name,
country= country_record)
city_entity.put()
return city_entity
def sanitize_key_name(self,key_name):
return re.sub(r'\s', '', key_name.lower())
请求:有人能帮我快速检查一下代码吗?看看我是否做错了什么,或者犯了一些新手错误?
1 个回答
使用 get_or_create
(这相当于你提到的 get_or_insert):
country, country_is_new = UserReportedCountry.objects.get_or_create(country_name=my_country_name)
city, city_is_new = UserReportedCity.objects.get_or_create(country=country, city_name=my_city_name)