Python cho người Việt

Python cho người Việt

MySQLdb - Thiết lập kết nối

written by Phạm Thị Minh Hoài, on May 31, 2010 11:55:00 PM.

MySQLdb là một wrapper của thư viện MySQL C API: _mysql. Nó cho phép bạn viết các ứng dụng Python khả chuyển (portable) chạy trên nhiều môi trường khác nhau để truy cập vào máy chủ có hệ quản trị CSDL MySQL.

Bài viết sau đây đề cập một số khía cạnh liên quan tới thiết lập kết nối CSDL. Đó là vấn đề quan trọng đầu tiên khi làm việc với bất kỳ hệ quản trị CSDL nào.

Bản cài đặt MySQLdb có thể download trên trang: http://sourceforge.net/projects/mysql-python/. Download có sẵn cho các nền tảng windows 32 bit và các họ unix. Đáng tiếc là MySQLdb hiện chỉ sử dụng cho các phiên bản python từ 2.3 đến 2.6.

Hello World

Giả thiết trên máy của bạn đã cài MySQL với cổng mặc định (3306) và account root không cần password. Đoạn chương trình sau minh họa một kết nối đơn giản nhất có thể. Nó in ra các db có trong CSDL này:

>>> db = MySQLdb.connect(user="root")
>>> cursor = db.cursor()
>>> query = "SHOW DATABASES"
>>> cursor.execute(query)
6L
>>> cursor.fetchall()
(('information_schema',), ('cdcol',), ('mysql',), ('phpmyadmin',), ('test',))

Kết nối theo IP

Truy cập từ xa đến một hệ thống phức tạp hơn, bạn cần biết các tham số:

  • Máy chủ chứa MySQL (mặc định: localhost hay 127.0.0.1)

  • Cổng truy cập vào MySQL (mặc định: 3306)

  • User, Password mà bạn được cấp

  • Tên CSDL bạn muốn truy cập

Ví dụ sau in ra các bảng của CSDL mydb trên máy 192.168.90.31 với cổng 3310:

>>> db = MySQLdb.connect(user="you", db="mydb", passwd="mypw", \
      host="192.168.90.31", port=3310)
>>> cursor = db.cursor()
>>> query = "SHOW TABLES"
>>> cursor.execute(query)
>>> cursor.fetchall()

Kết nối theo UNIX socket

Trên các localhost cho phép dùng UNIX socket bạn có thể viết:

db = MySQLdb.connect(db="test", user="hoaiptm", passwd="hoaiptm", \
                     unix_socket="/opt/hoaiptm/mysql/mysql.sock")

Truy cập MySQL qua các socket trên unix tương tự như named pipe trên windows. Nó cho phép các ứng dụng localhost tạo các kết nối cực kỳ nhanh đến CSDL. Nếu bạn chưa hiểu rõ về socket bạn có thể đọc: http://beej.us/guide/bgipc/output/html/multipage/unixsock.html.

Giấu password

Các ví dụ trên đây đều yêu cầu phải có password đặt trong mã nguồn Python. MySQLdb cho phép bạn giấu chúng trong một nơi mà chỉ bạn được phép truy cập:

db = MySQLdb.connect(db="yourdb", read_default_file="/home/hoaiptm/mysql.ini")

tập tin options /home/hoaiptm/mysql.ini có thể có nội dung như sau:

[client]
port=3310
socket=/opt/hoaiptm/mysql/mysql.sock
user=hoaiptm
password=hoaiptm

Hướng dẫn về các option này có thể đọc trong tài liệu: http://www.yellis.net/docs/mysql/manuel_Option_files.html#Option_files.

Thay đổi charset mặc định

Các kết nối trong các ví dụ trên sử dụng charset mặt định là latin1, do đó bạn không lấy được các dữ liệu tiếng Việt. Chẳng hạn bạn tạo một bảng user với chartset utf8 trong CSDL test như sau:

USE `test`;
CREATE TABLE `user` (
  `Id` int(11) NOT NULL AUTO_INCREMENT,
  `account` varchar(50) DEFAULT NULL,
  `fullname` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`Id`)
) ENGINE=MyISAM AUTO_INCREMENT=3 **DEFAULT CHARSET=utf8** ROW_FORMAT=DYNAMIC;
INSERT INTO `user` VALUES (1,'hoaiptm','Phạm Thị Minh Hoài');
INSERT INTO `user` VALUES (2,'trangnt','Ngô Thu Trang');

Sau đó cố gắng lấy dữ liệu từ bảng user:

>>> db = MySQLdb.connect(user="hoaiptm", db="test", passwd="hoaiptm", port=3310)
>>> cursor = db.cursor()
>>> query = "SELECT fullname FROM user"
>>> cursor.execute(query)
2L
>>> cursor.fetchall()
(('Ph?m Th? Minh Ho\xe0i',), ('Ng\xf4 Thu Trang',))

Các dấu ? cho thấy các ký tự utf8 đã không được truyền tải đúng. Để giải quyết vấn đề này chúng ta thêm tùy chọn charset = "utf8" trong connection:

>>> db = MySQLdb.connect(user="hoaiptm", db="test", passwd="hoaiptm", \
      port=3310, charset="utf8")
...
>>> cursor.fetchall()
((u'Ph\u1ea1m Th\u1ecb Minh Ho\xe0i',), (u'Ng\xf4 Thu Trang',))

Lúc này tất cả các dữ liệu trong trường text, char, varchar đều được trả về dạng unicode.

Yêu cầu trả về từ điển

MySQLdb cho phép trả về các kết quả dạng từ điển, để làm được điều đó bạn thêm tùy chọn cursorclass=MySQLdb.cursors.DictCursor. Ví dụ:

>>> db = MySQLdb.connect(user="hoaiptm", db="test", passwd="hoaiptm", port=3310, \
      charset="utf8", cursorclass=MySQLdb.cursors.DictCursor)
>>> cursor = db.cursor()
>>> query = "select * from user"
>>> cursor.execute(query)
2L
>>> cursor.fetchall()
({'account': u'hoaiptm', 'fullname': u'Ph\u1ea1m Th\u1ecb Minh Ho\xe0i', 'Id': 1L}, \
 {'account': u'trangnt', 'fullname': u'Ng\xf4 Thu Trang', 'Id': 2L})

Chương trình sẽ chạy chậm đi chút xíu, nhưng bù lại kết quả trả về rất dễ sử dụng.

Comments

  • Cám ơn bạn rất nhiều. Đúng cái mình đang cần, nhưng mình cần về Postgresql , mảng cgi thực sự, hôm nay cũng tìm thêm được về python-postgresql. Mày mò , không có thầy dậy mệt thật. Nghe nói mọi người bảo Python dễ nhưng mình thấy sao mà khó thế không biết , có lẽ do mình không được thông minh lắm. google search từ: cgi python accessing postgresql database thì tìm được một trang:

    https://wiki.inf.ed.ac.uk/DatabaseGroup/TeachingPythonPostgreGuide

    Cám ơn bạn rất nhiều. Thanks bqt vithon.org

    Comment by Naruto — Jun 1, 2010 8:59:13 PM | #

  • Quên mất. Bạn có thể cho mình hỏi , bây giờ ví dụ muốn insert dữ liệu từ bằng cgi , mình cũng không biết diễn tả như thế nào cả. Mình cũng không có nhiều kiến thức lắm. Ý mình là mình muốn insert dữ liệu vào mysql trên nền web thực sự, vì cái trên vẫn phải dùng python thì mới insert dữ liệu vào mysql . Bây giờ muốn insert dữ liệu vào mysql trên nền web sử dụng cgi python . Rất mong bạn giúp đỡ.

    Comment by Naruto — Jun 1, 2010 9:02:58 PM | #

    • Tiếc là mình chưa dùng postgresql và python cgi bao giờ nên không giúp gì được bạn lúc này. Có lẽ bạn phải nhờ đến anh Google nhiều hơn. Python không khó, nhưng chắc phải mất nhiều thời gian để trở nên thành thạo. Khi bạn thu được nhiều kinh nghiệm rồi thì hãy chia sẻ cho mọi người cùng biết. Chúc bạn thành công.

      Comment by Phạm Thị Minh Hoài — Jun 1, 2010 9:48:54 PM | #

  • Cám ơn bạn. mysql và python cgi cũng được bạn ạ. Nếu có thể bạn chia sẻ thêm. Vì mình nghĩ nó cũng tương tự như nhau. thêm được cái nữa , tìm thêm được cái nữa lưu tạm vào đây: homepages.inf.ed.ac.uk/hmueller/teaching/ad/tutorial6/display-munros.txt

    Comment by Naruto — Jun 1, 2010 11:04:40 PM | #

  • Ở trên bạn đã gọi dữ liệu từ mysql ra python rồi, bây giờ bạn có thể cho thêm nó có thể hiển thị trên nền web và có thể input dữ , sửa đổi dữ liệu trên nền web được không bạn , giống như code của trang web ta đang dùng? Xin lỗi có lẽ yêu cầu hơi quá. Nếu có gì không phải mong bạn lượng thứ.

    Comment by Naruto — Jun 1, 2010 11:07:45 PM | #

  • Ví dụ cái này chẳng hạn: Nhưng nó bị lỗi về sript_name, mình đang dùng Python3.1.2, bó tay, Hiện báo lỗi Keyerrro: SCRIPT_NAME . có thể dùng các phiên bản cũ có lẽ sẽ không bị lỗi, nhưng chẳng hiểu sao mình cứ thích dùng python 3.1.2, ngu thật.

    #!c:/python31/python

    import cgitb
    cgitb.enable()

    import os
    import sys

    import re

    print( “Content-Type: text/html\r\n\r\n”)

    1. Now print out a fairly standard HTML preamble:

    print( “”" <!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01//EN” “www.w3.org/TR/html4/strict.dtd”>
    <html>
    <head>
    <link rel=”stylesheet” type=”text/css” href=”/sXXXXXX/ad/style.css” title=”home”>
    <title>All of the Munros</title>
    </head>
    <body>
    “”")

    1. These lines should read my PostgreSQL scripting password out of a
    2. file in my web space that can only be read by my user ID, so that I
    3. don’t have to worry about getting the permissions of each script
    4. wrong…

    #FILE = open( “/public/homepages/sXXXXXXX/web/.postgresql-password”, “r” )
    #password = FILE.read().rstrip(os.linesep)
    #FILE.close()

    1. … however, if you’re confident that you haven’t made your CGI
    2. script readable by anyone except yourself, you can do something like
    3. this instead.
    1. password = ‘notactuallymypassword’
    1. ------------------------------------------------------------------------
    1. The module we use for accessing the PostgreSQL database is called
    2. pgdb.

    from pg8000 import DBAPI

    db = DBAPI.connect( user = ‘enterprisedb’,
    host = ‘localhost’,
    password = ’12345678′,
    database = ‘demo11’,
    port=5444 )

    1. We use a “cursor” for accessing the database:

    cursor = db.cursor()

    import cgi

    1. Print out the form at the top for searching through the Munros by
    2. substring…

    print( ‘’'
    <FORM ACTION=”%s” METHOD=”GET”>
    Search for a substring in the Munros’ names:
    <INPUT TYPE=”text” NAME=”matching”>
    <INPUT TYPE=”submit”>
    <INPUT TYPE=”reset”>
    </FORM>
    ‘’' % ( os.environ[’SCRIPT_NAME’] ))

    form = cgi.FieldStorage()

    if len(form.keys()) > 0:

    1. Then we’re searching for a particular Munro:

    substring = form.getvalue(”matching”)

    if substring:

    m = re.match(’^[a-zA-Z\’\- ]*$’, substring)

    if m:

    1. Then there only fairly normal characters in the supplied
    2. parameter. We still have to be careful of SQL injection
    3. attacks, since we want to allow single quotes in the
    4. search string. However, we’re going to use placeholder
    5. variables, so this should be fine.
    1. ILIKE is a non-standard PostgreSQL operator which is a
    2. case-insensitive LIKE.

    cursor.execute(”SELECT name,heightm FROM munros “ + “WHERE name ILIKE %(munro_substring)s” + “ORDER BY heightm DESC”, { “munro_substring”: “%” + substring + “%” } )

    print( “<h2>All the Munros matching: ‘” + cgi.escape(substring) + “’</h2>”)

    else:
    print( “<h2>Invalid Parameter</h2>”)
    print( “<p>There were disallowed characters in the search parameter: ‘”)
    print( cgi.escape( substring ))
    print( “’</p>”)
    sys.exit()

    else:

    cursor.execute(”SELECT name,heightm FROM munros ORDER BY heightm DESC” )

    print( “<h2>All the Munros (and one invented one)</h2>”)

    rows = cursor.fetchall()

    cursor.close()
    db.close()

    1. Print the table heading:

    print( “<table>”) print( “<tr><th>Munro Name</th><th>Height in Metres</th></tr>”)

    1. Print each row of the table.

    for row in rows: print( “<tr><td>%s</td><td>%s</td></tr>” % (row[0],row[1]))

    1. Close all the open tags,

    print( “</table></body></html>”)

    Comment by Naruto — Jun 1, 2010 11:18:08 PM | #

  • Quên mất cái code trên lấy từ nguồn: homepages.inf.ed.ac.uk/hmueller/teaching/ad/tutorial6/display-munros.txt

    Comment by Naruto — Jun 1, 2010 11:25:20 PM | #

  • Comment by naruto — Jun 2, 2010 10:26:30 AM | #

  • Hoặc cái code này chẳng hạn, nhưng vẫn bị lỗi: (mình vẫn dùng python 3.1.2)

    cái này dùng cho python 2.3: nguồn bytes.com/topic/python/answers/38463-transfer-data-webpage-form-database

    #!/pack/python-2.3.2/bin/python2.3

    from pyPgSQL import PgSQL
    import cgi
    import cgitb
    cgitb.enable()

    form = cgi.FieldStorage()

    connect = PgSQL.connect(user=”user”, password=”password”, host=”host”,
    database=”database”)
    cur = connect.cursor()
    cur.execute(’'’INSERT INTO persons (name, surname, username, password) VALUES(%s,%s, %s, %s)’'’) %(form[’name’].value, form[’surname’].value, form[’username’].value, form[’password’].value) --------------------------------------------------------------------------------------------- My question is, do I need more code to tell the program that I want to transfer the user input ( on my webpage ) to my postgresql database. --------------------------------------------------------------------------- The code from my webpage is:

    #!/pack/python-2.3.2/bin/python2.3

    from pyPgSQL import PgSQL
    import cgi
    import cgitb
    cgitb.enable()

    print ‘’'

    <html>

    <head>

    <title> Adminperson </title>

    </head>

    <body bgcolor=”#0479ff”>

    <h1><p align=”center”>Insert Person</h1></p>

    <hr>

    <form action=”insertintotable.py” method=”get”>
    <p>Name:<br><input type=”text” name=”name”></p>
    <p>Surname:<br><input type=”text” name=”surnavn”></p><p>Username:<br><input type=”text” name=”usernavn”></p><p>Password:<br><input type=”text” name=”password”></p>
    <p><input type=”submit” value=”Submit”></p>
    </body> </html>’'’

    mình thấy báo lỗi ở đoạn raise keyerror (key). Có thể còn thiếu cái trình tự , hình như là phải sắp xếp theo thứ tự để , cái này mình cũng không rõ lắm, …

    Comment by naruto — Jun 2, 2010 10:32:23 AM | #

  • Comment by Naruto — Jun 2, 2010 6:53:45 PM | #

  • Thôi bạn đừng nhìn mấy cái đoạn code ở trên rối mắt. Bạn cho mình hỏi ngắn gọn cái dòng ở dưới đây mình thiếu gì với: vì nó báo lỗi raise error(key) hoặc exec

    <code>
    #!c:/python31/python
    import cgi , os
    import sys
    import cgitb; cgitb.enable()
    print( “Content-type: text/html”)
    print()
    print( “<html><head><title>Situation snapshot</title></head><body>”)

    from pg8000 import DBAPI connect = DBAPI.connect(user=”enterprisedb”,host=”localhost”,port=5444,database=”demo11”,password=”12345678″) cur = connect.cursor()

    form = cgi.FieldStorage(environ=os.environ,keep_blank_values=1)

    if not “s_name” in form: print( ‘<h1>Simple form</h1><form action=”guicgi.py” method=”POST”>’) print( ‘Enter your name: <input name=”s_name” type=”text”><br>’) print( ‘<input name=”submit” type=”submit”></form></body></html>’) <b>cur.execute(”insert into text (text) values(’form[’s_name’].value ‘)”)</b>else: print( “<p>Your name is:”,form[’s_name’].value)

    cur.close()
    connect.close()

    print(”</body></html>”)
    </code>

    Comment by Naruto — Jun 2, 2010 6:56:09 PM | #

  • <b>cur.execute(”insert into text (text) values(’form[’s_name’].value ‘)”)</b> cái dòng này mình tưởng trong html nó sẽ đậm nên mình cho thêm <b></b>. Cái dòng này mình mới quan tâm đến vì để sao cho nó hiện chữ từ form và hiển thị bằng form[’s_name’].value bây giờ. Vì nó cứ báo lỗi raise error(key)

    Comment by Naruto — Jun 2, 2010 6:58:40 PM | #

  • Nó cứ báo lỗi self và raise error(key), lúc thì exec

    Comment by Naruto — Jun 2, 2010 6:59:40 PM | #

  • Mình chẳng khác gì mấy nhân vật lục tiên cốc gì gì đấy, trong Tiếu Ngạo Giang Hồ. Nhanh nhẩu ẩu đoảng, hồ đồ. Quanh đi quẩn lại thì thành công được một nửa. Có nghĩa là đã ghi được dữ liệu vào form rồi, nhưng là code mẫu nhìn khó hiểu quá.
    code:
    #!c:/python31/python
    ##############################################################################

    1. Python/CGI/PostgreSQL Example
    2. =============================
    3. This is a simple web application that demonstrates how you can get Python,
    4. the Python CGI module and PostgreSQL to work together. #
    5. The design of this example is based around a Model, View, Controller (MVC)
    6. pattern that is very popular in GUI and Web Application design. The main
    7. idea of this pattern is to separate the data (model), graphical (view) and
    8. logical (controller) layers. The main advantage of doing this is that each
    9. individual part can then easily be replaced or changed without affecting
    10. the other parts. For more information on this see the SEOC course notes.

    ##############################################################################

    1. Import the bits we need.
    1. The cgitb module catches errors in your CGI scripts and prints out nice
    2. HTML pages explaining where things went wrong.
      import cgitb; cgitb.enable()

    import cgi
    from pg8000 import DBAPI

    ##############################################################################

    1. In this example the database access details are hard wired into the
    2. script code itself to make the example self contained. This is generally
    3. a bad idea in any real world web application. A far better place for these
    4. to live is in some configuration file that is either read by the web
    5. application scritps, or passed into environment (e.g. environment variables)
    6. of the web application.

    host = ‘localhost’
    port = 5444

    1. You will need to change these to your specific connection details.
      user = ‘enterprisedb’
      dbname = ‘demo11’
      passwd = ’12345678′

    dsn = host + ‘:’ + dbname

    ##############################################################################

    1. Very crude view layer for MVC-like design. The idea here is that all the
    2. code to do with rendering the HTML output is encapsulated behind the
    3. interface of the View class. Ideally the HTML generation would be a little
    4. more sophisticated than print statements (e.g. a template engine or maybe
    5. something XML driven), but for this example this is adequate.

    class View:

    def __init__(self, data=[]):
    “”"Constructor.”"”
    self.data = data

    def write(self):
    “”"Write entire page out.”"”
    self.writeHTTPHeader()
    self.writeHeader()
    self.writeData()
    self.writeFooter()

    def writeHTTPHeader(self):
    “”"Write HTTP Header.”"”
    print( “Content-type: text/html\n”)

    def writeHeader(self):
    “”"Write Page Header.”"”
    print( “”"
    <html>
    <head>
    <title>Database Access Example</title>
    <style><!– table,td { border: 1px solid black; } –></style>
    </head>
    <body>
    <h1>Database Access Example</h1>
    <p>Use the follwing input box to add data to the database:</p>

    <form method=”POST”>
    Input Box:
    <input type=”text” name=”data” value=”Type something here!” /> <input type=”submit” name=”submit” value=”Submit” />
    </form>
    “”")

    def writeData(self):
    “”"Write out data table.”"”
    if self.data == None or len(self.data) == 0: print( “”" <p>There is currently no data in the database.</p>
    “”")
    else:
    print( “<table>”)
    for (code, data) in self.data:
    print( “<tr>”)
    print( ‘<td><a href=”?delete=%d”>delete</td>’ % code)
    print( “<td>%s</td>” % data)
    print( “<tr>”)
    print( “</table>”)

    def writeFooter(self):
    “”"Write Page Footer.”"”
    print( “”"
    </body>
    </html>
    “”")

    (còn nữa)

    Comment by Naruto — Jun 2, 2010 7:45:41 PM | #

  • (tiếp theo) ##############################################################################

    1. A class that wraps up a database table to act as the model layer. Similar to
    2. the encapsulation ideas used for the View layer, all the code to do with
    3. mangling the data model is hidden behind the interface for this class. All
    4. the database code for example is within this class. #
    5. Note that this code does not even attempt to deal with the exceptions that
    6. can (and will) happen if anything goes wrong accessing the database. Whether
    7. you micro manage the errors (try, except blocks everywhere) or have one high
    8. level catchall depends on what you want to present to the user when things
    9. go wrong. For development purposes letting the exceptions propegate all the
    10. way up to the cgitb module has its advantages.

    class Model:

    def __init__(self):
    “”"Constructor.”"”
    self.connection = DBAPI.connect(user=”enterprisedb”,host=”localhost”,password=”12345678″,port=5444,database=”demo11”)

    def add(self, data):
    “”"Add a data entry to the database.”"”
    cursor = self.connection.cursor()

    1. IMPORTANT! This example deliberately does not check the strings
    2. passed in from the user before evaluating them as part of the SQL
    3. query. This is to show what happens when user input is not checked
    4. before being passed in to an SQL query. To see what I mean try
    5. adding the sentence “Don’t do this!” to the database. It will break!
    6. The reason for this is that the “’” apostrophe in “don’t” is passed
    7. directly into the SQL query string without being escaped. This
    8. results in an invalid SQL query. Malicious users can exploit
    9. unchecked strings being passed to databases to extract or modify
    10. the dataset.
    1. Build up the query string. query = “INSERT INTO text (text) VALUES (’%s’);” % data cursor.execute(query)

    self.connection.commit()
    cursor.close()

    def delete(self, code): “”"Delete an entry from the data model.”"” cursor = self.connection.cursor()

    1. Build up the query string. query = “DELETE FROM example WHERE code = ‘%d’;” % int(code)

    cursor.execute(query)
    self.connection.commit()
    cursor.close()

    def fetchAll(self):
    “”"Get all the data in the database.”"”
    cursor = self.connection.cursor()
    cursor.execute(”SELECT * FROM example;”)
    data = cursor.fetchall()
    cursor.close()
    return data

    def __del__(self): “”"Things to do when the model is destroyed.”"” self.connection.close()

    (còn nữa)

    Comment by Naruto — Jun 2, 2010 7:46:32 PM | #

  • Mình ngu quá mọi người có thể tham khảo file gốc của nó ở đây : https://wiki.inf.ed.ac.uk/twiki/pub/DatabaseGroup/TeachingPythonPostgreGuide/database.cgi.txtChính là cái một cái link ở trên. Nhưng lần trước mình sửa để dùng trong Python 3.1.2 thì vẫn còn sót, thành ra bị lỗi và không thành công , cứ search google loanh quanh luẩn quẩn lại quay lại nó. Lần này sửa has_key và đã có thể tạm gọi thành công một phần là dùng được trong Python 3.1.2 . Sỡ dĩ mình phải ghi lại ở đây, một phần là đôi khi mình configure , gọi là configure cho nó oai thực ra chỉ là sửa mấy thêm mấy cái ngoặc cho lệnh print và thay if self.form.has_key(’data’) bằng if ‘data’ in self.form và if self.form.has_key(’delete’) bằng if ‘delete’ in self.form. Có thể lúc này configure được nhưng về sau không dùng đến là lại quên hết và lại mò mẫm từ đầu. Mình ngu thế đấy.

    Vẫn bị lỗi tùm lum…

    Comment by Naruto — Jun 2, 2010 7:53:22 PM | #

  • create table example(code serial8,data text, primary key (code));. Phần primary key (code) mình nghĩ là không bắt buộc lắm. Ok đó là phần PostgreSQL . Thế thôi, vì mình cũng chỉ là mới newbie mà.

    Tiếp theo sang phần code Python 3.1.2 thì mình cũng chưa thực xự hiểu toàn bộ đâu, mình đoán mình chỉ hiểu 1/10 cái đoạn code này thôi. Vì mình chỉ chăm chăm lao vào CGI thành ra bị hổng khá nhiều, nếu chịu khó tìm hiểu từ đầu theo trình tự thì đỡ vất vả hơn. Theo mình đúc kết lại trình tự tìm hiểu về Python . Từ Python 2 sau đó sang Python 3, Hoặc có thể python 3 luôn cũng được , nhưng trước hết bạn cần tìm hiểu những sự thay đổi mới trong Python 3. Hầu hết các ví dụ về Python lại là Python 2. Mình cũng không biết Python 3 có gì ưu việt hơn Python 2 cả . Thôi cứ chọn Python 3 , cứ thế mà phang thôi. Mình chỉ tâp trung vào mảng CGI , còn các mảng khác mình cảm thấy khó quá. Hoặc kiến thức mình còn quá ít nên không hiểu . Vì mới đầu mình , mục đích của mình là tập trung và Python 3. Nhưng đến khi tìm tài liệu ít quá. Ngay cả cài đặt Python 3 mình cũng không cài nổi, configure như thế nào cũng không configure được với Apache. Nản quá , thế là nhảy sang php được một thời gian. Thực ra quá trình tìm hiểu php cũng chả khác gì cưỡi ngựa xem hoa, phải nói là cưỡi máy bay xem hoa. Sau đó lại quay về Python cài đặt một loạt Python 2 lúc được lúc không, tậm tịt. Xóa đi rồi lại cài lại, nản vô cùng. Rồi chẳng biết thế nào cài Python 3 lại được . Cài được rồi chạy CGI cũng không xong. Mãi mới được. Còn WSGI chỉ được đúng cái Helloworld . thấy def điếc lằng nhằng quá, hoa cả mắt. Vì CGI nó còn tương đối đỡ hơn , có thể nó chậm hơn , nhưng chình độ còi đành chấp nhận vậy. Sau khi Python 2 và Python 3 tiếp theo là PostgreSQL và bộ driver . Nhiều quá nhỉ? thôi blah blah quá.

    , cứ lỗi thì mò mẫm , mò mẫm sửa , hiện giờ nó như thế này: <code>cái này mình mơ ước từ lâu lắm rồi, bây giờ mới chỉ được một phần nhỏ :

    Comment by naruto — Jun 2, 2010 11:21:33 PM | #

  • create table example(code serial8,data text, primary key (code));. Phần primary key (code) mình nghĩ là không bắt buộc lắm. Ok đó là phần PostgreSQL . Thế thôi, vì mình cũng chỉ là mới newbie mà.

    Tiếp theo sang phần code Python 3.1.2 thì mình cũng chưa thực xự hiểu toàn bộ đâu, mình đoán mình chỉ hiểu 1/10 cái đoạn code này thôi. Vì mình chỉ chăm chăm lao vào CGI thành ra bị hổng khá nhiều, nếu chịu khó tìm hiểu từ đầu theo trình tự thì đỡ vất vả hơn. Theo mình đúc kết lại trình tự tìm hiểu về Python . Từ Python 2 sau đó sang Python 3, Hoặc có thể python 3 luôn cũng được , nhưng trước hết bạn cần tìm hiểu những sự thay đổi mới trong Python 3. Hầu hết các ví dụ về Python lại là Python 2. Mình cũng không biết Python 3 có gì ưu việt hơn Python 2 cả . Thôi cứ chọn Python 3 , cứ thế mà phang thôi. Mình chỉ tâp trung vào mảng CGI , còn các mảng khác mình cảm thấy khó quá. Hoặc kiến thức mình còn quá ít nên không hiểu . Vì mới đầu mình , mục đích của mình là tập trung và Python 3. Nhưng đến khi tìm tài liệu ít quá. Ngay cả cài đặt Python 3 mình cũng không cài nổi, configure như thế nào cũng không configure được với Apache. Nản quá , thế là nhảy sang php được một thời gian. Thực ra quá trình tìm hiểu php cũng chả khác gì cưỡi ngựa xem hoa, phải nói là cưỡi máy bay xem hoa. Sau đó lại quay về Python cài đặt một loạt Python 2 lúc được lúc không, tậm tịt. Xóa đi rồi lại cài lại, nản vô cùng. Rồi chẳng biết thế nào cài Python 3 lại được . Cài được rồi chạy CGI cũng không xong. Mãi mới được. Còn WSGI chỉ được đúng cái Helloworld . thấy def điếc lằng nhằng quá, hoa cả mắt. Vì CGI nó còn tương đối đỡ hơn , có thể nó chậm hơn , nhưng chình độ còi đành chấp nhận vậy. Sau khi Python 2 và Python 3 tiếp theo là PostgreSQL và bộ driver . Nhiều quá nhỉ? thôi blah blah quá.

    , cứ lỗi thì mò mẫm , mò mẫm sửa , hiện giờ nó như thế này: <code>cái này mình mơ ước từ lâu lắm rồi, bây giờ mới chỉ được một phần nhỏ :

    Comment by naruto — Jun 2, 2010 11:21:36 PM | #

  • có những đoạn có thể thừa , nhưng thôi kệ , tôn trọng tác giả , mới cả mình làm ăn cũng khá là cẩu thả, hứng lên thì làm, lúc oải rồi , mình cũng cảm thấy oải quá: vì không biết code lại như thế nào để dữ nguyên định dạng, bạn cứ chiếu theo bản gốc trong đường link ở trên tạm vậy: #!c:/python31/python ##############################################################################

    1. Python/CGI/PostgreSQL Example
    2. =============================
    3. This is a simple web application that demonstrates how you can get Python,
    4. the Python CGI module and PostgreSQL to work together. #
    5. The design of this example is based around a Model, View, Controller (MVC)
    6. pattern that is very popular in GUI and Web Application design. The main
    7. idea of this pattern is to separate the data (model), graphical (view) and
    8. logical (controller) layers. The main advantage of doing this is that each
    9. individual part can then easily be replaced or changed without affecting
    10. the other parts. For more information on this see the SEOC course notes.

    ##############################################################################

    1. Import the bits we need.
    1. The cgitb module catches errors in your CGI scripts and prints out nice
    2. HTML pages explaining where things went wrong.
      import cgitb; cgitb.enable()

    import cgi
    from pg8000 import DBAPI

    ##############################################################################

    1. In this example the database access details are hard wired into the
    2. script code itself to make the example self contained. This is generally
    3. a bad idea in any real world web application. A far better place for these
    4. to live is in some configuration file that is either read by the web
    5. application scritps, or passed into environment (e.g. environment variables)
    6. of the web application.

    host = ‘localhost’
    port = 5444

    1. You will need to change these to your specific connection details.
      user = ‘enterprisedb’
      dbname = ‘demo11’
      passwd = ’12345678′

    dsn = host + ‘:’ + dbname

    Comment by naruto — Jun 2, 2010 11:25:10 PM | #

  • ##############################################################################

    1. Very crude view layer for MVC-like design. The idea here is that all the
    2. code to do with rendering the HTML output is encapsulated behind the
    3. interface of the View class. Ideally the HTML generation would be a little
    4. more sophisticated than print statements (e.g. a template engine or maybe
    5. something XML driven), but for this example this is adequate.

    class View:

    def __init__(self, data=[]):
    “”"Constructor.”"”
    self.data = data

    def write(self):
    “”"Write entire page out.”"”
    self.writeHTTPHeader()
    self.writeHeader()
    self.writeData()
    self.writeFooter()

    def writeHTTPHeader(self):
    “”"Write HTTP Header.”"”
    print( “Content-type: text/html\n”)

    def writeHeader(self):
    “”"Write Page Header.”"”
    print( “”"
    <html>
    <head>
    <title>Database Access Example</title>
    <style><!– table,td { border: 1px solid black; } –></style>
    </head>
    <body>
    <h1>Database Access Example</h1>
    <p>Use the follwing input box to add data to the database:</p>

    <form method=”POST”>
    Input Box:
    <input type=”text” name=”data” value=”Type something here!” /> <input type=”submit” name=”submit” value=”Submit” />
    </form>
    “”")

    def writeData(self):
    “”"Write out data table.”"”
    if self.data == None or len(self.data) == 0: print( “”" <p>There is currently no data in the database.</p>
    “”")
    else:
    print( “<table>”)
    for (code, data) in self.data:
    print( “<tr>”)
    print( ‘<td><a href=”?delete=%a”>delete</td>’ % code)
    print( “<td>%s</td>” % data)
    print( “<tr>”)
    print( “</table>”)

    def writeFooter(self):
    “”"Write Page Footer.”"”
    print( “”"
    </body>
    </html>
    “”")

    Comment by naruto — Jun 2, 2010 11:26:00 PM | #

  • ##############################################################################

    1. A class that wraps up a database table to act as the model layer. Similar to
    2. the encapsulation ideas used for the View layer, all the code to do with
    3. mangling the data model is hidden behind the interface for this class. All
    4. the database code for example is within this class. #
    5. Note that this code does not even attempt to deal with the exceptions that
    6. can (and will) happen if anything goes wrong accessing the database. Whether
    7. you micro manage the errors (try, except blocks everywhere) or have one high
    8. level catchall depends on what you want to present to the user when things
    9. go wrong. For development purposes letting the exceptions propegate all the
    10. way up to the cgitb module has its advantages.

    class Model:

    def __init__(self):
    “”"Constructor.”"”
    self.connection = DBAPI.connect(user=”enterprisedb”,host=”localhost”,password=”12345678″,port=5444,database=”demo11”)

    def add(self, data):
    “”"Add a data entry to the database.”"”
    cursor = self.connection.cursor()

    1. IMPORTANT! This example deliberately does not check the strings
    2. passed in from the user before evaluating them as part of the SQL
    3. query. This is to show what happens when user input is not checked
    4. before being passed in to an SQL query. To see what I mean try
    5. adding the sentence “Don’t do this!” to the database. It will break!
    6. The reason for this is that the “’” apostrophe in “don’t” is passed
    7. directly into the SQL query string without being escaped. This
    8. results in an invalid SQL query. Malicious users can exploit
    9. unchecked strings being passed to databases to extract or modify
    10. the dataset.
    1. Build up the query string. query = “INSERT INTO example (data) VALUES (’%s’);” % data cursor.execute(query)

    self.connection.commit()
    cursor.close()

    def delete(self, code): “”"Delete an entry from the data model.”"” cursor = self.connection.cursor()

    1. Build up the query string. query = “DELETE FROM example WHERE code = ‘%d’;” % int(code)

    cursor.execute(query)
    self.connection.commit()
    cursor.close()

    def fetchAll(self):
    “”"Get all the data in the database.”"”
    cursor = self.connection.cursor()
    cursor.execute(”SELECT * FROM example;”)
    data = cursor.fetchall()
    cursor.close()
    return data

    def __del__(self): “”"Things to do when the model is destroyed.”"” self.connection.close()

    ##############################################################################

    1. This class controls the logic of the application. It is responsible for
    2. interpreting the requests from the user and then manipulating the model
    3. before telling the View layer it is to take over the work.

    class Controller:

    def __init__(self):
    “”"Constructor.”"”

    1. Extract the HTML Form values from the HTTP POST/GET. self.form = cgi.FieldStorage()
    1. Create an instance of the model.
      self.model = Model()

    def handleRequest(self):
    “”"Handle a HTTP request.”"”

    1. This is where you might add more logic to look for other possible
    2. actions to perform on the data model. A common approach is to add
    3. an “action” variable to the HTML form that the controller can then
    4. use to work out what action is being requested (e.g. add, edit,
    5. delete). This example does things the easy way.
      if ‘data’ in self.form:
      self.model.add(self.form.getfirst(’data’,’Nothing was added!’))

    if ‘delete’ in self.form: self.model.delete(self.form.getfirst(’delete’, None))

    1. Once we’ve dealt with any actions to perform, pass on control to the
    2. View layer to actually write out the page.
      self.renderView()

    def renderView(self): “”"Call the view object to render/write out the page.”"”

    1. In many MVC implementations the View would access the Model
    2. directly. If the Model class in this example implemented the python
    3. list interface we could pass the model directly into the View. This
    4. would make the code less readable though so for this example we
    5. break the clean MVC pattern and hack the python list object out
    6. of the model and pass it into the View. Same result, but not quite
    7. as clean (look up MVC-push and MVC-pull for more on this).
      view = View(self.model.fetchAll())
      view.write()

    ##############################################################################

    1. Application entry point.

    if __name__ == “__main__”:

    1. Bootstrap the controller object.
      Controller().handleRequest()

    ##############################################################################

    Comment by Naruto — Jun 2, 2010 11:26:42 PM | #

  • Mới biết python mà bạn đã đi ngay vào làm python cgi và database thì chắc là sẽ gặp nhiều khó khăn, thôi thì phải cố gắng vậy. Python 3 khác python 2 nhiều lắm, đặc biệt python 3 hỗ trợ unicode thông suốt và loại bỏ các rắc rối của tiếng Việt trong python 2. Các bạn mới học Python nên tiếp cận python 3 ngay từ đầu. Tuy nhiên mình vẫn dùng python 2.5 và đa số các thư viện quan trọng mà mình dùng hiện vẫn chưa hỗ trợ python 3 (MySQLdb chẳng hạn). Chắc mình sẽ còn dùng python bản 2.5 thêm vài năm nữa.

    Comment by Phạm Thị Minh Hoài — Jun 3, 2010 9:22:03 AM | #

  • Cám ơn bạn đã cho ý kiến. Cám ơn bạn rất nhiều.

    Comment by Naruto — Jun 3, 2010 11:48:31 AM | #

  • Cuối cùng gần một năm trời , bỏ rồi lại theo đuổi , rồi khó quá chuyển sang php rồi lại quyến luyến quay về python mới tìm được một cái gần như ý mình. Chỉ có điều tài liệu từ 2006 . Nhưng đúng cái mình cần. Một cái gần giống như guestbook bằng Python , chạy trên cơ sở dữ liệu PostgreSQL. Chi tiết tại đây: mail.python.org/pipermail/tutor/2006-January/044275.html. Chỉ có điều mới chỉnh sửa được một nửa, vì cái này lại chạy trên python 2, mình lại đang dùng Python 3.1.2 . Nhưng code của nó cũng không có khác biệt gì hoàn toàn chạy ổn , chỉ có điều không biết khởi tạo cái bảng members và bảng divisions sao cho ổn. Nó vẫn chưa hoàn thiện, vẫn bị lỗi và không thành công.

    Comment by Naruto — Jun 8, 2010 8:06:29 PM | #

  • Cho mình hỏi download MySQL-python cho python 2.5 và 32 bit ở đâu vậy,

    Comment by konquer_htm — Jul 2, 2010 5:15:37 PM | #

  • www.google.com/Top/Computers/Programming/Languages/Python/Modules/Databases_and_Persistence/Database_API/

    bạn thử tham khảo trang trên xem sao. Hy vọng có cái bạn cần.

    Comment by naruto — Jul 24, 2010 6:33:03 AM | #