【问题标题】:Integrity error - get_or_create says cannot be NULL on importing data完整性错误 - get_or_create 说在导入数据时不能为 NULL
【发布时间】:2013-10-31 15:28:14
【问题描述】:

我问过a question to try and fix an issue 我不明白如何正确使用 ForeignKeys。这是非常有帮助的修复,虽然我在django.db.utils.IntegrityError: core_team.blahblah_id may not be NULL 遇到了一个后续问题并且我决定回滚,做一些稍微简单的事情 - 为了避免双重查找(比赛与团队和联赛相关),我会写一个管理命令来导入团队。

根据我对上一个问题的(明显有缺陷的)理解,我做对了——它使用get_or_create 来检查联赛实例,然后根据它分配球队。我还仔细检查了数据库是否是最新的(我正在向南运行并在上次更改方案时进行了前向迁移,从那时起没有任何变化。最后的更改是使两个模型中的名称成为主键(因为每个名字只有一支球队,每个名字只有一个联赛。)

最近,我添加了代码来为团队 get_or_create 部分提供默认值,但我收到了同样的错误。我理解错误的原因(我认为) - Team 中的 ForeignKey 'league' 已经存在于数据库中,并且不能为空插入另一个团队(来自 https://docs.djangoproject.com/en/1.5/ref/models/querysets/#get-or-create),只是不是如何解决它。

管理命令:

from django.core.management.base import BaseCommand, CommandError
import csv
import csvImporter
#from core.models import Match
from time import strptime
from datetime import datetime

master_data = open ('/Users/chris/Desktop/AllDataTruncated.csv', 'r') 
data = list(tuple(rec) for rec in csv.reader(master_data, delimiter=','))

from core.models import League, Team

team_list = []
for row in data:

    if row[2] == "HomeTeam":
        print "Continuing"
        continue
    elif row[2] == "":
        print "Continuing"
        continue
    else:
        league, _ = League.objects.get_or_create(name=row[0])
        print league
        team, _ = Team.objects.get_or_create(team_name=row[2], defaults={'league':league})
        current_team = Team(league = league, team_name=team)

    print current_team 

以及models.py的相关部分:

class League (models.Model):
    name = models.CharField(max_length=2, primary_key=True)
    last_modified = models.CharField(max_length=50)
    def __unicode__(self):
        return unicode(self.name)

class Team(models.Model):
    team_name = models.CharField(max_length=50, primary_key=True)
    league = models.ForeignKey(League)
    team_colour = models.CharField(max_length=6, null=True, blank=True)
    def __unicode__(self):
        return unicode (self.team_name)

完整的回溯是:

$ python manage.py importteams
Continuing
E0
Traceback (most recent call last):
  File "manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/core/management/__init__.py", line 453, in execute_from_command_line
    utility.execute()
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/core/management/__init__.py", line 392, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/core/management/__init__.py", line 272, in fetch_command
    klass = load_command_class(app_name, subcommand)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/core/management/__init__.py", line 77, in load_command_class
    module = import_module('%s.management.commands.%s' % (app_name, name))
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/utils/importlib.py", line 35, in import_module
    __import__(name)
  File "/Users/chris/Dropbox/Django/gmblnew/core/management/commands/importteams.py", line 26, in <module>
    team2, _ = Team.objects.get_or_create(team_name=row[3])
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/manager.py", line 146, in get_or_create
    return self.get_query_set().get_or_create(**kwargs)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/query.py", line 487, in get_or_create
    six.reraise(*exc_info)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/query.py", line 477, in get_or_create
    obj.save(force_insert=True, using=self.db)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/base.py", line 546, in save
    force_update=force_update, update_fields=update_fields)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/base.py", line 650, in save_base
    result = manager._insert([self], fields=fields, return_id=update_pk, using=using, raw=raw)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/manager.py", line 215, in _insert
    return insert_query(self.model, objs, fields, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/query.py", line 1661, in insert_query
    return query.get_compiler(using=using).execute_sql(return_id)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 937, in execute_sql
    cursor.execute(sql, params)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/backends/util.py", line 41, in execute
    return self.cursor.execute(sql, params)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/backends/sqlite3/base.py", line 364, in execute
    six.reraise(utils.IntegrityError, utils.IntegrityError(*tuple(e.args)), sys.exc_info()[2])
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/backends/sqlite3/base.py", line 362, in execute
    return Database.Cursor.execute(self, query, params)
django.db.utils.IntegrityError: core_team.league_id may not be NULL

现在 - 我认为它在这里说 League_id 很奇怪,因为这应该不再相关了?当我进行迁移时,问题出现了:

 ? The field 'League.id' does not have a default specified, yet is NOT NULL.
 ? Since you are removing this field, you MUST specify a default
 ? value to use for existing rows. Would you like to:
 ?  1. Quit now.
 ?  2. Specify a one-off value to use for existing columns now
 ?  3. Disable the backwards migration by raising an exception; you can edit the migration to fix it later
 ? Please select a choice: 3

这是导致这个问题长期存在的原因吗?

编辑:似乎没有。删除了 DB 并移动了 South migrations 文件夹,它仍在执行此操作。源 CSV 也很好(没有空行或空字符串/段),上面的代码有一个部分可以跳过这些段;它没有那么远。

【问题讨论】:

  • 你能放下你的数据库再试一次吗?
  • 这样做了,并从一个完全空白的数据库开始(运行syncdb 然后migrate。迁移给出...Running migrations for core: - Migrating forwards to 0005_auto__del_field_team_id__chg_field_team_team_name__add_unique_team_tea. &gt; core:0001_initial &gt; core:0002_auto__chg_field_match_away_shots_on_target__chg_field_match_full_time_ &gt; core:0003_auto__chg_field_match_away_shots_on_target__chg_field_match_full_time_ 之后运行 importteams 给出相同的错误:django.db.utils.IntegrityError: core_team.league_id may not be NULL跨度>
  • 这就是为什么我,呃,“非常不喜欢”南方:迁移地狱。如果您的所有数据都保存在 CSV 中,并且准备好导入程序:将您的 migrations 目录移动到 /tmp 或其他东西,从一个新的数据库开始,然后重试。如果这样可以解决问题,请用火杀死迁移目录。
  • 好的,试过了,没用,同样的错误。值得注意的是 - 当我在空白数据库上运行它时,它会正确创建一个新的联赛对象 - 运行 importteams 后现在 E0 就在那里,当我尝试将一个团队分配给数据库。
  • 您的文件中是否有空行,或者row[0]'' 的行?

标签: python-2.7 csv model django-south django-1.5


【解决方案1】:

呃。对于任何其他稍后会来的新手来说,这个问题的答案实际上非常简单。我在这里所做的是在“团队”表中创建一个条目,该表有一个可以返回“联盟”的 ForeignKey。

“技巧”(这不是技巧,只是在文档中解释得很糟糕,恕我直言)是,当您为 Team 对象执行 get_or_create 时,您需要明确地将联赛传回。这不仅仅是匹配团队名称

我以为我已经做到了,但我没有,看来。此代码有效(并且非常有效地确保没有重复):

for row in data:

    if row[2] == "HomeTeam":
        print "Continuing"
        continue
    elif row[2] == "":
        print "Continuing"
        continue
    else:
        league, _ = League.objects.get_or_create(name=row[0])
        print league
        team, _ = Team.objects.get_or_create(team_name=row[2], league=league)
        current_team = Team(league = league, team_name=team)
    print current_team 

【讨论】:

    猜你喜欢
    • 2013-10-22
    • 1970-01-01
    • 1970-01-01
    • 2014-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多