django-taggit on models with UUID as pk throwing out of range on save

Aus*_*tin 5 django django-taggit django-contenttypes

I have models that uses UUID as its PK

class Foo(models.Model):        
    foo_id = models.UUIDField(  
        primary_key=True,             
        default=uuid.uuid4,           
        editable=False                
    )  
    tags = TaggableManager()        
Run Code Online (Sandbox Code Playgroud)

When I go and try to add a new tag

f = Foo.objects.latest('pk')
f.tags.add("testing")
Run Code Online (Sandbox Code Playgroud)

I get DataError: integer out of range

When I import pdb on the cursor to view the SQL going in I see this.

(Pdb) params                                                                                                              
(1, 287082253891563438098836942573405313042, 9)                                                                           
(Pdb) sql                                                                                                                 
'INSERT INTO "taggit_taggeditem" ("tag_id", "object_id", "content_type_id") VALUES (%s, %s, %s) RETURNING "taggit_taggedit
m"."id"'    
Run Code Online (Sandbox Code Playgroud)

That long integer (287082253891563438098836942573405313042) trying to be insterted is obvsiouly the cause for the error. This number is the int of the UUID for foo_id

In [6]: foo.foo_id.int                      
Out[6]: 287082253891563438098836942573405313042  
Run Code Online (Sandbox Code Playgroud)

Is there something I can set to allow django-taggit to play nicely with contenttypes and UUID?

Raf*_*lar 9

I'd like to extend @Pramod response, that was very helpful for me to find the right answer:

Taggit has another class that allows to change the behavior of the TaggedItem

Here is a snippet of how to implement this solution:

from django.db import models
from django.utils.translation import ugettext_lazy as _

from taggit.managers import TaggableManager
from taggit.models import GenericUUIDTaggedItemBase, TaggedItemBase

class UUIDTaggedItem(GenericUUIDTaggedItemBase, TaggedItemBase):
    # If you only inherit GenericUUIDTaggedItemBase, you need to define
    # a tag field. e.g.
    # tag = models.ForeignKey(Tag, related_name="uuid_tagged_items", on_delete=models.CASCADE)

    class Meta:
        verbose_name = _("Tag")
        verbose_name_plural = _("Tags")

class Food(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    # ... fields here

    tags = TaggableManager(through=UUIDTaggedItem)
Run Code Online (Sandbox Code Playgroud)

source: http://django-taggit.readthedocs.io/en/latest/custom_tagging.html#genericuuidtaggeditembase


Pra*_*mod 3

这是基于奥斯汀评论的答案。

在 中django-taggit,对标记模型的引用存储在名为 的GenericTaggedItemBase字段下命名的模型中object_id。该object_id字段被硬编码为models.IntegerField. 因此不可能标记具有 UUID 主键的模型。代码位于此处

如果需要标记的所有模型都属于同一类型(在本例中为models.UUIDField),那么您可以将object_id的类型设置为models.UUIDField

假设您正在使用,以下是必须进行的更改virtualenvwrapper

  1. taggit在站点包文件夹中找到该包。~/virtualenvs/<your_virtualenv>/lib/<python_version>/site-packages/taggit

  2. 将目录复制taggit到您的项目中。

  3. 删除该taggit目录site-packages

  4. models.py文件中taggit,替换

object_id = models.IntegerField(verbose_name=_('Object id'), db_index=True)

object_id = models.UUIDField(verbose_name=_('Object id'), db_index=True)
Run Code Online (Sandbox Code Playgroud)
  1. 迁移 taggit。

python manage.py makemigrations taggit

python manage.py migrate