2013-11-09 4 views
2

У меня есть html-форма, которая имеет Firstname, LastName, Age и Gender и ADD кнопка. Я ввожу данные в форму и попадает в Berkeelys db. Что мой код делает, он печатает только последние значения. Я хочу, чтобы он должен показать все значения, относящиеся к конкретному ключевомуКак передать несколько значений одному ключу с помощью словаря?

#!/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 
+0

Избегайте использования модуля ['bsddb'] (http://docs.python.org/2/library/bsddb.html), поскольку он устарел. Если вы хотите, чтобы интерфейс типа «dict» был в БД, используйте модуль ['shelve'] (http://docs.python.org/2/library/shelve.html). Кроме того: если вы хотите сохранить больше одного объекта в качестве значения, используйте значение «list» как «и», а «добавьте» значения при их вставке. – Bakuriu

+0

Могу ли я иметь больше объектов записей, хранящихся в db? – Jeremy

+0

Что такое объект записи? Вы никогда не определяли его. Кроме того, что вы подразумеваете под «db»? Вы имеете в виду базу данных, обработанную 'shelve'? База данных в целом? – Bakuriu

ответ

2

Вы должны использовать базу данных SQL вместо интерфейса на основе dict, поскольку базы данных SQL уже обрабатывают несколько кортежей в таблице.

Во всяком случае, если вы хотите иметь интерфейс dict вы можете использовать shelve модуль (bsddb является устаревшим, поэтому следует избегать его) и сохранить каждое значение в 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'...' просто означает, что строки Юникода, это не меняет свое значение)

Однако этот код есть некоторые проблемы (например, попробуйте запустить его дважды ...), но если вы хотите следовать этому пути, то вы должны должен сначала изучить SQL, так что продолжайте и stufy его (есть много онлайн-руководств. mple w3schools).

+0

. Я не был в модуле полки. хотя мне нужна такая же работа с использованием модуля Berkelys db. Я ценю ваш код. – Jeremy

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

е = открыт ('рабочего файла', 'ж') Первый аргумент является строкой, содержащей имя файла. Второй аргумент - это другая строка, содержащая несколько символов, описывающих способ использования файла. mode может быть «r», когда файл будет считан только «w» только для записи (существующий файл с тем же именем будет удален), а «a» открывает файл для добавления; любые данные, записанные в файл, автоматически добавляются в конец.

+0

Могу ли я писать так: db = bsddb.hashopen ("/ home/neeraj/public_html/database/mydb.db", "c"). перезапишет ли он ??? – Jeremy

+0

Также нет «а», если я использую hashopen. Он говорит, что вы можете использовать только r, w, c, n – Jeremy

+0

Я полагаю, что попытка - это ваш единственный вариант, поскольку я не знаком с BDB. –

0

Правильный ответ: не использовать BDB для такого случая. Для простых приложений вы можете использовать встроенный модуль sqlite, который был впервые представлен в python 2.5.

1

Правильный способ связывания нескольких значений с одним ключом состоит в том, чтобы упаковать список или значение словаря, используя, например, «json.dumps».

Вот Exemple:

#!/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 и применимо к другим DBS ключ/значение, как LevelDB.

Extra:

Учитывая тот факт, что ключи bsddb Hashmap упорядочены лексикографически (т.е. как питон 2 строки.), Вы можете построить HashMaps с ключами, имеющими predicatable порядка избавляя Вас идти через весь стол ,

Чтобы использовать эту функцию, вам необходимо создать полезные ключи. Снова вам понадобится функция упаковки, которая переводит порядок сортировки python в лексиграфический порядок (то есть 11 > 2, но "11" < "2"). Вот Exemple такая упаковка функция:

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) вы можете построить еще один HashMap мы называем age_index, с которой вы можете легко восстановить каждый пользователь в возрасте до 30 лет HashMap может выглядеть следующим образом:

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

Этот представляет собой читаемый человеком вид hasmap: ключ фактически заполнен функцией pack. Как вы можете видеть, клавиша составage и primarykey предмета, сохраненного ранее. В этом случае значение не используется, потому что оно нам не нужно. Имейте в виду, что каждый ключ является и должен быть уникальным.

После того, как эта схема на месте, вы делаете «выбор запросов», называемых запросами диапазона в bsddb, используя 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]) 

Это возвращает документ, связанный с пользователем amz.

идти дальше нужно использовать другой интерфейс bsddb который точка входа bsddb.db.DB и bsddb.db.DBEnv (documentation]. С помощью этого интерфейса вы можете иметь несколько HashMap связанного с тем же контекстом транзакции, даже если это не требуется использовать транзакции ,

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 вы должны использовать курсор, чтобы получить детали см documentation для этого или вы можете получить все элементы принадлежит к одной клавише с помощью

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' Надеюсь, это поможет.

Смежные вопросы