Opened 9 years ago

Closed 9 years ago

Last modified 8 years ago

#1928 closed defect (fixed)

[patch] Forget some foreignkeys during "python manage.py syncdb" with an empty postgres db.

Reported by: hornero Owned by: adrian
Component: Core (Management commands) Version: master
Severity: major Keywords: Forget foreignkey django-admin.py
Cc: landonf@… Triage Stage: Unreviewed
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

Description

For models with several foreignkeys to the same table, like this :

class File(models.Model):
    Name = models.CharField(maxlength=200,null=False, blank=False, unique=True)
    Storage = models.CharField(maxlength=200, null=True, blank=True)
    def __repr__(self):
        return self.Name
class Job(models.Model):
    Name = models.CharField(maxlength=200)
    Script_FK = models.ForeignKey(File,related_name='Script', verbose_name="The script file",null=True, blank=True)
    JobLog_FK = models.ForeignKey(File,related_name='JobLog', verbose_name="The log file",null=True, blank=True)
    def __repr__(self):
        return self.Name
class Header(models.Model):
    FULL_PATH_FITS = models.CharField(maxlength=200, null=False, blank=False, unique=True)
    Fits_File_FK = models.ForeignKey(File, related_name='Fits_File_FK', verbose_name="The related File",null=True, blank=True)       
    def __repr__(self):
        return str(int(self.FULL_PATH_FITS))

When we launch python manage.py syncdb" with an empty postgres db, some foreignkeys are missing :

=> \d process_job
                                    Table "public.process_job"
    Column    |          Type          |                        Modifiers
--------------+------------------------+----------------------------------------------------------
 id           | integer                | not null default nextval('process_job_id_seq'::regclass)
 Name         | character varying(200) | not null
 Script_FK_id | integer                |
 JobLog_FK_id | integer                |
Indexes:
    "process_job_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
    "JobLog_FK_id_referencing_process_file_id" FOREIGN KEY ("JobLog_FK_id") REFERENCES process_file(id)
    "Script_FK_id_referencing_process_file_id" FOREIGN KEY ("Script_FK_id") REFERENCES process_file(id)

=> \d process_header
                                       Table "public.process_header"
       Column       |          Type          |                          Modifiers
--------------------+------------------------+-------------------------------------------------------------
 id                 | integer                | not null default nextval('process_header_id_seq'::regclass)
 FULL_PATH_FITS     | character varying(200) | not null
 Fits_File_FK_id    | integer                |
Indexes:
    "process_header_pkey" PRIMARY KEY, btree (id)
    "process_header_FULL_PATH_FITS_key" UNIQUE, btree ("FULL_PATH_FITS")

I think the problem start with the update of the dictionnary "pending_references" in django/core/management.py :
(In the function syncdb()):

449 	            sql, references = _get_sql_model_create(model, seen_models)
450 	            seen_models.add(model)
451 	            created_models.add(model)
452 	            pending_references.update(references)        #===============> Problem...
453 	            sql.extend(_get_sql_for_pending_references(model, pending_references))

The update function overwrites the previous references to the file table with the new ones.

In order to keep the previous foreignkeys, I've written the folowing function to replace the update dictionnary function :

def update_dict(dict_input = {},dict_update = {}):
    "New update function which keep the previous references."     
     dict_output = dict_input     
     try :
     	for k_update, v_update in dict_update.items() :
     		try :
			value_to_update = dict_input[k_update]
			value_output = value_to_update + v_update
			dict_output[k_update] = value_output	
		except :
			dict_output[k_update] = v_update
     except :
     	dict_output.update(dict_update)
     return dict_output

and call it in syncdb():

pending_references = update_dict(pending_references,references)

The same error can be found in get_sql_create(app).

Now, in the db, we have :

\d process_header                                        Table "public.process_header"        Column       |          Type          |                          Modifiers
--------------------+------------------------+-------------------------------------------------------------
 id                 | integer                | not null default nextval('process_header_id_seq'::regclass)
 FULL_PATH_FITS     | character varying(200) | not null
 Fits_File_FK_id    | integer                |
Indexes:
    "process_header_pkey" PRIMARY KEY, btree (id)
    "process_header_FULL_PATH_FITS_key" UNIQUE, btree ("FULL_PATH_FITS")
Foreign-key constraints:
    "Fits_File_FK_id_referencing_process_file_id" FOREIGN KEY ("Fits_File_FK_id") REFERENCES process_file(id)

\d process_job                                     Table "public.process_job"     Column    |          Type          |                        Modifiers
--------------+------------------------+----------------------------------------------------------
 id           | integer                | not null default nextval('process_job_id_seq'::regclass)
 Name         | character varying(200) | not null
 Script_FK_id | integer                |
 JobLog_FK_id | integer                |
Indexes:
    "process_job_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
    "JobLog_FK_id_referencing_process_file_id" FOREIGN KEY ("JobLog_FK_id") REFERENCES process_file(id)
    "Script_FK_id_referencing_process_file_id" FOREIGN KEY ("Script_FK_id") REFERENCES process_file(id)

Attachments (1)

bug1928.diff (778 bytes) - added by Geert Vanderkelen 9 years ago.
Based on Shaun's solution mentioned in the forum thread.

Download all attachments as: .zip

Change History (5)

comment:1 Changed 9 years ago by mtredinnick

Changed 9 years ago by Geert Vanderkelen

Based on Shaun's solution mentioned in the forum thread.

comment:2 Changed 9 years ago by Geert Vanderkelen

  • Summary changed from Forget some foreignkeys during "python manage.py syncdb" with an empty postgres db. to [patch] Forget some foreignkeys during "python manage.py syncdb" with an empty postgres db.

Adding a patch based on Shaun's solution mentioned in the forum thread (see in the Change History of this bug report).

Just had to make it work, so I figured I upload a patch.

comment:3 Changed 9 years ago by anonymous

  • Cc landonf@… added

comment:4 Changed 9 years ago by mtredinnick

  • Resolution set to fixed
  • Status changed from new to closed

(In [3182]) Fixed #1928 -- Correctly create foreign key references when there are multiple
keys on multiple models. Based on a patch from Geert Vanderkelen and some
diagnosis from hornero.

Note: See TracTickets for help on using tickets.
Back to Top