0

我有一个 Django 模型,其中包含限制为 128 个字符的产品字段:

class SKU(models.Model):
    ...
    product = models.CharField(max_length=128, null=True, blank=False)
    ...

在应用程序的某一时刻,我读入了一些用户数据并从中制作了一个 SKU,然后保存。事实证明,有时进入产品字段的数据超过了 128 个字符的指定大小。当 Apache 通过 WSGI 为我的应用程序提供服务时,sku.save()命令会发出以下警告:

/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/backends/mysql/base.py:114: Warning: Data truncated for column 'product' at row 1 

……但仅此而已,一个警告。sku 被保存,product字段的内容被截断为 128 个字符。但是,当我使用 Django 的内置测试服务器对此进行测试时,sku.save()命令会导致崩溃,并且会出现以下(缩写)堆栈跟踪:

File "/Library/WebServer/Documents/acdc_cmd/trunk/promotions/promo_parsers.py", line 467, in createKitsAndContents  

theSKU.save()

File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/base.py", line 463, in save
self.save_base(using=using, force_insert=force_insert, force_update=force_update)
...
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/backends/mysql/base.py", line 114, in execute  
return self.cursor.execute(query, args)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/MySQL_python-1.2.4b4-py2.7-macosx-10.6-intel.egg/MySQLdb/cursors.py", line 204, in execute
if not self._defer_warnings: self._warning_check()
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/MySQL_python-1.2.4b4-py2.7-macosx-10.6-intel.egg/MySQLdb/cursors.py", line 117, in _warning_check
warn(w[-1], self.Warning, 3)
Warning: Data truncated for column 'product' at row 1

在这种情况下,sku.save()会使程序崩溃。这意味着导入操作的结果在测试服务器上和由 Apache 服务时是不同的。我有以下问题:

  1. 在这两个(Apache 与测试服务器)案例中,Django 如何做不同的事情?
  2. 有没有办法在我的代码中明确指出:保存这个sku,根据模型定义截断字段就可以了?
  3. 有没有更好的方法来处理这个?

Wrt #3,我可以想象自省模型的字段定义,并在尝试保存之前手动截断字符串;但这很麻烦。我怀疑有一种前门方法可以做到这一点,但我找不到。

4

1 回答 1

1

确实是一个奇怪的情况。我的建议在这里:

首先,你应该尽量避免这种情况。无论apache是​​否正确保存数据,您都应该尝试删除所有警告。

最好的方法是截断所有相关位置的数据。不难也不乱。

首先,我建议您javascript在表单中包含一些代码,以便尽快向用户反馈他做错了什么。在客户端代码安全的情况下,您应该继续并添加该行

product=forms.CharField(max_length=128 ...)

SKUForm(无论它是正常Form的还是ModelForm. 我知道你说过自省模型会非常混乱,但这可能是一个严重的安全问题,所以值得这样做。你可以手动截断覆盖save方法的字符串你的模型或你的形式 - 如果你真的感到偏执,或者两者兼而有之:)。

做这样的事情会简单得多:

request.POST['product']=request.POST['product'][:128]

但遗憾的是这不起作用,因为 request.POST 是类型QueryDict并且是不可变的,所以你不能修改它。您可以将字典复制到一个新字典并将该对象传递给表单而不是 request.POST 但我不知道什么会更混乱。

很抱歉,我不知道为什么 Django 在生产/开发环境中表现不同。我知道旧版本的 MySql 的行为方式与您描述的方式相同(如果 varchar 比指定的长,则截断,新版本禁止这样做,但您不能打开它来扭曲数据库引擎中的一些内部设置。

我希望这有帮助。祝你好运!

于 2013-05-09T23:39:51.683 回答