[Answered ]-Possible bug in django models

2👍

Django is behaving just as expected. To understand why we’ll start with a look at the ways to pass keyword arguments to a model class’ constructor in case of a foreign key relationship.

  1. Use the name of the relationship (uid_string). In this case, you have to pass an instance of the related model (uid_string = rootentry).

  2. Use the name of the database field (uid_string_id). Here you have to pass a value of an appropriate type. So if the FK points to an integer field, pass an integer; if it points to text, pass a text instance etc.

Now let us look at your code. We’ll start with the first line:

shrubentry = shrub(uid_string_id = rootentry.uid_string)
shrubentry.save() # Succeeds

You have created a relation between shrub and root but have also specified a custom to_field to link to. Since this column is a text field you are able to pass the rootentry.uid_string as the value of the uid_string_id keyword argument (mechanism #2 listed above).

There is another way to express what you did above, without using the field name as the keyword argument. That will be to use the name of the relationship and pass an instance of root (mechanism #1 listed above).

shrubentry = shrub(uid_string = rootentry)
shrubentry.save() # Succeeds

Now let us take a look at the second line.

treeentry = tree(uid_string = rootentry.uid_string) # Raises error.
# ValueError: Cannot assign "'text'": "tree.uid_string" must be a "root" instance.

This line is different from the first line. You are using mechanism #1 (relationship name) and therefore Django expects an instance of root as the value of the keyword argument. If you switch to mechanism #2 (field name):

treeentry = tree(uid_string_id = rootentry.uid_string)
treeentry.save() # Succeeds

Now comes the interesting part. Try this:

treeentry = tree(uid_string_id = rootentry.id)  # No problem
treeentry.save() # Blows up
# IntegrityError: ...
# DETAIL:  Key (uid_string)=(2) is not present in table "app_root".

The first line of the above snippet works. But when you try to save it the database looks for a key “2” (i.e. rootentry.id) in the _uid_string_ column of the root table. Since it is not there, the save() fails.

0👍

When dealing with foreignkeys, you need to use object instance like below.

treeentry = tree(uid_string = rootentry)

BTW, use CamelCase for Class names. Please read http://www.python.org/dev/peps/pep-0008/

Leave a comment