Django过滤MySQL警告

rh0*_*ium 8 python django django-models

之前大家指出我在这里这里挖掘有点不同.所以我转移到我的生产服务器后开始出现这个着名的错误.

django/db/backends/mysql/base.py:86:警告:第1行的'slug'列数据被截断

我做的第一件事就是在解决问题后开始谷歌搜索.为了解决这个问题,我调整了两个模型,使其max_length为128,然后更新SQL表以匹配它. 但问题仍然存在. 有点确信我确实解决了这个问题,我认为我也可以开始过滤它们.所以在我的脚本的顶部我放置了这个.

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

我很乐意将其推向生产阶段.猜猜是什么 - 你猜对了问题依然存在.那么现在怎么办.我很快就失去了信心,我确实解决了这个问题,但仔细检查表明所有的slug列都是128个字符长.此外,如果长度超过128而且仍然没有,我将sluggify包装为错误.那2个问题:

  1. 我怎样才能确定哪些操作标志着这一点.即我的代码中的哪个标志被提升了?

  2. 我怎么能真正过滤掉这些?我的修复不起作用?这真的是MySQLdb警告还是django.db.mysql.base警告?

谢谢和快乐Django黑客!

对于那些对结构有疑问的​​人..

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;
Run Code Online (Sandbox Code Playgroud)

和相关的models.py.

slug = models.SlugField(max_length=128, editable=False, unique=True)
Run Code Online (Sandbox Code Playgroud)

希望有所帮助..

Chr*_*ams 3

首先,我强烈建议不要过滤这样的警告:这个错误是由 MySQL 生成的,它绝对意味着您正在丢失数据。

\n\n

要做的第一件事是使用 MySQL 描述命令来确保您的数据库列实际上定义为您期望的相同大小:如果您更改列的长度,Django 不支持数据库迁移,因此如果您的slug 字段比现在短,您需要手动更改表以设置新长度:

\n\n
mysql> DESCRIBE my_table slug;\n+-------+--------------+------+-----+---------+-------+\n| Field | Type         | Null | Key | Default | Extra |\n+-------+--------------+------+-----+---------+-------+\n| slug  | varchar(255) | NO   | UNI | NULL    |       |\n+-------+--------------+------+-----+---------+-------+\n1 row in set (0.00 sec)\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果该字段不是您所期望的,您可以通过更新列长度来简单地解决问题:

\n\n
mysql> ALTER TABLE my_table MODIFY slug VARCHAR(255) NOT NULL;\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果您允许在 slugs 中使用 Unicode 字符,这也可以解释为上面的转储似乎使用latin1字符集而不是UTF-8 \xe2\x80\x93 单个 UTF-8 字符最多可以是 4 个字节的数据,这意味着短至 17 个字节的值可能会溢出VARCHAR(64).

\n\n

下一个调试步骤是对您正在进行的调用进行简单的变体,以过滤警告以准确找出错误发生的位置:

\n\n
warnings.simplefilter("error",  category=MySQLdb.Warning)\n
Run Code Online (Sandbox Code Playgroud)\n\n

这将使警告致命,这将停止您的程序,但更重要的是还会产生堆栈跟踪。通过类似的操作,您将看到以下输出:

\n\n
#!/usr/bin/env python\nimport warnings\n\ndef foo():\n    warnings.warn("uhoh")\n\ndef bar():\n    foo()\n\ndef main():\n    warnings.simplefilter("error", UserWarning)\n    bar()\n\nif __name__ == "__main__":\n    main()\n
Run Code Online (Sandbox Code Playgroud)\n\n

没有 simplefilter 调用:

\n\n
cadams@Io:~ $ python test_warnings.py \ntest_warnings.py:5: UserWarning: uhoh\n  warnings.warn("uhoh")\n
Run Code Online (Sandbox Code Playgroud)\n\n

使用 simplefilter 调用:

\n\n
cadams@Io:~ $ python test_warnings.py \nTraceback (most recent call last):\n  File "test_warnings.py", line 15, in <module>\n    main()\n  File "test_warnings.py", line 12, in main\n    bar()\n  File "test_warnings.py", line 8, in bar\n    foo()\n  File "test_warnings.py", line 5, in foo\n    warnings.warn("uhoh")\nUserWarning: uhoh\n
Run Code Online (Sandbox Code Playgroud)\n