﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
34816	GenericForeignKey crashes if content_type_id is changed and object_id is type incompatible with old object	Richard Laager	Oguzhan Akan	"Steps to reproduce:

1. Create a model (""A"") with a GenericForeignKey.
2. Create an instance of A (""a"") referencing an instance of model ""B"" with a PK that is an integer type.
3. Change the instance of ""A"" to reference an instance of model ""C"" with a PK that is incompatible with int(). But make this change using `content_type_id` and `object_id` properties, not `content_object`, i.e.:
{{{#!python
    a.content_type_id = ContentType.objects.get_for_model(B).pk
    a.object_id = ""foo""
}}}
4. Try to access `a.content_object`.

Expected result:

This looks up and returns an instance of ""b"" (the B with a PK of ""foo"").

Actual result:

This crashes (I'm using 3.2, but the code is unchanged in master):
{{{#!python
  File ""django/db/models/fields/__init__.py"", line 1836, in to_python
    return int(value)

  ValueError: invalid literal for int() with base 10: 'foo'
}}}

This happens because it tries to `to_python()` the new key on the old model's PK field.

One possible fix would be to make the logic short-circuit, like this (also attached):
{{{#!diff
diff --git a/django/contrib/contenttypes/fields.py b/django/contrib/contenttypes/fields.py
index 35fcd0d908..e984fb5375 100644
--- a/django/contrib/contenttypes/fields.py
+++ b/django/contrib/contenttypes/fields.py
@@ -242,11 +242,11 @@ class GenericForeignKey(FieldCacheMixin):
             ct_match = (
                 ct_id == self.get_content_type(obj=rel_obj, using=instance._state.db).id
             )
-            pk_match = rel_obj._meta.pk.to_python(pk_val) == rel_obj.pk
-            if ct_match and pk_match:
-                return rel_obj
-            else:
-                rel_obj = None
+            if ct_match:
+                pk_match = rel_obj._meta.pk.to_python(pk_val) == rel_obj.pk
+                if pk_match:
+                    return rel_obj
+            rel_obj = None
         if ct_id is not None:
             ct = self.get_content_type(id=ct_id, using=instance._state.db)
             try:
}}}"	Bug	closed	contrib.contenttypes	4.2	Normal	fixed			Ready for checkin	1	0	0	0	0	0
