为Django模型生成非顺序ID / PK [英] Generating a non-sequential ID/PK for a Django Model

查看:136
本文介绍了为Django模型生成非顺序ID / PK的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开始一个新的webapp工作的尖端。其中的一部分将给用户页面,他们可以以一对多的关系自定义。这些页面自然需要有唯一的URL。



Django通常会分配一个标准的 AUTOINCREMENT ID到模型。虽然这样做很有意思,但它看起来并不好看,这也使得页面非常可预测(在这种情况下,这是不需要的)。



而不是1,2 ,3,4我想要设置长度,随机生成的字母数字字符串(例如h2esj4)。可能的36个字符的6个点应该给我超过20亿的组合,这在现阶段应该是足够的。当然,如果我可以在稍后的时间进行扩展,那也是很好的。



但是有两个问题:


  1. 随机字符串偶尔会拼出坏话或其他令人反感的短语。有没有一个体面的方式来回避呢?为了公平起见,我可能会找到一个数字字符串,但它确实有可能发生冲突。


  2. 如何获取Django(或数据库)在插入时做重载吗?我宁愿不插入,然后然后确定密钥(因为这不是一个关键)。我假设有并发问题需要注意,但是如果两个新页面同时生成,而第二个(相对于所有的几率),在第一个提交之前就会神奇地得到与第一个相同的密钥。


我没有看到这是一个百万英里不同于URL缩短器生成其ID。如果有一个体面的Django实现,我可以背叛。

解决方案

这是我最后做的。我做了一个抽象的模型。我的用例是需要几个型号,产生自己的随机s。。



一个s lug似乎像$ code> AA ## AA 所以这是 52x52x10x10x52x52 = 731,161,600 组合。可能是我需要的一千倍,如果这是一个问题,我可以添加一个信件52倍以上的组合。



使用 default 参数不会因为抽象模型需要检查孩子的屁股碰撞而被剪切。继承是最简单的方式,可能只是这样做。

从$ d code从django.db导入模型
从django.contrib .auth.models import User

import string,random

class SluggedModel(models.Model):
slug = models.SlugField(primary_key = True,unique = true,editable = False,blank = True)

def save(self,* args,** kwargs):
while not self.slug:
ret = []
ret.extend(random.sample(string.letters,2))
ret.extend(random.sample(string.digits,2))
ret.extend(random.sample(string .letters,2))

newslug =''.join(ret)
如果self.objects.filter(pk = newslug).count():
self.slug = newslug

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

class Meta:
abstract = True


I'm on the cusp of starting work on a new webapp. Part of this will give users pages that they can customise in a one to many relationship. These pages naturally need to have unique URLs.

Left to its own devices, Django would normally assign a standard AUTOINCREMENT ID to a model. While this works fantastically, it doesn't look great and it also makes pages very predictable (something that isn't desired in this case).

Rather than 1, 2, 3, 4 I would like set-length, randomly generated alphanumeric strings (eg h2esj4). 6 spots of a possible set of 36 characters should give me over two billion combinations which should be more than enough at this stage. Of course if I could expand this at a later time, that would be good too.

But there are two issues:

  1. Random strings occasionally spell out bad words or other offensive phrases. Is there a decent way to sidestep that? To be fair I could probably settle for a numeric string but it does have a hefty hit on the likelihood of clashes.

  2. How do I get Django (or the database) to do the heavy lifting on insert? I'd rather not insert and then work out the key (as that wouldn't be much of a key). I assume there are concurrency issues to be aware of too though if two new pages were generated at the same time and the second (against all odds) magically got the same key as the first before the first was committed.

I don't see this being a million miles different from how URL shorteners generate their IDs. If there's a decent Django implementation of one, I could piggyback off that.

解决方案

Here's what I ended up doing. I made an abstract model. My use-case for this is needing several models that generate their own, random slugs.

A slug looks like AA##AA so that's 52x52x10x10x52x52 = 731,161,600 combinations. Probably a thousand times more than I'll need and if that's ever an issue, I can add a letter for 52 times more combinations.

Use of the default argument wouldn't cut it as the abstract model needs to check for slug collisions on the child. Inheritance was the easiest, possibly only way of doing that.

from django.db import models
from django.contrib.auth.models import User

import string, random

class SluggedModel(models.Model):
    slug = models.SlugField(primary_key=True, unique=True, editable=False, blank=True)

    def save(self, *args, **kwargs):
        while not self.slug:
            ret = []
            ret.extend(random.sample(string.letters, 2))
            ret.extend(random.sample(string.digits, 2))
            ret.extend(random.sample(string.letters, 2))

            newslug = ''.join(ret)
            if self.objects.filter(pk=newslug).count():
                self.slug = newslug

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

    class Meta:
        abstract = True

这篇关于为Django模型生成非顺序ID / PK的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆