有没有办法在Django中使用GUID?

19

我有几个表在SQL Server中使用GUID进行了连接。 我已经找到了一些自定义字段,以便在Django中支持GUID,但我倾向于尽可能避免在博客文章中使用代码。除了连接GUID之外,我不会对其进行任何操作,也许可以在新条目上分配GUID(但这是可选的)。 有没有办法使用Django内置类型来实现这一点?例如,我可以使用某种char字段或二进制字段,并“欺骗”Django使用它进行连接吗?

如果有帮助的话,我正在使用django-pyodbc。


为什么guid必须是主键?它不能只是一个索引列和常规字符字段吗?在最初将所有表转换为Django“models”之后,添加任何新产品等都需要设置guid,但您将通过Django外键访问另一个表。 - Andriy Drozdyuk
我想那是一个好问题。我还没有真正考虑过。 :-) - Jason Baker
6个回答

20

我会创建一个基本的GUID模型,以便在我的项目中重复使用它的属性。自Django 1.0之前的几个版本以来,模型继承一直运行良好,并且在Django 1.0中非常稳定。

创建类似于project/common/models.py的文件,并将以下类放置其中:

import hashlib
import random
from django.db import models

class GUIDModel(models.Model):

    guid = models.CharField(primary_key=True, max_length=40)

    def save(self, *args, **kwargs):

      if not self.guid:
        self.guid = hashlib.sha1(str(random.random())).hexdigest()

      super(GUIDModel, self).save(*args, **kwargs)

然后像往常一样创建您的其他模型:

from common.models import GUIDModel

class Customer(GUIDModel):
  name = models.CharField(max_length=64)

class Product(GUIDModel):
  name = models.CharField(max_length=64)

class Sale(GUIDModel):
  customer = models.ForeignKey(Customer)
  product = models.ForeignKey(Product)
  items = models.PositiveIntegerField()

使用GUID作为主键而不是自增整数,一切都应该可以很好地工作。


10
我建议使用Python的uuid模块,并通过uuid.uuid1()或uuid.uuid4()生成新的GUID。 - Craig Trader
2
为了使这段代码与表单一起工作,您需要在GUIDModel中添加blank=True。这允许表单进行验证;我们实际上永远不会得到一个空的guid,因为save()确保有一个值。 - Rich
10
дҪ жҳҜеҗҰеә”иҜҘеңЁGUIDModelдёӯзҡ„class Meta:дёӢж·»еҠ abstract = TrueпјӣеҗҰеҲҷпјҢжҲ‘и®ӨдёәDjangoдјҡи®Өдёәе®ғ们йғҪжҢҮеҗ‘дёҖдёӘдёӯеӨ®иЎЁ... - Jordan Reiter
12
生成“GUID”的代码非常错误。像Craig建议的那样,应该使用uuid.uuid4()而不是重新发明轮子。如果你必须要自己发明,那么有一个规范可以告诉你如何生成GUID - RFC4122。对于随机GUID,你需要122位好质量的随机数;但你最多只有53位随机数,而且不清楚种子有多好。(来源:http://docs.python.org/library/random.html说random.random()“产生53位精度的浮点数”)GUID中的6个位必须设置为特定的值,以指示它是随机GUID,但你未这么做。 - user9876

8

这是一个老问题,但我记性不太好。这似乎是一个指向旧的Google代码存储库的链接,而不是akotian放置的更新的github链接。 - hum3
1
好的,@hum3,谢谢你提醒我。我已经更新了 Github 仓库的链接。 - Jj.

6

虽然这是一个老问题,但对于使用Django 1.8+的任何人来说,内置的UUIDField可能会很有用。


较新的文档链接。最新的开发者链接是UUIDField,但可能应该查看上一个版本。 - hum3

1

Django现在已经在1.8及以上版本中包含了UUID字段。 这是用于存储通用唯一标识符的字段。使用Python的UUID类。当在PostgreSQL上使用时,它会存储在uuid数据类型中,否则存储在char(32)中。 该字段通常用作主键,以下是如何在模型中使用它的方法 ->

your_app/models.py

import uuid
from django.db import models

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

0
如果我运行 python manage.py inspectdb 命令,输出结果会类似于这样:
class SomeModel(models.Model):
    uid = models.TextField(primary_key=True)

class SomeOtherModel(models.Model):
    uid = models.TextField()

但这并不起作用。由于某种原因,如果uid是主键,它将无法正常工作。因此我将其更改为:

class SomeModel(models.Model):
    uid = models.TextField()

class SomeOtherModel(models.Model):
    somemodel = models.ForeignKey(SomeModel, db_column='uid', to_field='uid')

这似乎可行,但速度实在是太慢了。


1
为什么不将其更改为CharField(primary_key=True)? - webjunkie

-3

对于那些实际需要生成 GUID 的人:

guid = hashlib.sha1(str(random.random())).hexdigest()

3
你的回答与所问问题几乎没有关系,请专注于回答问题而不是提供离题信息。然而,除此之外,你的代码是错误的,因为它提供了 GUID 冲突的极大可能性,更好的选择是使用内置函数uuid.uuid1()uuid.uuid4() - Toji

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接