【问题标题】:How can _meta.local_fields not match the table schema in the database?_meta.local_fields 如何与数据库中的表模式不匹配?
【发布时间】:2010-02-06 16:09:49
【问题描述】:

我完全不明白为什么 _meta.local_fields 返回的字段比数据库表包含的字段多。 User 模型继承自 contrib.auth.models.User。

$ mysql -u user -p database  
Enter password:   
Reading table information for completion of table and column names  
You can turn off this feature to get a quicker startup with -A  

Welcome to the MySQL monitor.  Commands end with ; or \g.  
Your MySQL connection id is 1240032  
Server version: 5.0.77 Source distribution  

mysql> describe auth_user;  
+--------------------+------------------+------+-----+---------+----------------+  
| Field              | Type             | Null | Key | Default | Extra          |  
+--------------------+------------------+------+-----+---------+----------------+  
| id                 | int(11)          | NO   | PRI | NULL    | auto_increment |   
| username           | varchar(30)      | NO   | UNI | NULL    |                |   
| first_name         | varchar(30)      | NO   |     | NULL    |                |   
| last_name          | varchar(30)      | NO   |     | NULL    |                |   
| email              | varchar(75)      | NO   |     | NULL    |                |   
| password           | varchar(128)     | NO   |     | NULL    |                |   
| is_staff           | tinyint(1)       | NO   |     | NULL    |                |   
| is_active          | tinyint(1)       | NO   |     | NULL    |                |   
| is_superuser       | tinyint(1)       | NO   |     | NULL    |                |   
| last_login         | datetime         | NO   |     | NULL    |                |   
| date_joined        | datetime         | NO   |     | NULL    |                |   
| email_isvalid      | tinyint(1)       | NO   |     | NULL    |                |   
| email_key          | varchar(16)      | YES  |     | NULL    |                |   
| reputation         | int(10) unsigned | NO   |     | NULL    |                |   
| gravatar           | varchar(32)      | NO   |     | NULL    |                |   
| gold               | smallint(6)      | NO   |     | NULL    |                |   
| silver             | smallint(6)      | NO   |     | NULL    |                |   
| bronze             | smallint(6)      | NO   |     | NULL    |                |   
| questions_per_page | smallint(6)      | NO   |     | NULL    |                |   
| last_seen          | datetime         | NO   |     | NULL    |                |   
| real_name          | varchar(100)     | NO   |     | NULL    |                |   
| website            | varchar(200)     | NO   |     | NULL    |                |   
| location           | varchar(100)     | NO   |     | NULL    |                |   
| date_of_birth      | date             | YES  |     | NULL    |                |   
| about              | longtext         | NO   |     | NULL    |                |   
+--------------------+------------------+------+-----+---------+----------------+  
25 rows in set (0.00 sec)  

从 Django 错误页面,这是产生错误的 SQL 语句:异常值:(1110,“列'about'指定两次”)

'INSERT INTO `auth_user` (`username`, `first_name`, `last_name`, `email`, `password`, `is_staff`, `is_active`, `is_superuser`, `last_login`, `date_joined`,     `email_isvalid`, `email_key`, `reputation`, `gravatar`, `gold`, `silver`, `bronze`, `questions_per_page`, `last_seen`, `real_name`, `website`, `location`, `date_of_birth`, `about`, `email_isvalid`, `email_key`, `reputation`, `gravatar`, `gold`, `silver`, `bronze`, `questions_per_page`, `last_seen`, `real_name`, `website`, `location`, `date_of_birth`, `about`) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)'     

这个 SQL 语句似乎是通过迭代 User._meta.local_fields 生成的。
我不明白为什么 _meta.local_fields 与实际的用户表架构不匹配。

$ python2.5 manage.py shell  
Python 2.5.4 (r254:67916, Aug  5 2009, 12:42:40)   
[GCC 4.1.2 20080704 (Red Hat 4.1.2-44)] on linux2  
Type "help", "copyright", "credits" or "license" for more information.  
(InteractiveConsole)  
>>> from forum.models import User  
>>> len(User._meta.local_fields)  
39  
>>> import pprint  
>>> pprint.pprint(User._meta.local_fields)  
[<django.db.models.fields.AutoField object at 0x852c80c>,  
 <django.db.models.fields.CharField object at 0x8528c4c>,  
 <django.db.models.fields.CharField object at 0x8528cac>,  
 <django.db.models.fields.CharField object at 0x8528d0c>,  
 <django.db.models.fields.EmailField object at 0x8528d6c>,  
 <django.db.models.fields.CharField object at 0x8528e2c>,  
 <django.db.models.fields.BooleanField object at 0x8528ecc>,  
 <django.db.models.fields.BooleanField object at 0x8528f6c>,  
 <django.db.models.fields.BooleanField object at 0x852c02c>,  
 <django.db.models.fields.DateTimeField object at 0x852c0ac>,  
 <django.db.models.fields.DateTimeField object at 0x852c0ec>,  
 # here is where customizations to User begin.
 <django.db.models.fields.BooleanField object at 0x861744c>,  
 <django.db.models.fields.CharField object at 0x861732c>,  
 <django.db.models.fields.PositiveIntegerField object at 0x861746c>,  
 <django.db.models.fields.CharField object at 0x861748c>,  
 <django.db.models.fields.SmallIntegerField object at 0x861784c>,  
 <django.db.models.fields.SmallIntegerField object at 0x86178ec>,  
 <django.db.models.fields.SmallIntegerField object at 0x861792c>,  
 <django.db.models.fields.SmallIntegerField object at 0x861796c>,  
 <django.db.models.fields.DateTimeField object at 0x861798c>,  
 <django.db.models.fields.CharField object at 0x86179cc>,  
 <django.db.models.fields.URLField object at 0x8617a0c>,  
 <django.db.models.fields.CharField object at 0x8617a4c>,  
 <django.db.models.fields.DateField object at 0x8617a8c>,  
 <django.db.models.fields.TextField object at 0x8617acc>,  
 # this seems to be a duplicate of the fields added to User
 <django.db.models.fields.BooleanField object at 0x862ab2c>,  
 <django.db.models.fields.CharField object at 0x862a4ac>,  
 <django.db.models.fields.PositiveIntegerField object at 0x862ab6c>,  
 <django.db.models.fields.CharField object at 0x862f6cc>,  
 <django.db.models.fields.SmallIntegerField object at 0x861782c>,  
 <django.db.models.fields.SmallIntegerField object at 0x862fa2c>,  
 <django.db.models.fields.SmallIntegerField object at 0x862fa4c>,  
 <django.db.models.fields.SmallIntegerField object at 0x862fa8c>,  
 <django.db.models.fields.DateTimeField object at 0x862faac>,  
 <django.db.models.fields.CharField object at 0x862faec>,  
 <django.db.models.fields.URLField object at 0x862fb2c>,  
 <django.db.models.fields.CharField object at 0x862fb6c>,  
 <django.db.models.fields.DateField object at 0x862fbac>,  
 <django.db.models.fields.TextField object at 0x862fbec>]  

模型的附加字段就这样添加了:

User.add_to_class('email_isvalid', models.BooleanField(default=False))  
User.add_to_class('email_key', models.CharField(max_length=16, null=True))  
User.add_to_class('reputation', models.PositiveIntegerField(default=1))  
User.add_to_class('gravatar', models.CharField(max_length=32))  
User.add_to_class('email_feeds', generic.GenericRelation(EmailFeed))  
User.add_to_class('favorite_questions', models.ManyToManyField(Question, through=FavoriteQuestion, related_name='favorited_by'))  
User.add_to_class('badges', models.ManyToManyField(Badge, through=Award, related_name='awarded_to'))  
User.add_to_class('gold', models.SmallIntegerField(default=0))  
User.add_to_class('silver', models.SmallIntegerField(default=0))  
User.add_to_class('bronze', models.SmallIntegerField(default=0))  
User.add_to_class('questions_per_page', models.SmallIntegerField(choices=QUESTIONS_PER_PAGE_CHOICES, default=10))  
User.add_to_class('last_seen', models.DateTimeField(default=datetime.datetime.now))  
User.add_to_class('real_name', models.CharField(max_length=100, blank=True))  
User.add_to_class('website', models.URLField(max_length=200, blank=True))  
User.add_to_class('location', models.CharField(max_length=100, blank=True))  
User.add_to_class('date_of_birth', models.DateField(null=True, blank=True))  
User.add_to_class('about', models.TextField(blank=True))  

我认为 .add_to_class 方法可能是这个问题的一部分。

【问题讨论】:

    标签: python django django-models


    【解决方案1】:

    如果您展示了与此问题相关的 Django 模型,将会很有帮助。从 SQL 中的字段名称来看,这个模型似乎继承自 contrib.auth.models.User,是这样吗?如果是这样,您是否碰巧重复了 User 模型中定义的字段名称?

    更新:更坦率地说,我要求您编辑您的问题并包含您在 models.py 文件中声明的特定模型。几乎可以肯定,您已经声明了两个具有相同名称的字段。 auth.models.User 中声明的最后一个字段是 date_joined,因此 两个 about 的定义应该出现在你的模型声明中。

    实际上,再次仔细检查您的 SQL,您不仅有两列名为 about,而且其中有大约 14 个重复的字段名称。有点不对劲。

    套用 Jerry McGuire 的话说:给我看看模型! :-)

    第二次更新(使用 1 杯啤酒的差点(这是好东西!))

    我从来没有以这种方式使用过 add_to_class。为什么你走这条路而不使用更标准的Django model inheritance 技术之一?或者,既然这是您正在处理的用户,为什么不使用 UserProfile。它可能有点笨拙,但效果很好。

    第三次更新

    啊,Domini Nabisco,我的儿子——我不知道你是从别人那里继承来的。提醒一句:因为这改变了 Django 中的一个基本类(以一种明显的非标准方式),您可能需要查看 .py 文件 中对 user 的每一个引用模板。根据继承项目的大小,这可能是一个巨大 PITA,尤其是当它缺少测试时。您是否有机会追捕,我的意思是找到负责人并获得更多见解?这可能是让事情顺利进行的捷径。祝你好运!

    【讨论】:

    • 模型确实继承自 contrib.auth.models.User
    • 我想知道 User.add 到类是否会被解释两次。这是一个开源项目,CNPROG @ Github。我没有创建它。使用 UserProfile 或继承 User 似乎会更好。我现在必须重构它。该项目没有测试,所以我可能必须先创建这些。不久前我确实听说 MySQLdb 和 MySQL 接口存在问题,但我不知道版本。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-12-26
    • 2020-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多