[英]How to create random slug in Django
I have a Django app that will create a contract between two people.我有一个 Django 应用程序,它将在两个人之间创建合同。 The
user
creates the contract and, upon creation, a random url-safe string is generated using secrets
. user
创建合约,并在创建后使用secrets
生成一个随机的 url 安全字符串。
However, when I create more than one instance of a Contract
, the slugs are the same.但是,当我创建多个
Contract
实例时,slug 是相同的。 The only way to get a different randomly generated string is to restart my server.获得不同的随机生成字符串的唯一方法是重新启动我的服务器。 What am I doing wrong?
我究竟做错了什么?
Here's the part that matters in my models.py
这是我的
models.py
中重要的部分
slug = models.SlugField(
default=secrets.token_urlsafe(64),
editable=False,
blank=False
)
Here are the last three Contracts
I created.这是我创建的最后三个
Contracts
。 Changing the values of the other fields doesn't change the slug.更改其他字段的值不会更改 slug。
{
"model_email": "POOP@pooop.com",
"shoot_location": "Atlanta, GA",
"shoot_date": "2020-05-24",
"model_name": "",
"created_at": "2020-05-24T19:24:20.220845Z",
"sent_completed_to_model": null,
"sent_completed_to_photographer": null,
"photographer": 1,
"signed": false,
"slug": "Dqyk5-kDzE219_-abRKABETRuOCGOBxzvFVrXZaUGEe8ZLva6i6tdwUYMksSvKJ_BEABV_Vt1H_ttZ6p-yzRyg"
},
{
"model_email": "POOP@pooop.com",
"shoot_location": "Atlanta, GA",
"shoot_date": "2020-05-24",
"model_name": "",
"created_at": "2020-05-24T19:24:21.216218Z",
"sent_completed_to_model": null,
"sent_completed_to_photographer": null,
"photographer": 1,
"signed": false,
"slug": "Dqyk5-kDzE219_-abRKABETRuOCGOBxzvFVrXZaUGEe8ZLva6i6tdwUYMksSvKJ_BEABV_Vt1H_ttZ6p-yzRyg"
},
{
"model_email": "POOP@pooop.com",
"shoot_location": "Atlanta, GA",
"shoot_date": "2020-05-24",
"model_name": "",
"created_at": "2020-05-24T19:24:22.120845Z",
"sent_completed_to_model": null,
"sent_completed_to_photographer": null,
"photographer": 1,
"signed": false,
"slug": "Dqyk5-kDzE219_-abRKABETRuOCGOBxzvFVrXZaUGEe8ZLva6i6tdwUYMksSvKJ_BEABV_Vt1H_ttZ6p-yzRyg"
}
This happen because your default value is not function that will be called on each save, it's rather a constant value generated when your app start发生这种情况是因为您的默认值不是 function 将在每次保存时调用,而是在您的应用启动时生成的常量值
An other option would be moving the logic to save
method of your model:另一种选择是移动逻辑以
save
model 的方法:
slug = models.SlugField(
default='',
editable=False,
blank=False
)
...
def save(self, *args, **kwargs):
if not self.default:
self.default = secrets.token_urlsafe(64)
super().save(*args, **kwargs)
Change your code to:将您的代码更改为:
def get_token_slug():
return secrets.token_urlsafe(64)
... ...
slug = models.SlugField(
default=get_token_slug,
editable=False,
blank=False,
unique=True, # also add this
)
The problem was that the function call that you give as a default value is computed once and the result is used as a default value in all new instances of this model.问题在于,您作为默认值提供的 function 调用只计算一次,结果在此 model 的所有新实例中用作默认值。
Instead, you should give a callable as a default value, which will then be called when a new instance of the model is created.相反,您应该将可调用对象作为默认值,然后在创建 model 的新实例时调用它。 So just wrap the
token_urlsafe
call in a function, and give it as an argument (the function, not a call, so without parentheses ()
)所以只需将
token_urlsafe
调用包装在 function 中,并将其作为参数提供(function,不是调用,所以没有括号()
)
In terms of creating a unique slug field when saving an instance of your model, you will need to alter your save method so that it can create a slug which has the next available number appended to the end of your slug.在保存 model 的实例时创建一个唯一的 slug 字段,您需要更改保存方法,以便它可以创建一个 slug,在您的 slug 末尾附加下一个可用编号。 It might look something like the below...
它可能看起来像下面这样......
Replace MyModel
and field_you_are_using_to_slugify
as applicable.根据需要替换
MyModel
和field_you_are_using_to_slugify
。
def save(self):
if not self.slug.strip():
self.slug = slugify(self.field_you_are_using_to_slugify)
_slug = self.slug
_count = 1
while True:
try:
MyModel.objects.all().exclude(pk=self.pk).get(slug=_slug)
except MultipleObjectsReturned:
pass
except ObjectDoesNotExist:
break
_slug = f"{self.slug}{_count}"
_count += 1
self.slug = _slug
super(MyModel, self).save()
It should be noted however that if you're after a URL which cannot be interpreted and uses random string generation, then Django provides a UUID field for that purpose.但是应该注意的是,如果您使用的是无法解释的 URL 并使用随机字符串生成,那么 Django 会为此目的提供一个 UUID 字段。 Here is a link to the docs
这是文档的链接
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.