Ошибка целостности - get_or_create говорит, что не может быть NULL при импорте данных

Я задал вопрос, чтобы попытаться исправить возникшую проблему, когда я не понимал, как правильно использовать ForeignKeys. Это было очень полезно исправить, хотя у меня была последующая проблема с django.db.utils.IntegrityError: core_team.blahblah_id may not be NULL и я решил откатиться назад, сделать что-то немного проще - чтобы избежать двойного поиска (матч связан как с командой, так и с лигой), я бы написал команду управления для импорта команд.

По моему (явно ошибочному) пониманию из предыдущего вопроса, я все сделал правильно - он использует get_or_create проверить наличие экземпляра лиги, а затем назначить команду на основе этого. Я также дважды проверил, что БД обновлена ​​(я бегу на юг и выполнил прямую миграцию в последний раз, когда я менял схему, с тех пор ничего не изменилось. Последнее изменение состояло в том, чтобы сделать имена в обеих моделях первичным ключом (поскольку есть только одна команда каждого имени, только одна лига каждого имени.)

Совсем недавно я добавил код для обеспечения значения по умолчанию для раздела команды get_or_create, но получаю ту же ошибку. Я понимаю причину (я думаю) ошибки - то, что "лига" ForeignKey в Team уже существует в базе данных, и не может быть пустым, вставляя другую команду (с https://docs.djangoproject.com/en/1.5/ref/models/querysets/), только не как это исправить.

Команда управления:

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

Это то, что увековечивает эту проблему?

Изменить: кажется нет. Удалил БД и переместил папку миграций на юг, и она все еще делает это. Исходный CSV также хорош (без пустых строк или пустых строк / сегментов), и в коде выше есть раздел, чтобы пропустить эти сегменты в любом случае; это не так далеко.

1 ответ

Решение

Тьфу. Ответ на этот вопрос для любого другого новичка, который придет к нему позже, на самом деле смехотворно прост. Здесь я создаю запись в таблице "Команда", в которой ForeignKey возвращается в "Лигу".

"Уловка" (это не уловка, просто очень плохо объясненная в документации, imho) заключается в том, что вам нужно явно передавать лигу обратно, когда вы выполняете get_or_create для объекта Team. Речь идет не только о соответствии названия команды

Я думал, что сделал это, но я не сделал, кажется. Этот код работает (и достаточно эффективно обеспечивает отсутствие дубликатов):

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 
Другие вопросы по тегам