2010-08-04 5 views
8

Avant que vous me pointer tous à here et here le mien un peu différent. J'ai donc commencé à recevoir la fameuse erreur après être passé sur mon serveur de production.Django Filtrage Mises en garde MySQL

django/db/backend/mysql/base.py: 86: Avertissement: Les données tronquées pour la colonne 'limaces' à la ligne 1

La première chose que j'ai été commencer googler cela après je fixe le problème. Pour résoudre ce problème, j'ai modifié les deux modèles pour avoir une max_length de 128 ad puis mis à jour les tables SQL pour le faire correspondre. Mais le problème a persisté .. Un peu confiant que j'ai réellement résolu le problème, j'ai pensé que je ferais aussi bien commencer à les filtrer. Donc, en haut de mon script, j'ai placé ceci.

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

Et j'ai heureusement poussé cela à la production. Devinez quoi - vous l'avez deviné, le problème est resté. Et maintenant. Je perds rapidement confiance que j'ai effectivement résolu le problème mais une double vérification montre que toutes les colonnes slug ont 128 caractères. En outre, j'ai enveloppé sluggify à l'erreur si elle est plus longue que 128 et toujours rien. Donc, 2 questions:

  1. Comment puis-je clouer quelle opération faiblit cela. c'est-à-dire où dans mon code le drapeau est-il levé?

  2. Comment les filtrer? Ma solution ne fonctionne pas? Est-ce vraiment un avertissement MySQLdb ou un avertissement django.db.mysql.base?

Merci et joyeux piratage de Django!

Pour ceux qui ont des questions sur la structure ..

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; 

Et le models.py pertinent.

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

espoir qui aide ..

+0

sont le champ (s) ces données peuvent provenir ont des limites de texte imposé? –

+0

Non - Je suis en train de régler le slug sur save. Je pousse un avertissement si la longueur est> 128 (mais ce n'est pas ..). – rh0dium

+0

Pouvez-vous poster la sortie de 'describe' de votre table (de la boîte de production) et le modèle que vous utilisez? –

Répondre

3

D'abord, je recommande fortement contre les avertissements de filtrage comme celui-ci: cette erreur est générée par MySQL et cela signifie absolument vous perdez des données. La première chose à faire est d'utiliser la commande MySQL describe pour vous assurer que votre colonne de base de données est réellement définie à la taille que vous attendez: Django ne supporte pas les migrations de base de données si vous changez la longueur d'une colonne donc si votre champ slug est toujours plus courte que maintenant vous auriez besoin de modifier manuellement la table pour régler la nouvelle longueur:

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

Si ce champ n'était pas ce que vous vous attendiez pouvez simplement résoudre le problème en mise à jour de la longueur de la colonne:

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

Si vous autorisez les caractères Unicode dans vos limaces, cela pourrait également expliquer que votre sauvegarde ci-dessus semble utiliser le jeu de caractères latin1 plutôt que UTF-8 - un seul caractère UTF-8 peut contenir jusqu'à 4 octets de données, ce qui signifie qu'une valeur aussi court que 17 octets pourraient déborder un VARCHAR(64).

Une étape de débogage suivante est une simple variation sur l'appel que vous faites pour filtrer les avertissements pour savoir exactement où vos erreurs se produisent:

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

Cela rendra le fatal avertissement, qui arrêtera votre programme, mais plus important encore produira également un stacktrace. Avec quelque chose comme ça, vous verrez la sortie ci-dessous:

#!/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() 

Sans l'appel simplefilter:

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

Avec l'appel 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 - Parler d'un renouveau! Bon travail! Je l'avais déjà résolu (pas mis à jour ce site). C'était le problème UTF-8/Latin que vous avez mentionné. Quelle PITA c'était pour le trouver. De bons indices ici cependant! – rh0dium

1

J'éditeriez mon projet settings.py fichier pour laisser ce comportement se produire à travers mon projet django entier. Sinon, je pourrais simplement l'inclure dans une partie du script où je veux que ce comportement se produise.


Raise Avertissements MySQL comme des erreurs:

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

Pour ne pas tenir compte au lieu de soulever une erreur, REPLACE "error" avec "ignore".

les manipuler dans un essai-except comme:

try: 
    # a MySQL DB operation that raises a warning 
    # for example: a data truncated warning 
except Warning as a_warning: 
    # do something here 
Questions connexes