django-taggit 在模型上使用 UUID 作为 pk 在保存时抛出范围
django-taggit on models with UUID as pk throwing out of range on save
我有使用 UUID 作为主键的模型
class Foo(models.Model):
foo_id = models.UUIDField(
primary_key=True,
default=uuid.uuid4,
editable=False
)
tags = TaggableManager()
当我尝试添加新标签时
f = Foo.objects.latest('pk')
f.tags.add("testing")
我得到 DataError: integer out of range
当我在光标上导入 pdb 以查看 SQL 进入时,我看到了这个。
(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"'
试图插入的那个长整数 (287082253891563438098836942573405313042
) 显然是错误的原因。这个数字是 UUID
for foo_id
的整数
In [6]: foo.foo_id.int
Out[6]: 287082253891563438098836942573405313042
我可以设置什么让 django-taggit
与 contenttypes
和 UUID
一起玩吗?
这是根据 Austin 的评论做出的回答。
在 django-taggit
中,对标记模型的引用存储在名为 GenericTaggedItemBase
的模型中,位于名为 object_id
的字段下。 object_id
字段被硬编码为 models.IntegerField
。因此无法标记具有 UUID 主键的模型。代码是located here.
如果您所有需要标记的模型都是同一类型(在本例中为models.UUIDField
),那么您可以将object_id
的类型设置为models.UUIDField
。
以下是必须进行的更改,假设您使用的是 virtualenvwrapper
在站点包文件夹中找到 taggit
包。 ~/virtualenvs/<your_virtualenv>/lib/<python_version>/site-packages/taggit
将 taggit
目录复制到您的项目中。
从site-packages
中删除taggit
目录
在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)
- 迁移 taggit。
python manage.py makemigrations taggit
python manage.py migrate
我想扩展@Pramod 的回复,这对我找到正确答案很有帮助:
Taggit 有另一个 class 允许改变 TaggedItem
的行为
以下是如何实施此解决方案的片段:
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)
来源:http://django-taggit.readthedocs.io/en/latest/custom_tagging.html#genericuuidtaggeditembase
我有使用 UUID 作为主键的模型
class Foo(models.Model):
foo_id = models.UUIDField(
primary_key=True,
default=uuid.uuid4,
editable=False
)
tags = TaggableManager()
当我尝试添加新标签时
f = Foo.objects.latest('pk')
f.tags.add("testing")
我得到 DataError: integer out of range
当我在光标上导入 pdb 以查看 SQL 进入时,我看到了这个。
(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"'
试图插入的那个长整数 (287082253891563438098836942573405313042
) 显然是错误的原因。这个数字是 UUID
for foo_id
In [6]: foo.foo_id.int
Out[6]: 287082253891563438098836942573405313042
我可以设置什么让 django-taggit
与 contenttypes
和 UUID
一起玩吗?
这是根据 Austin 的评论做出的回答。
在 django-taggit
中,对标记模型的引用存储在名为 GenericTaggedItemBase
的模型中,位于名为 object_id
的字段下。 object_id
字段被硬编码为 models.IntegerField
。因此无法标记具有 UUID 主键的模型。代码是located here.
如果您所有需要标记的模型都是同一类型(在本例中为models.UUIDField
),那么您可以将object_id
的类型设置为models.UUIDField
。
以下是必须进行的更改,假设您使用的是 virtualenvwrapper
在站点包文件夹中找到
taggit
包。~/virtualenvs/<your_virtualenv>/lib/<python_version>/site-packages/taggit
将
taggit
目录复制到您的项目中。从
site-packages
中删除在
models.py
文件中taggit
,替换
taggit
目录
object_id = models.IntegerField(verbose_name=_('Object id'), db_index=True)
和
object_id = models.UUIDField(verbose_name=_('Object id'), db_index=True)
- 迁移 taggit。
python manage.py makemigrations taggit
python manage.py migrate
我想扩展@Pramod 的回复,这对我找到正确答案很有帮助:
Taggit 有另一个 class 允许改变 TaggedItem
以下是如何实施此解决方案的片段:
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)
来源:http://django-taggit.readthedocs.io/en/latest/custom_tagging.html#genericuuidtaggeditembase