MySQL i mod_python
W tym How To opiszę sposób używania baz MySQL w Pythonie.
I. Czego potrzebujemy
- Poprawnie skonfigurowany mod_python.
- Skonfigurowany moduł MySQLdb dla Pythona.
- Znajomość Pythona jak na poziomie how to nr1 ( tutaj )
- Podstawowa znajomość MySQL
II. Problemy już na samym początku
Może zdarzyć się ze MySQLdb jest skonfigurowany w taki sposób, że pliki tymczasowe domyślnie odnoszone są do /tmp/egg.
Wtedy nasza aplikacja web zwróci błąd o braku praw dostępu do ww. katalogu.
Trzeba zmienną PYTHONEGGCACHE wskazać na katalog do którego mamy pełny dostęp ( na przykład ~/tmp ).
W tym celu najprościej w naszej aplikacji web w pierwszych linijkach ustawić należy tą zmienną:
1 2 | from os import environ environ['PYTHON_EGG_CACHE']='/pelna/sciezka/do/katalogu/' |
III. Podłączanie się do bazy
1 2 3 4 5 6 | import MySQLdb from MySQLdb import cursors db=MySQLdb.connect(host=host,user=user, passwd=haslo,db=nazwa_bazy, use_unicode=False, charset='latin1', cursorclass=MySQLdb.cursors.DictCursor) |
Linie 1 - 2: bez komentarza.
Linie 3 - 6: Jest to jedno polecenie rozbite w linie na potrzeby formatowania tekstu w how to. Ustalamy parametry naszego połączenia z bazą danych. Oprócz 3 ostatnich parametrów powinno być wszystko jasne.
- use_unicode - parametr informujący MySQL czy chcemy używać unicode.
- charset - parametr ustawiający kodowanie znaków w MySQL nie zważając na poszczególne kodowania w tabelach bazy danych ( nie stosować jeśli use_unicode=True )
- cursorclass - w tym przypadku ustawiam kursor bazy danych który w wyniku zwraca tuplę dwuelementową: słownik z wartościami wynikowymi, oraz ilość pasujących wyników ( jak len())
IV. Wykonanie zapytania
1 2 3 | c=db.cursor() c.execute("""komenda MySQL""", (wartosci, do, przypisania)) |
Linia 1 : zainicjowanie kursora
Linia 2 : wykonanie zapytania do MySQL.
V. Przykład zapytania
Poprawnie:
1 2 3 4 5 6 | c=db.cursor() c.execute("""SELECT autor,tresc FROM post WHERE id=%s AND typ=%s""", (2, norm)) wart=c.fetchall()[0] c.close() |
Nie poprawnie:
1 2 3 4 5 6 | c=db.cursor() c.execute("""SELECT autor,tresc FROM post WHERE id=%s AND typ=%s"""%(2, norm)) wart=c.fetchall()[0] c.close() |
Różnice ?:
Na pierwszy rzut oka żadne oprócz znaku po “”". Otóż używając powodujemy, że argumenty pobierane z tupli wartości ( w naszym przypadku (2, norm) ) pobierane są jako string, więc ktoś w łatwy sposób może wykonać praktycznie dowolną komendę ( SQL injection ), po prostu NIE UŻYWAĆ znaku % w wypadku wykonywania zapytań SQL.
Składnia “poprawna” automatycznie “zabezpiecza” niebezpieczne znaki, między innymi poprzez dodawanie znaku \, powoduje ona, że znaki te traktowane są bez żadnych specjalnych, przypisanych im własności w składni MySQL.
Dzięki wart=c.fetchall()[0] pobieramy wszystkie wyniki jakie zwróciło zapytanie. wart jest słownikiem ( wart[0][’tresc’] zwraca nam treść pierwszej pobranej pary autor, tresc, wart[1][’autor’] - autora drugiej itd)
Dlaczego c.fetchall()[0] ?: Samo c.fetchall() zwraca tuplę 2 elementową, pożądane przez nas wartości oraz ilość par wartości które zostały pobrane ( ilość można pobrać też na przykład poprzez: len=c.execute(”"”komenda MySQL”"”) )
Dostępne jest też przydatne:
1 | c.fetchone() |
Które pobiera tylko jeden wynik.
Ale NIE zastępuje opcji LIMIT 1 w SQL.
Koniec
To by było na tyle.
W razie wątpliwości proszę pisać.
Kolejne How To niedługo.