I have a html form which has Firstname
, LastName
, Age
and Gender
and a ADD
button.
I enter the data into the form and that gets into the Berkeelys db. What my code does is it prints only the last values. I want that it should show all the values related to particular key
#!/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
The correct answer is: do not use the BDB for such a case. For simple applications you can use the builtin sqlite module that was first introduced in python 2.5.
I suppose opening the database everytime with
w
option, you are overwriting everytime & only storing the last entry. You should instead usea
.Extract from the official Python manual -->
You should use an SQL database instead of the
dict
-based interface, since SQL databases already handle multiple tuples in a table.Anyway, if you want to have a
dict
interface you can use theshelve
module (bsddb
is deprecated, so you should avoid it) and save each value in alist
:The above code outputs:
If you want to use an SQL database you could use the
sqlite3
module. For example:The above code outputs:
(Note the
u'...'
simply means that the strings are unicode, it doesn't change their value)However this code has some problems (e.g. try to run it twice...), but if you want to follow this path then you must learn SQL first, so go ahead and stufy it (there are a lot of online tutorials. For example
w3schools
ones).You can save multiple values against single key in berkeley db by setting the duplicate flag
But you cant retrieve all of them using 'Get' method of BDB you have to use cursor to retrieve items see documentation for this or you can retrieve all the items belongs to single key using
output will be
This will return list of tuple having all the values belong to key '1' Hope this helps.
The correct method to associate multiple values to a single key is to pack a list or dictionary value using for instance "json.dumps".
Here is an exemple:
This is the basic pattern to be used with bsddb and is applicable to other key/value dbs like leveldb.
Extra:
Given the fact that bsddb hashmap keys are ordered lexicographically (ie. like python 2 strings) you can build hashmaps with keys having a predicatable order saving you the trouble of going through all the table.
To put that feature to good use you have to build useful keys. Again you need a packing function that translates python sort order to lexigraphic order (ie.
11 > 2
but"11" < "2"
) . Here is an exemple such packing function:This is a kind of naive, you could go the extra mile and support
float
and better packint
to save space.For instance, given the simplified schema
User(username, age)
you can build another hashmap we callage_index
with which you can easily retrieve every user at age of 30. The hashmap can look like the following:This is a human readable view of the hasmap: the key is actually packed with the above
pack
function. As you can see the key is the composition of theage
and theprimarykey
of the the item stored previously. In this case the value is not used because we don't need it. Mind the fact that each key is and must be unique.Once that schema in place, you do "select queries", called range queries in bsddb using
Cursor.set_range(key)
. This will set the cursor at the nearest key and return the key/value pair associated (the semantic can be a bit different depending on the database).For instance to retrieve the first person that has
age=30
, one use the following code:This will return the document associated with user
amz
.To go further one needs to make use of the other bsddb interface which entry point is
bsddb.db.DB
andbsddb.db.DBEnv
(documentation]. With this interface you can have several hashmap bound to the same transaction context even if it's not required to use transactions.