Я думаю, что ваши два примера на самом деле только один: free()
должен появиться только в конце процесса, который, как вы указываете, бесполезен, так как процесс завершается.
В вас второй пример, однако, единственное различие заключается в том, что вы разрешаете неопределенное число malloc()
, что может привести к нехватке памяти. Единственный способ справиться с ситуацией - проверить код возврата malloc()
и действовать соответственно.
Вот что я в итоге сделал. Я сделал абстрактную модель. Мой вариант использования для этого требует нескольких моделей, которые генерируют свои собственные, случайные слизни.
Слизень выглядит как AA##AA
, так что это 52x52x10x10x52x52 = 731,161,600
комбинаций. Вероятно, в тысячу раз больше, чем мне нужно, и если это когда-нибудь станет проблемой, я могу добавить письмо в 52 раза больше комбинаций.
Использование аргумента default
не приведет к его сокращению, поскольку абстрактная модель должна проверять наличие столкновений слагов на дочернем элементе. Наследование было самым простым, возможно, единственным способом сделать это.
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:
newslug = ''.join([
random.sample(string.letters, 2),
random.sample(string.digits, 2),
random.sample(string.letters, 2),
])
if not self.objects.filter(pk=newslug).exists():
self.slug = newslug
super().save(*args, **kwargs)
class Meta:
abstract = True
Есть встроенный в Django способ достичь того, чего вы хотите. Добавьте поле к модели «пользовательской страницы» с именем primary_key=True
и default=
функции генерации ключа, например:
class CustomPage(models.Model):
...
mykey = models.CharField(max_length=6, primary_key=True, default=pkgen)
...
Теперь для каждого экземпляра модели page
, page.pk
становится псевдонимом для page.mykey
, который автоматически присваивается строке, возвращаемой вашей функцией pkgen()
в момент создания этого экземпляра.
Быстрая и грязная реализация:
def pkgen():
from base64 import b32encode
from hashlib import sha1
from random import random
rude = ('lol',)
bad_pk = True
while bad_pk:
pk = b32encode(sha1(str(random())).digest()).lower()[:6]
bad_pk = False
for rw in rude:
if pk.find(rw) >= 0: bad_pk = True
return pk
Вероятность того, что две страницы получат идентичные первичные ключи, очень мала (при условии, что random()
является достаточно случайной), и нет проблем параллелизма. И, конечно же, этот метод легко расширяем, выделяя больше символов из кодированной строки.
Может быть, вам нужно взглянуть на Python UUID , он может генерировать случайные длинные символы. Но вы можете нарезать его и использовать нужное количество символов с небольшой проверкой, чтобы убедиться, что он уникален даже после нарезки.
Фрагмент UUIDField может помочь вам, если вы не хотите сами создавать UUID.
Также посмотрите это сообщение в блоге
Django теперь включает тип UUIDField , так что вам не нужен какой-либо пользовательский код или внешний пакет, предложенный Срикант Чунди. В этой реализации используются строки HEX с черточками, поэтому текст довольно безопасный для детей, кроме 1337 выражений, таких как abad1d3a:)
Вы можете использовать его как псевдоним pk
для поля uuid
в качестве первичный ключ:
import uuid
from django.db import models
class MyModel(models.Model):
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
# other fields
Обратите внимание, однако, что при маршрутизации к этому представлению в urls.py вам необходимо другое регулярное выражение, как , упомянутое здесь Например:
urlpatterns = [
url(r'mymodel/(?P<pk>[^/]+)/, MyModelDetailView.as_view(),
name='mymodel'),
]
Оли: Если вы беспокоитесь о том, чтобы произносить грубые слова, вы всегда можете сравнить / найти их в UUIDField, используя фильтр ненормативной лексики django, и пропустить все UUID, которые могут быть триггерами.
Это то, что я в итоге использовал UUID.
import uuid
from django.db import models
from django.contrib.auth.models import User
class SluggedModel(models.Model):
slug = models.SlugField(primary_key=True, unique=True, editable=False, blank=True)
def save(self, *args, **kwargs):
if not self.slug:
uuid.uuid4().hex[:16] # can vary up to 32 chars in length
super(SluggedModel, self).save(*args, **kwargs)
class Meta:
abstract = True
Глядя на приведенные выше ответы, вот что я использую сейчас.
import uuid
from django.db import models
from django.utils.http import int_to_base36
ID_LENGTH = 9
def id_gen() -> str:
"""Generates random string whose length is `ID_LENGTH`"""
return int_to_base36(uuid.uuid4().int)[:ID_LENGTH]
class BaseModel(models.Model):
"""Django abstract model whose primary key is a random string"""
id = models.CharField(max_length=ID_LENGTH, primary_key=True, default=id_gen, editable=False)
class Meta:
abstract = True
class CustomPage(BaseModel):
...