2010-08-04 20 views
8

Zanim wszyscy wskazaliście mi here imoje inne. Więc zacząłem otrzymywać słynny błąd po przejściu na mój serwer produkcyjny.Django Filtrowanie ostrzeżeń MySQL

django/db/backends/mysql/base.py: 86: Uwaga: Dane obcinane na kolumnie 'ślimak' w rzędzie 1

Pierwszą czynnością było rozpocząć guglanie to po tym jak ustalona problem. Aby to naprawić, zmodyfikowałem oba modele, aby uzyskać maksymalną długość 128 reklam, a następnie zaktualizowałem tabele SQL, aby je dopasować. Ale problem utrzymywał się. Nieco pewny, że naprawiłem problem, pomyślałem, że równie dobrze zacznę je filtrować. Na samym szczycie mojego skryptu umieściłem to.

# Get rid of the MySQLdb warnings 
import warnings 
import MySQLdb 
with warnings.catch_warnings(): 
    warnings.filterwarnings("ignore", category=MySQLdb.Warning) 

I z przyjemnością przekazałem to do produkcji. Zgadnij co - zgadłeś, że problem pozostał. I co teraz. Szybko tracę pewność, że faktycznie naprawiłem problem, ale podwójne sprawdzenie tego pokazuje, że wszystkie kolumny ślimaków mają długość 128 znaków. Co więcej, zawinęłam się do błędu, jeśli jest dłuższa niż 128 i nadal nic. Więc 2 pytania:

  1. Jak mogę paznokci w dół, co operacja jest słabnącym to. tj. gdzie w moim kodzie flaga jest podnoszona?

  2. Jak mogę je odfiltrować? Moja poprawka nie działa? Czy to naprawdę ostrzeżenie MySQLdb lub django.db.mysql.base?

Dzięki i radosne hakowanie Django!

Dla tych, którzy mają pytania dotyczące struktury ..

CREATE TABLE `people_employee` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `name` varchar(100) DEFAULT NULL, 
    `email` varchar(75) DEFAULT NULL, 
    `location_id` varchar(100) DEFAULT NULL, 
    `jpeg` longtext, 
    `first_name` varchar(100) DEFAULT NULL, 
    `last_name` varchar(100) DEFAULT NULL, 
    `maildomain` varchar(32) DEFAULT NULL, 
    `mailserver` varchar(32) DEFAULT NULL, 
    `mailfile` varchar(64) DEFAULT NULL, 
    `contractor` tinyint(1) NOT NULL, 
    `temporary` tinyint(1) NOT NULL, 
    `formal_name` varchar(100) DEFAULT NULL, 
    `nickname` varchar(32) DEFAULT NULL, 
    `cell_phone` varchar(32) DEFAULT NULL, 
    `office_phone` varchar(32) DEFAULT NULL, 
    `other_phone` varchar(32) DEFAULT NULL, 
    `fax` varchar(32) DEFAULT NULL, 
    `assistant_id` int(11) DEFAULT NULL, 
    `supervisor_id` int(11) DEFAULT NULL, 
    `is_supervisor` tinyint(1) NOT NULL, 
    `department_id` varchar(100) DEFAULT NULL, 
    `division_id` varchar(100) DEFAULT NULL, 
    `section_id` varchar(100) DEFAULT NULL, 
    `job_classification_id` varchar(100) DEFAULT NULL, 
    `functional_area_id` varchar(100) DEFAULT NULL, 
    `position_id` varchar(100) DEFAULT NULL, 
    `notes_url` varchar(200) DEFAULT NULL, 
    `ldap_active` tinyint(1) NOT NULL, 
    `notes_active` tinyint(1) NOT NULL, 
    `created_at` datetime NOT NULL, 
    `last_update` datetime NOT NULL, 
    `is_active` tinyint(1) NOT NULL, 
    `site_id` int(11) NOT NULL, 
    `slug` varchar(128) DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `slug` (`slug`), 
    KEY `people_employee_location_id` (`location_id`), 
    KEY `people_employee_assistant_id` (`assistant_id`), 
    KEY `people_employee_supervisor_id` (`supervisor_id`), 
    KEY `people_employee_department_id` (`department_id`), 
    KEY `people_employee_division_id` (`division_id`), 
    KEY `people_employee_section_id` (`section_id`), 
    KEY `people_employee_job_classification_id` (`job_classification_id`), 
    KEY `people_employee_functional_area_id` (`functional_area_id`), 
    KEY `people_employee_position_id` (`position_id`), 
    KEY `people_employee_site_id` (`site_id`) 
) ENGINE=MyISAM AUTO_INCREMENT=1429 DEFAULT CHARSET=latin1; 

a odpowiednim models.py.

slug = models.SlugField(max_length=128, editable=False, unique=True) 

nadzieję, że pomoże ..

+0

Czy pole (s) dane te mogą pochodzić z zostały nałożone limity tekstowe? –

+0

Nie - ustawiam slug przy zapisie. Wyciągam ostrzeżenie, jeśli długość wynosi> 128 (ale to nie jest ...). – rh0dium

+0

Czy możesz opublikować dane wyjściowe tabeli "opisz" (z pola produkcyjnego) i Modelu, którego używasz? –

Odpowiedz

3

Najpierw bym Odradzamy ostrzeżeń filtrujących takich jak ten: ten błąd jest generowany przez MySQL i to absolutnie oznacza, że ​​tracą dane.

Pierwszą rzeczą do zrobienia byłoby użycie polecenia opisywania MySQL, aby upewnić się, że kolumna bazy danych jest rzeczywiście zdefiniowana do tego samego rozmiaru, jakiego się spodziewasz: Django nie obsługuje migracji baz danych, jeśli zmienisz długość kolumny więc jeśli pole ślimak był coraz krótszy, niż jest teraz, że trzeba ręcznie zmieniać tabelę, aby ustawić nową długość:

mysql> DESCRIBE my_table slug; 
+-------+--------------+------+-----+---------+-------+ 
| Field | Type   | Null | Key | Default | Extra | 
+-------+--------------+------+-----+---------+-------+ 
| slug | varchar(255) | NO | UNI | NULL |  | 
+-------+--------------+------+-----+---------+-------+ 
1 row in set (0.00 sec) 

Jeśli to pole nie było to, czego oczekiwać można po prostu rozwiązać ten problem aktualizacja długości kolumny:

mysql> ALTER TABLE my_table MODIFY slug VARCHAR(255) NOT NULL; 

Jeśli zezwalasz na znaki Unicode w twoich wtyczkach, to może to również wyjaśnić, ponieważ Twój zrzut powyżej wydaje się używać zestawu znaków latin1, a nie UTF-8 - pojedynczy znak UTF-8 może zawierać do 4 bajtów danych, co oznacza, że ​​wartość tak krótkich jak 17 bajtów może przepełnić VARCHAR(64).

Jeden krok następny debugowanie to prosta wariacja na wezwanie robisz filtrować ostrzeżenia, aby dowiedzieć się dokładnie, gdzie błędy są dzieje:

warnings.simplefilter("error", category=MySQLdb.Warning) 

To sprawi, że ostrzeżenie śmiertelne, która zatrzyma swój program, ale co ważniejsze, wytworzy również ślad stosu. Z czymś takim, zobaczysz poniższy wynik:

#!/usr/bin/env python 
import warnings 

def foo(): 
    warnings.warn("uhoh") 

def bar(): 
    foo() 

def main(): 
    warnings.simplefilter("error", UserWarning) 
    bar() 

if __name__ == "__main__": 
    main() 

Bez zaproszenia simplefilter:

cadams[email protected]:~ $ python test_warnings.py 
test_warnings.py:5: UserWarning: uhoh 
    warnings.warn("uhoh") 

z zaproszenia simplefilter:

[email protected]:~ $ python test_warnings.py 
Traceback (most recent call last): 
    File "test_warnings.py", line 15, in <module> 
    main() 
    File "test_warnings.py", line 12, in main 
    bar() 
    File "test_warnings.py", line 8, in bar 
    foo() 
    File "test_warnings.py", line 5, in foo 
    warnings.warn("uhoh") 
UserWarning: uhoh 
+0

Wow - Opowiedz o odrodzeniu! Dobra robota! Już go rozwiązałem (nie udało się zaktualizować tej strony). To był problem UTF-8/łaciński, o którym wspomniałeś. Co za PITA, to go znaleźć. Świetne wskazówki tutaj! – rh0dium

1

Chciałbym edytować settings.py mojego projektu plik, aby to zachowanie mogło się zdarzyć w całym moim projekcie django. W przeciwnym razie mógłbym po prostu uwzględnić to w części skryptu, gdzie chcę, aby to zachowanie się zdarzyło.


Ostrzeżenia Raise MySQL jako błędy:

import warnings, MySQLdb 
warnings.filterwarnings('error', category=MySQLdb.Warning) 

ignorować zamiast podniesienia błąd, wymień "error" z "ignore".

obchodzić je w try-z wyjątkiem bloku jak:

try: 
    # a MySQL DB operation that raises a warning 
    # for example: a data truncated warning 
except Warning as a_warning: 
    # do something here 
Powiązane problemy