Opened 5 years ago

Closed 5 years ago

Last modified 5 years ago

#17167 closed Bug (invalid)

ModelForm model=class not honoring reference fields with secondary database

Reported by: furbeenator@… Owned by: nobody
Component: Forms Version: 1.3
Severity: Normal Keywords: ModelForm, using(), foreign key, reference field
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Karen Tracey)

When using a separate database for objects used as an instance in a ModelForm, reference fields are not searching the secondary database. For example, a secondary database (not default) is created, and set up in as database 'my_employee'. Two tables are created. One for employees, and one for departments they work in.

The tables contain these rows:

username | department_id
'mark' | 1

department_id | name
1 | 'Dept1'
2 | 'Dept2'

The models are as follows:

class Department(models.Model):
    name = models.CharField(max_length=32)
    def __unicode__(self):

class Employee(models.Model):
    username = models.CharField(max_length=32)
    department = models.ForeignKey(Department)
    def __unicode__(self):
        return self.username + ": <dept: " + + ">"

class EmployeeForm(ModelForm):
    class Meta:
        model = Employee

In a view:

emp = Employee.objects.using('my_employee').get(id=1)

print emp
'mark <dept: Dept1>'

frm = EmployeeForm(instance=emp)

print frm

This generates a DatabaseError Exception, relation 'department' does not exist. It exists in the secondary database, but not in the default database.

If I create a department table in the default database, the Employee object still gets retrieved, including the id for the Department, but the department details are retrieved from the default database instead of the secondary. As follows:

In default database:

department_id | name
1 | 'DefaultDBDept1'
2 | 'DefaultDBDept2'

No employee table exists in default database. The view below:

emp = Employee.objects.using('my_employee').get(id=1)

print emp
'mark <dept: Dept1>'

frm = EmployeeForm(instance=emp)

print frm

This generates a form as normal, but the Department details from the default database are included instead of details from the secondary database. So, two select options are created with the labels 'DefaultDBDept1' and 'DefaultDBDept2' and the selected one is correctly 'DefaultDBDept1.' If I update the secondary table so that employee 'mark' has department_id 2, the selected option is 'DefaultDBDept2.' If I remove the default department table, the DatabaseError exception, relation 'department' does not exist, returns.

Change History (5)

comment:1 Changed 5 years ago by Karen Tracey

Description: modified (diff)
Needs documentation: unset
Needs tests: unset
Patch needs improvement: unset

Fixed formatting. PLEASE use WikiFormatting and preview before posting.

comment:2 Changed 5 years ago by Karen Tracey

Resolution: invalid
Status: newclosed

Near as I can tell you are trying to have ForeignKeys that cross database boundaries. This is not supported by Django's multiple database support, see:

comment:3 Changed 5 years ago by anonymous

Resolution: invalid
Status: closedreopened

This does not span multiple databases. The employee and department tables are both in the secondary database. I can print the employee's department just fine, it is when I use it as an instance to a ModelForm that the references do not work. It is forcefully looking in the default database for the department, even though the employee object looks to the secondary database correctly.

comment:4 Changed 5 years ago by Karen Tracey

Resolution: invalid
Status: reopenedclosed

Why have you forked this discussion off to django-users as well, and then re-opened this here? Please see my response there. You don't seem to have done anything to tell Django to look in the secondary DB for this 2nd model, therefore the default is where it is looking for it. I think you need to code database routing to do what you are looking for, automatic routing so far as I know does not propagate database stickiness in the way you are looking for.

comment:5 Changed 5 years ago by anonymous

Thank you for your help, Karen. The issue is that everything is honored up to the point that I use the employee as an instance to a ModelForm. This works fine and the employee's department name is printed:

employee = Employee.objects.using('my_employee').get(id=1)

As soon as I assign a ModelForm:

frm = EmployeeForm(instance=employee)
print frm

The DatabaseError Exception is raised. What I was explaining in the original post was that if I have a table in the default database that has the name department, it works to attach the employee from 'my_employee' to the corresponding department from default. Perhaps I added TOO much detail in the original description. I have been trying to nail down exactly what the behavior is.

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