{{{#!python
class Author(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4,
editable=False)
class Book(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4,
editable=False)
author = models.ForeignKey(
Author, null=True, blank=True, on_delete=models.CASCADE
)
}}}
{{{#!python
In [1]: book = Book.objects.create()
In [2]: author = Author.objects.create()
In [3]: book.author_id
In [4]: book.author
In [5]: book.author_id = author
In [6]: book.save()
In [7]: book.author
---------------------------------------------------------------------------
KeyError Traceback (most recent call
last)
...
ValidationError: ['“Author object (caaf8f9a-f934-44e9-8e6b-00d71d116acf)”
is not a valid UUID.']
}}}
Similarly, if someone tries to use `book.author_id` to fetch an author
using `Author.objects.get(id=book.author_id)` will also fail with a
similar error.
--
Ticket URL: <https://code.djangoproject.com/ticket/34918>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
Comment (by Rahul Beniwal):
Hi Ricardo Busquet
I checked this, and you are right. But instead of assigning
`book.author_id=author` to `book.author=author` it seems to be working
fine.
{{{#!python
In [23]: book.author = author
In [24]: book.save()
In [25]: book.author_id
Out[25]: UUID('857acf04-960a-40ae-9c85-8c363b0a0dfd')
In [26]: book.author
Out[26]: <Author: Author object (857acf04-960a-40ae-9c85-8c363b0a0dfd)>
In [27]: Author.objects.get(id=book.author_id)
Out[27]: <Author: Author object (857acf04-960a-40ae-9c85-8c363b0a0dfd)>
}}}
Can we update the documentation for the UUID field to aware reader about
this situation or code level changes are needed?
Please feel free to assign this to me
--
Ticket URL: <https://code.djangoproject.com/ticket/34918#comment:1>
Comment (by Tim Graham):
Django generally doesn't validate model attribute assignments. For
example, if Book has a title `CharField`, you can assign it the wrong
type, like `datetime` and it'll be silently coerced to string. I don't
think we're going to add this sort of validation or document it, but I
will leave this ticket open for a second opinion in case I'm overlooking
something.
Incidentally, similar steps with `id` as an `AutoField` also save
correctly but subsequently fail on access:
{{{ #!python
Traceback (most recent call last):
File
"/home/tim/code/django/django/db/models/fields/related_descriptors.py",
line 235, in __get__
rel_obj = self.field.get_cached_value(instance)
File "/home/tim/code/django/django/db/models/fields/mixins.py", line 15,
in get_cached_value
return instance._state.fields_cache[cache_name]
KeyError: 'reporter'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/tim/code/django/django/db/models/fields/__init__.py", line
2116, in get_prep_value
return int(value)
TypeError: int() argument must be a string, a bytes-like object or a real
number, not 'Reporter'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/home/tim/code/django/tests/many_to_one/tests.py", line 856, in
test_cached_relation_invalidated_on_save
self.assertEqual(self.a.reporter, self.r2)
File
"/home/tim/code/django/django/db/models/fields/related_descriptors.py",
line 253, in __get__
rel_obj = self.get_object(instance)
File
"/home/tim/code/django/django/db/models/fields/related_descriptors.py",
line 216, in get_object
return qs.get(self.field.get_reverse_related_filter(instance))
File "/home/tim/code/django/django/db/models/query.py", line 633, in get
clone = self._chain() if self.query.combinator else self.filter(*args,
**kwargs)
File "/home/tim/code/django/django/db/models/query.py", line 1476, in
filter
return self._filter_or_exclude(False, args, kwargs)
File "/home/tim/code/django/django/db/models/query.py", line 1494, in
_filter_or_exclude
clone._filter_or_exclude_inplace(negate, args, kwargs)
File "/home/tim/code/django/django/db/models/query.py", line 1501, in
_filter_or_exclude_inplace
self._query.add_q(Q(*args, **kwargs))
File "/home/tim/code/django/django/db/models/sql/query.py", line 1599,
in add_q
clause, _ = self._add_q(q_object, self.used_aliases)
File "/home/tim/code/django/django/db/models/sql/query.py", line 1631,
in _add_q
child_clause, needed_inner = self.build_filter(
File "/home/tim/code/django/django/db/models/sql/query.py", line 1458,
in build_filter
return self._add_q(
File "/home/tim/code/django/django/db/models/sql/query.py", line 1631,
in _add_q
child_clause, needed_inner = self.build_filter(
File "/home/tim/code/django/django/db/models/sql/query.py", line 1545,
in build_filter
condition = self.build_lookup(lookups, col, value)
File "/home/tim/code/django/django/db/models/sql/query.py", line 1375,
in build_lookup
lookup = lookup_class(lhs, rhs)
File "/home/tim/code/django/django/db/models/lookups.py", line 30, in
__init__
self.rhs = self.get_prep_lookup()
File "/home/tim/code/django/django/db/models/lookups.py", line 362, in
get_prep_lookup
return super().get_prep_lookup()
File "/home/tim/code/django/django/db/models/lookups.py", line 88, in
get_prep_lookup
return self.lhs.output_field.get_prep_value(self.rhs)
File "/home/tim/code/django/django/db/models/fields/__init__.py", line
2118, in get_prep_value
raise e.__class__(
TypeError: Field 'id' expected a number but got <Reporter: Paul Jones>.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/34918#comment:2>
* status: new => closed
* resolution: => invalid
Comment:
I agree with Tim.
--
Ticket URL: <https://code.djangoproject.com/ticket/34918#comment:3>