2013-10-22 55 views
0

我詢問a question to try and fix an issue我當時不知道如何正確使用ForeignKeys。儘管我後來遇到了django.db.utils.IntegrityError: core_team.blahblah_id may not be NULL的問題,但我決定回滾,做一些稍微簡單的事情 - 爲了避免雙重查找(匹配與團隊和聯盟相關聯),我會寫一個管理命令導入團隊。完整性錯誤 - get_or_create在導入數據時不能爲NULL

在上一個問題中我明顯有缺陷的理解,我已經做對了 - 它使用get_or_create來檢查聯盟實例,然後根據該實例分配團隊。我還重新檢查過數據庫是否是最新的(我正在向南運行,並且在我最後一次更改方案時進行了向前遷移,此後沒有任何更改,最後更改是將兩個模型中的名稱都作爲主鍵因爲每個名稱只有一個團隊,每個名稱只有一個團隊。)

最近,我添加了代碼以向團隊get_or_create部分提供默認值,但是我收到了同樣的錯誤,我理解導致(我認爲)的錯誤 - 該團隊中的ForeignKey'聯盟'已經存在於數據庫中,並且不能爲null插入另一個團隊(從https://docs.djangoproject.com/en/1.5/ref/models/querysets/#get-or-create),而不是如何解決它。命令:

models.py的
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 

及相關位:

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 

這是什麼永久性的這個問題?

編輯:似乎沒有。丟棄了數據庫並移動了南遷移文件夾,但它仍在執行。源CSV也很好(沒有空行或空字符串/分段),並且上面的代碼有一段可以跳過這些分段;它沒有那麼遠。

+1

您可以直接刪除數據庫並重試嗎? –

+0

這樣做,並開始一個完全空白的數據庫(運行'syncdb',然後'migrate'。migrate given ...'運行核心遷移: - 正向遷移到0005_auto__del_field_team_id__chg_field_team_team_name__add_unique_team_tea。 >核心:0001_initial >核心:0002_auto__chg_field_match_away_shots_on_target__chg_field_match_full_time_ >核心:0003_auto__chg_field_match_away_shots_on_target__chg_field_match_full_time_' 運行importteams給出了同樣的錯誤後:'django.db.utils.IntegrityError:core_team.league_id可能不NULL' – Withnail

+1

這就是爲什麼我,呃,「強烈不喜歡」南方:遷徙地獄。如果無論如何你都有CSV數據並且準備好導入程序:將你的'migrations'目錄移動到'/ tmp'或其他東西,從一個新的數據庫開始,然後重試。如果解決了這個問題,請使用fire來終止遷移目錄。 –

回答

1

呃。對於此後的任何其他新手來說,答案實際上是十分簡單的。我在這裏做的是在「團隊」表中創建一個條目,該條目的外鍵將返回到「聯盟」。 '技巧'(這不是一個技巧,只是在文檔中非常糟糕地解釋,imho)是當你爲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