ďťż

[Python/Django]Problem z polskimi znakami

       

Podstrony


telcocafe

Witam, mam problem z polskimi znakami w dokumencie.

Mimo ustawienia przez dreamweavera kodowania dokumentu na "UTF-8" i wrzuceniu jako pierwszą linijkę dokumentu:
# -*- coding: utf-8 -*-
użycie w dokumencie polskiego znaku (przykładowo "ł") powoduje wyświetlenie komunikatu:


Non-ASCII character '\xb3'

Co jeszcze mogę tu zrobić?



A co dokładnie wyrzuca taki wyjątek? Jakiś print albo inna operacja?

1. Jeżeli używasz np. MySQL sprawdź czy baza i tabele korzystają z kodowania utf-8. Czasami globalne ustawienia MySQL mogą wymuszać latin-1.
2. Stringi unikodowe należy oznaczać literką "u":
pint u'to jest unikod'

W urls.py dałem:
(r'cos/$', 'widok', {'zmienna': u'zażółć gęślą jaźń'}),
i przy próbie wejścia w "coś" wyświetla błędy (django).

Dziwny przykład. Zmienne w urls.py, domyślnie mapowane z podanych URLi nie zawierają w normalnych przypadkach znaków diakrytycznych i innych niezbyt mile widzianych w adresach URL.

Samo użycie takiej konstrukcji błędu nie powinno generować. Domyślne kodowanie łańcuchów w Pythonie ustawisz tworząc plik sitecustomize.py w katalogu Pythona (w przypadku Linuksa jest to np. /usr/lib*/python*/) o kodzie:
import sys sys.setdefaultencoding('utf-8')
To powinno zapewnić że napisy będą traktowane zawsze w kodowaniu utf-8.



Problem tkwi w tym, że nie mam dostępu do folderu pythona na moim serwerze.
A znaki diakrytyczbe w urls.py to nie URL tylko zmienne wykorzystywane w szablonach.

A mogę wiedzieć dlaczego umieszczasz je w urls.py a nie w samych widokach, np. w render_to_response, albo w TEMPLATE_CONTEX_PROCESSOR dla szablonowych zmiennych globalnych? Trzymając poprawną konstrukcję aplikacji będzie ona działać tak jak "gwarantuje" to jakość frameworka. (A "generic views" konfigurowane na poziomie urli to rozwiązanie bardzo prostych czynności, a nie zastępstwo widoków z N-zmiennymi.)
Użytkownik Riklaunim edytował ten post 14 grudzień 2009, 14:08
Tutaj podałem tylko taki przykład, ale podam inny - mam formularz z województwami.
User wybiera sobie województwo dolonośląskie i próbuję filtrować bazę danych wg podanego województwa i się sypie bo z formularza przyszły dane z polskimi znakami.

A sprawdziłeś np. kodowanie bazy danych, o czym pisałem w pierwszym poście? Coś Ci nie działa (dlaczego akurat tylko tobie), gdzieś tam się sypie - nie podajesz kody, pełnego wyjątku. Wszystko co ma polskie znaki musi być oznaczone jako unikod.

Mam zmienić to kodowanie przez PMA czy przez django? Bo widzę, że faktycznie mam przy "Metoda porównywania napisów" wartość "latin2_general_ci".

Ale myślę, że nie w tym tkwi problem bo jeśli na sucho w pliku .py wrzucę "Dane.filter(wojewodztwo= u'dolnośląskie')" to i tak sypie błędem:


UnicodeDecodeError at /DJango/

'utf8' codec can't decode byte 0xb6 in position 0: unexpected code byte


Zmienić możesz w phpmyadmin, czy przez konsolę MySQL ;) dowolnie.

Zmieniłem to, i nadal sie sypie.
Mam na przykład taką linijkę:
wojewodztwo = request.POST[u"wojewodztwo"]
w tym widoku wykonuję pewną operację na tabeli oraz przekierowuję użytkownika dalej zawierając województwo w zmiennych GET.
No i otrzymuję taki komunikat:
'ascii' codec can't encode characters in position 31-32: ordinal not in range(128), HTTP response headers must be in US-ASCII format

Coś kombinujesz że masz takie błędy. Poza tym wklejasz jedną linijkę kodu, a po tym jeszcze fragment wyjątku i tak na prawdę nie wiadomo co i dlaczego wygenerowało ten wyjątek. Warto też napisać jakiej konfiguracji serwera używasz i na jakim systemie.

PS. "polskie" kodowanie nie jest zalecane, typu request.POST[u"wojewodztwo"]

To jak powinienem to przyjąć, żeby zmienne z formularzy - te z polskimi znakami przypisać do zmiennych w django bez sypania?

Kodowanie bazy utf-8 i gotowe. Co do kluczy słowników, czy nazw zmiennych to należy stosować wyłącznie znaki ascii i najlepiej stosować nazewnictwo anglojęzyczne (jeżeli chcesz pisać kod dobrej jakości).

W bazy już jest UTF-8, ale dalej się sypie przy tym u"".
Jak wygląda składnia z tymi znakami ascii, albo tego anglojęzycznego nazewnictwa?

Wersja anglojęzyczna
region = request.POST['region']
Jeżeli masz stronę HTML kodowaną w UTF-8 (a powinieneś) to wartości nie trzeba specjalnie unikodować. Za wyjątkami operacji na napisach:
print u'Województwo: %s' % region

Też powinieneś walidować dane. Dla klasy zwykłego formularza
form = TwojFormularz(request.POST) if form.is_valid(): data = form.cleaned_data region = data['region'] # zrobić coś z daną i przekierować

czy dla formularza opartego o model:
form = TwojFormularz(request.POST) if form.is_valid(): form.save() # przekierowanie

A co, jeżeli dane przychodzą z innej strony (nie napisanej w django)?
Nie korzystam więc tam z systemu formularzy Django, lecz zwykły form z HTMLa, jak tam przesłać te polskie znaki?

Dane są przesyłane albo POST, albo GET i oba źródła lub własne słowniki możesz użyć w systemie formularzy.

Jeżeli zewnętrzna strona, która wysyła formularz nie jest kodowana w unikodzie to dane, które przyszły można zakodować za pomocą funkcji encode lub decode w zależności od sytuacji.
Użytkownik Riklaunim edytował ten post 18 grudzień 2009, 20:08
Cały czas mam błąd:


Exception Type: UnicodeEncodeError
Exception Value: 'ascii' codec can't encode character u'\u015b' in position 36: ordinal not in range(128), HTTP response headers must be in US-ASCII format

Unicode error hint
The string that could not be encoded/decoded was: dolnośląski


Dane przychodzą z pliku kodowanego UTF-8. Nie rozumiem co jest nie tak.
Próbowałem też funkcją unicode() ale wtedy otrzymywałem "decoding Unicode is not supported".

Masz trzy opcje do przetestowania:
zmienna = unicode(zmienna) zmienna = zmienna.decode('utf-8') zmienna = zmienna.encode('utf-8')

Przy pierwszym mam:
'ascii' codec can't encode character u'\u015b' in position 36: ordinal not in range(128), HTTP response headers must be in US-ASCII format

Przy drugim:
'ascii' codec can't encode character u'\u015b' in position 5: ordinal not in range(128)

Przy trzecim:
'ascii' codec can't decode byte 0xc5 in position 5: ordinal not in range(128)

A co ty robisz z tymi danymi że w pierwszym przypadku wywala ci wyjątek w nagłówkach? Pokaż więcej kodu aplikacji

PS. polecam też http://forum.python.org.pl
Użytkownik Riklaunim edytował ten post 20 grudzień 2009, 21:13
def filter_redirect(request, **kwargs): wojewodztwo = request.POST["wojewodztwo"] wojewodztwo = wojewodztwo.decode('utf-8') return HttpResponseRedirect('/filter/'+wojewodztwo+"/1/")
To mój widok.
Nie wiem jaki jeszcze kod chciałbyś żebym wkleił.
Użytkownik Nazwarisz edytował ten post 21 grudzień 2009, 14:17
No i problem rozwiązany. Adresy URL nie sprzyjają stosowaniu polskich znaków diakrytycznych (i innych nie-ascii też). Stwórz np. słownik gdzie kluczami będą nazwy województw bez polskich znaków, a wartościami zwykłe nazwy. W URL stosujesz wersję uproszczoną (slug), a w kodzie do filtrowania wersję normalną poprzez ten słownik.

Hmm, to trochę dziwne bo jak wpiszę ten adres z polskimi znakami w przeglądarce to działa bez problemowo z polskimi znakami.
Tylko przy przekierowywaniu się pluje.

Znaki specjalne w URLach to kwestia ich kodowania przez przeglądarkę i obsługi przez serwer. Nie chcesz mieć problemów - nie używaj. ;)

w ostateczności spróbuj może to przejdzie (ale to proszenie się o problemy):
return HttpResponseRedirect(u'/filter/%s/1/' % wojewodztwo)
Użytkownik Riklaunim edytował ten post 22 grudzień 2009, 16:37
  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • nvm.keep.pl

  • Sitedesign by AltusUmbrae.