2

Here is my model

from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
import uuid

class PiO(models.Model): 
    uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) # surrogate
    person = models.ForeignKey(Person, on_delete=models.PROTECT, max_length=25, blank=True)
    content_type = models.ForeignKey(ContentType, on_delete=models.PROTECT) # for the various organization types
    object_id = models.UUIDField(primary_key=False, default=uuid.uuid4, editable=False) # the uuid of the specific org
    content_object = GenericForeignKey('content_type', 'object_id')

Here is my traceback

AttributeError: 'UUIDField' object has no attribute 'uuid4'.

Note this is specifically referencing the object_id field, not the uuid (pk) field. As a test, I commented out the object_id field. I did not get an error for not having an object_id field, and the check went on to a new error 12 lines away.

I googled the exact phrase and got

No results found for "AttributeError: 'UUIDField' object has no attribute 'uuid4'".

What I did looks consistent with the docs to me.

What am I missing? Does the presence of the generic foreign key and or the contenttype have anything to do with it?

Malik A. Rumi
  • 1,855
  • 4
  • 25
  • 36

1 Answers1

12

The problem is that your model field uuid is clashing with the module uuid.

One option would be to rename your model field, for example:

class PiO(models.Model): 
    id = models.UUIDField(primary_key=True, default=uuid4, editable=False)
    ...

Another option would be to change the import to from uuid import uuid4, and update the defaults to use uuid4 instead of uuid.uuid4.

from uuid import uuid4

class PiO(models.Model): 
    uuid = models.UUIDField(primary_key=True, default=uuid4, editable=False) # surrogate
    ...
    object_id = models.UUIDField(primary_key=False, default=uuid4, editable=False) # the uuid of the specific org
Alasdair
  • 298,606
  • 55
  • 578
  • 516
  • Thanks. And to Sayse for the initial comment that helped me and maybe cost him some points ;-). Just a couple of things. I’ll have to go back and refactor my code because I named a lot of pk fields ‘uuid’. Not the end of the world. Also, when I replaced uuid with id as the field name, it turned blue (the same color as ‘class’ in my Sublime theme) which was a 'red flag'. See https://docs.djangoproject.com/en/1.10/topics/db/models/#automatic-primary-key-fields and http://stackoverflow.com/questions/77552/id-is-a-bad-variable-name-in-python . So I decided to just change them all to uuid_ – Malik A. Rumi Sep 27 '16 at 13:26
  • UPDATE for anyone with this issue. Although Python allows uuid_, Django does not, so you have to figure out another name. – Malik A. Rumi Sep 29 '16 at 02:43
  • Django allows model fields with leading underscores e.g. `_uuid` but not trailing underscores e.g. `uuid_`. Having said that, I don't see why you have to figure out another name. If you change the imports, you can keep `uuid`. Alternatively, you could just use `id`. Django uses `id` for auto-generated primary keys so it's ok for you to use it too. I realise that your editor shows a warning, but it's safe to ignore in this case. – Alasdair Sep 29 '16 at 08:50
  • Although Django allows leading underscores, e.g. `_uuid`, I wouldn't recommend doing this. You'll end up with triple underscores when you do lookups that span relationships, e.g. `MyModel.objects.filter(othermodel___uuid=uuid)`, which is confusing. – Alasdair Sep 29 '16 at 16:25