2

我有一个 html 表单,其中包含、Firstname和和一个按钮。我将数据输入到表格中,然后进入 Berkeelys 数据库。我的代码所做的是它只打印最后一个值。我希望它应该显示与特定键相关的所有值LastNameAgeGenderADD

#!/usr/bin/python

import bsddb
import cgi

form = cgi.FieldStorage()

print "Content-type:text/html\n"
Fname = form.getvalue('firstname', '')
Lname = form.getvalue('lastname', '')
Age = form.getvalue('age', 0)
Gender = form.getvalue('gender', '')

#print Fname, Lname, Age 

db = bsddb.hashopen("/home/neeraj/public_html/database/mydb.db","w")
db['FirstName'] = Fname  
db['LastName'] = Lname
db['Age'] = Age 
db['Gender'] = Gender
db.close()
db = bsddb.hashopen("/home/neeraj/public_html/database/mydb.db","r")
#db = bsddb.hashopen("/home/neeraj/public_html/database/mydb.db")
print db['FirstName'], db['LastName'], db['Age'], db['Gender']
db.close()
print db 
4

5 回答 5

2

您应该使用 SQL 数据库而不是dict基于 - 的接口,因为 SQL 数据库已经处理表中的多个元组。

无论如何,如果你想要一个dict接口,你可以使用shelve模块(bsddb已弃用,所以你应该避免它)并将每个值保存在 a 中list

import shelve

COLUMNS = ('FirstName', 'LastName', 'Age', 'Sex')

the_db = shelve.open('test.db', writeback=True)
for col_name in COLUMNS:
    if col_name not in the_db:
        the_db[col_name] = []

records = [
    ('John', 'Deer', 20, 'M'),
    ('Ada', 'Lovelace', 23, 'F'),
]

for record in records:
    for col_name, value in zip(COLUMNS, record):
        the_db[col_name].append(value)

the_db.close()

the_db = shelve.open('test.db')

for record in zip(*(the_db[col_name] for col_name in COLUMNS)):
    print(record)

the_db.close()

上面的代码输出:

('John', 'Deer', 20, 'M')       
('Ada', 'Lovelace', 23, 'F')

如果您想使用 SQL 数据库,您可以使用该sqlite3模块。例如:

import sqlite3

conn = sqlite3.connect('test.sqlite')

cursor = conn.cursor()

cursor.execute('''
CREATE TABLE people (
    FirstName text,
    LastName text,
    Age int,
    Sex text
    )''')

cursor.execute('''
INSERT INTO people values ('John', 'Deer', 20, 'M')''')

cursor.execute('''
INSERT INTO people values ('Ada', 'Lovelace', 23, 'F')''')

conn.commit()

for record in cursor.execute('''SELECT * FROM people'''):
    print(record)

上面的代码输出:

(u'John', u'Deer', 20, u'M')
(u'Ada', u'Lovelace', 23, u'F')

(注意u'...'简单的意思是字符串是 unicode,它不会改变它们的值)

但是这段代码有一些问题(例如尝试运行两次......),但是如果你想遵循这条路,那么你必须先学习SQL,所以继续学习它(网上有很多教程。例如w3schools那些)。

于 2013-11-09T11:12:58.343 回答
1

将多个值关联到单个键的正确方法是使用例如“json.dumps”打包列表或字典值。

这是一个例子:

#!/usr/bin/python
from json import dumps
from json import loads
import bsddb

# write
users = bsddb.hashopen("users.db","w")
primarykey = 'amz'
users[primarykey] = dumps(dict(username="amz", age=30, bio="craftsman"))
users.close()

# read

users = bsddb.hashopen("users.db","r")

for key in users.keys():
    print loads(users[key])

users.close()

这是与 bsddb 一起使用的基本模式,适用于其他键/值数据库,如 leveldb。

额外的:

鉴于 bsddb hashmap 键是按字典顺序排列的(即像 python 2 字符串),您可以使用具有可预测顺序的键构建 hashmap,从而省去遍历所有表的麻烦。

要充分利用该功能,您必须构建有用的密钥。同样,您需要一个将 python 排序顺序转换为字典顺序(即11 > 2"11" < "2")的打包函数。这是一个这样的打包函数的例子:

def pack(*values):
    def __pack(value):
        if type(value) is int:
            return '1' + struct.pack('>q', value)
        elif type(value) is str:
            return '2' + struct.pack('>q', len(value)) + value
        else:
            data = dumps(value, encoding='utf-8')
            return '3' + struct.pack('>q', len(data)) + data
    return ''.join(map(__pack, values))

这是一种天真,您可以加倍努力并支持float和更好地打包int以节省空间。

例如,给定简化的模式User(username, age),您可以构建另一个我们称之为age_index的 hashmap,您可以使用它轻松检索每个 30 岁的用户。hashmap 可能如下所示:

   key    | value
 -----------------
  29  tom |   X
  30  amz |   X
  30  joe |   X
  30  moh |   X

这是一个人类可读的 hasmap 视图:键实际上是用上述pack函数打包的。如您所见,关键是先前存储的项目的组成和。在这种情况下,不使用该值,因为我们不需要它。请注意,每个键都是并且必须是唯一的。ageprimarykey

一旦该模式到位,您就可以使用Cursor.set_range(key). 这会将光标设置在最近的键上并返回关联的键/值对(语义可能会因数据库而有所不同)。

例如,要检索具有 的第一个人,age=30请使用以下代码:

def get_first_person_with_age_thirty()
    key, _ = age_index.set_range(pack(30))  # we don't need value
    age, pk = unpack(key)
    # set_range, will set the key to "30" and a pk
    # or with a key prefix superior to 30.
    #  So we need to check that age is really 30.
    if age == 30:
        return loads(users[pk])

这将返回与 user 关联的文档amz

为了更进一步,需要使用入口点所在的另一个 bsddb 接口bsddb.db.DBbsddb.db.DBEnv文档)。使用此接口,即使不需要使用事务,您也可以将多个哈希映射绑定到相同的事务上下文。

于 2015-08-21T18:51:05.690 回答
1

您可以通过设置重复标志在 berkeley db 中针对单个键保存多个值

filename = '/path/to/berkeley/db/file'
fruitDB = db.DB()
fruitDB.set_flags(db.DB_DUP)
fruitDB.open(filename, None, db.DB_BTREE, db.DB_CREATE)
fruitDB.put(str(1), "Waqar")
fruitDB.put(str(1), "Umer")
fruitDB.put(str(2), "x")
fruitDB.put(str(2), "y")
fruitDB.put(str(4), "z")
fruitDB.put(str(5), "e")

但是您不能使用 BDB 的“获取”方法检索所有这些,您必须使用光标来检索项目,请参阅此文档,或者您可以使用检索所有属于单个键的项目

cursor = fruitDB.cursor()
cursor.set(str(1))
record = cursor.current()
listTup = []
while record:
    print record
    listTup.append(record)
    record = cursor.next_dup()

输出将是

('1', 'Waqar')
('1', 'Umer')

这将返回所有值都属于键“1”的元组列表希望这会有所帮助。

于 2017-05-18T05:35:15.593 回答
0

我想每次都使用w选项打开数据库,你每次都覆盖并且只存储最后一个条目。您应该改用a.

db = bsddb.hashopen("/home/neeraj/public_html/database/mydb.db","a")

摘自官方 Python 手册 -->

    open() returns a file object, and is most commonly used with two arguments:
    open(filename, mode).

f = open('workfile', 'w') 第一个参数是一个包含文件名的字符串。第二个参数是另一个字符串,其中包含一些描述文件使用方式的字符。mode 可以是 'r' 只读取文件,'w' 只写入(同名的现有文件将被删除),'a' 打开文件进行追加;写入文件的任何数据都会自动添加到末尾。

于 2013-11-09T07:52:34.913 回答
0

正确答案是:在这种情况下不要使用 BDB。对于简单的应用程序,您可以使用在 python 2.5 中首次引入的内置sqlite模块。

于 2013-11-09T09:30:27.297 回答