2015-05-19 74 views
4

我有三個Django模型之間的關係如下:跨多個模型定義關係 - Django的

class TestCase(models.Model): 
     ''' 
     Define the testcase model. A testcase is a python Class 
     which contains a set of tests 
     ''' 
     name = models.BinaryField(blank=False) 
     filename = models.BinaryField(blank=True) 
     run_flag = models.IntegerField(default=0) 
     run_as_root = models.BooleanField(default=0) 
     num_tests = models.IntegerField(default=0) 
     testsuite = models.ForeignKey(TestSuite) 

     def __str__(self): 
      return self.name 

請忽略TestSuite:它不是這個問題很重要。每個TestCase是你可以想象的:一個TestCase(班級)。所以每次一個執行TestCase它有一個TestExecutionResult

class Result(models.Model): 
     ''' 
     Define the result of a testcase. It may be 'PASS', 'FAIL', 
     'SKIPPED' or 'ABORTED' 
     ''' 
     FAIL = 0 
     PASS = 1 
     ABORTED = 2 
     SKIPPED = 3 

     Status = (
      (PASS, 'PASS'), 
      (FAIL, 'FAIL'), 
      (SKIPPED, 'SKIPPED'), 
      (ABORTED, 'ABORTED'), 
     ) 

     status = models.IntegerField(choices=Status, default=FAIL) 

     testcase = models.ForeignKey(TestCase) 


    class TestExecution(models.Model): 

     name = models.BinaryField(blank=False) 
     num_testsuites = models.IntegerField(default=0) 
     time = models.FloatField() 
     date = models.DateTimeField(default=django.utils.timezone.now) 

     result = models.OneToOneField(Result) 

     def __str__(self): 
      return self.name + " : " + self.date + " : " + self.time 

,可以說,一個TestCasehasManyResultResultTestExecution之間的關係是OneToOne。我的模型模式存在一些問題。我知道一個簡單的解決辦法是mergeResultTestExecution

python manage.py migrate 
Operations to perform: 
    Synchronize unmigrated apps: staticfiles, messages 
    Apply all migrations: admin, autotester, contenttypes, auth, sessions 
Synchronizing apps without migrations: 
    Creating tables... 
    Running deferred SQL... 
    Installing custom SQL... 
Running migrations: 
    Rendering model states... DONE 
    Applying autotester.0005_auto_20150519_1831...Traceback (most recent call last): 
    File "manage.py", line 10, in <module> 
    execute_from_command_line(sys.argv) 
    File "/usr/local/lib/python2.7/dist-packages/django/core/management/__init__.py", line 338, in execute_from_command_line 
    utility.execute() 
    File "/usr/local/lib/python2.7/dist-packages/django/core/management/__init__.py", line 330, in execute 
    self.fetch_command(subcommand).run_from_argv(self.argv) 
    File "/usr/local/lib/python2.7/dist-packages/django/core/management/base.py", line 390, in run_from_argv 
    self.execute(*args, **cmd_options) 
    File "/usr/local/lib/python2.7/dist-packages/django/core/management/base.py", line 441, in execute 
    output = self.handle(*args, **options) 
    File "/usr/local/lib/python2.7/dist-packages/django/core/management/commands/migrate.py", line 221, in handle 
    executor.migrate(targets, plan, fake=fake, fake_initial=fake_initial) 
    File "/usr/local/lib/python2.7/dist-packages/django/db/migrations/executor.py", line 110, in migrate 
    self.apply_migration(states[migration], migration, fake=fake, fake_initial=fake_initial) 
    File "/usr/local/lib/python2.7/dist-packages/django/db/migrations/executor.py", line 147, in apply_migration 
    state = migration.apply(state, schema_editor) 
    File "/usr/local/lib/python2.7/dist-packages/django/db/migrations/migration.py", line 115, in apply 
    operation.database_forwards(self.app_label, schema_editor, old_state, project_state) 
    File "/usr/local/lib/python2.7/dist-packages/django/db/migrations/operations/fields.py", line 62, in database_forwards 
    field, 
    File "/usr/local/lib/python2.7/dist-packages/django/db/backends/mysql/schema.py", line 43, in add_field 
    super(DatabaseSchemaEditor, self).add_field(model, field) 
    File "/usr/local/lib/python2.7/dist-packages/django/db/backends/base/schema.py", line 403, in add_field 
    self.execute(sql, params) 
    File "/usr/local/lib/python2.7/dist-packages/django/db/backends/base/schema.py", line 111, in execute 
    cursor.execute(sql, params) 
    File "/usr/local/lib/python2.7/dist-packages/django/db/backends/utils.py", line 79, in execute 
    return super(CursorDebugWrapper, self).execute(sql, params) 
    File "/usr/local/lib/python2.7/dist-packages/django/db/backends/utils.py", line 64, in execute 
    return self.cursor.execute(sql, params) 
    File "/usr/local/lib/python2.7/dist-packages/django/db/utils.py", line 97, in __exit__ 
    six.reraise(dj_exc_type, dj_exc_value, traceback) 
    File "/usr/local/lib/python2.7/dist-packages/django/db/backends/utils.py", line 64, in execute 
    return self.cursor.execute(sql, params) 
    File "/usr/local/lib/python2.7/dist-packages/django/db/backends/mysql/base.py", line 124, in execute 
    return self.cursor.execute(query, args) 
    File "/usr/local/lib/python2.7/dist-packages/MySQLdb/cursors.py", line 205, in execute 
    self.errorhandler(self, exc, value) 
    File "/usr/local/lib/python2.7/dist-packages/MySQLdb/connections.py", line 36, in defaulterrorhandler 
    raise errorclass, errorvalue 
django.db.utils.IntegrityError: (1062, "Duplicate entry '0' for key 'result_id'") 

什麼關於模型架構進行最適當的方式?

添加autotester/migrations/0005_auto_20150519_1831.py爲每個請求:

# - - 編碼:UTF-8 - - 從未來進口unicode_literals

從django.db進口車型,遷移

類遷移(migrations.Migration):

dependencies = [ 
     ('autotester', '0004_auto_20150519_1744'), 
    ] 

    operations = [ 
     migrations.RemoveField(
      model_name='testexecution', 
      name='framework', 
     ), 
     migrations.AddField(
      model_name='testexecution', 
      name='result', 
      field=models.OneToOneField(default=None, to='autotester.Result'), 
      preserve_default=False, 
     ), 
    ]   
+0

你的問題是關於遷移嗎? – Charlesthk

+0

你能告訴我們autotester.0005_auto_20150519_1831嗎? – Charlesthk

+0

@Charlesthk完成! – cybertextron

回答

2

A OneToOneField就像是ForeignKeyunique=True

你的問題帶有這個獨特的約束,因爲如果你的數據庫不是空的,你不能添加一個唯一約束的字段。你所要做的是:

  1. 添加字段沒有唯一約束= ForeignKey
  2. 填充就即將進行的唯一約束這個領域,你將有
  3. 更改ForeignKey的一個OneToOneField

以下是詳細步驟:

第一步:

刪除您autotester/migrations/0005_auto_20150519_1831.py文件,並改變你TestExecution模型result = models.ForeignKey(Result, null=True, blank=True)result場進行遷移:

./manage.py makemigrations autotester 
./manage.py migrate autotester 

第二步:

Result你有,創建一個TestExecution(用適當的數據代替FOO):

results = Result.objects.all() 

for result in results: 
    tst = TestExecution() 
    tst.name = FOO 
    tst. num_testsuites = FOO 
    tst.time = FOO 
    tst.result_id = result.id 
    tst.save() 

第三步

更改與result = models.OneToOneField(Result)你的結果字段,然後進行遷移:

./manage.py makemigrations autotester 
./manage.py migrate autotester 

你應該是好去。

+0

remove'result = models.OneToOneField(Result)'? – cybertextron

+0

我編輯了我的答案給你更多的細節 – Charlesthk

+0

你設法做到了嗎? – Charlesthk