Django的,prepopulated_fields

时间:2009-08-15 14:45:15

标签: django django-models

我想知道prepopulated_field是否在ModelAdmin之外可用?

我想创建一个slugfield,其值来自字段标题。

此致 Asinox

2 个答案:

答案 0 :(得分:2)

不是我知道的。 我使用javascript和AJAX做了类似的事情:当标题字段失去焦点时,带有它的AJAX请求被发送到你的应用程序中返回slug的url。这是javascript:

<script type="text/javascript">
Event.observe(window, 'load', function() {
    form = $("post_form");
    title = $('id_title');
    slug = $('id_slug');
    title.observe('blur', getSlug);
});

function getSlug() {
    var titleText = $F(title);
    ajax = new Ajax.Request("/blog/utils/get-slug", {
        'method': 'get',
        'parameters': {'title': titleText},
        'onSuccess': setSlug
    })

}
function setSlug(transport) {
    var slugText = transport.responseText;
    slug.value = slugText
}
</script>

它使用Prototype但您可以轻松使用jQuery或其他任何东西。 在Django方面,这里是AJAX请求被引导到一些辅助函数的视图:

def GetSlug(request):
    """This Django view provides a url-friendly slug based on a given post title. 
    It helps avoid primary key violations by creating different slug names 
    for posts with the same title.It is designed to be called by an AJAX 
    request from within the admin interface."""

    title = request.GET.get('title', None)
    title = unquote(title)
    if not title:
        return HttpResponseNotFound("")
    result = findSlug(title)
    if not result:
        result = ""
    return HttpResponse(result)    

def findSlug(title):
        title = urlify(title)
        words = title.split('-')
        if len(words) > 5:
            title = "-".join(words[0:5])
            extraWords = words[5:]
        else: 
            extraWords = []

        def testSlug(slug):
            try:
                Post.objects.get(slug=slug)
            except Post.DoesNotExist:
                return slug
            return False
        #if slug does not already exist, return that
        if testSlug(title):
            return title
        #if title had extra words, add them one at a time and test that
        else:
            for word in extraWords:
                title = title + "-" + word
                if testSlug(title):
                    return title
        #if we've run out of words and slug is _still_ not unique, try incrementing: title-2, title-3, etc. 
        incrementor = 2
        while incrementor < 10:
            tempTitle = title + "-%d" + incrementor
            if testSlug(tempTitle):
                return tempTitle
        #if all else fails, punt to the user
        return None

def urlify(string):
    """This takes a string (say, a post title) and convets it to something url-friendly

    >>> title = "I read \"War & Peace\" to-day"
    >>> urlify(title)
    i-read-war-and-peace-to-day

    """
    string = string.lower().strip() #remove leading, trailing whitespace
    string = string.replace("&", "and")
    string = re.sub("[^a-z0-9- ]", "", string) #remove non-alphanumeric chars  (except dashes and spaces)
    string = re.sub("\W+", "-", string) #replace whitespace with "-"
    string = re.sub("-{2,}", "-", string) #remove double dahses
    return string 

即使在标题可能已经存在于另一条记录的情况下,GetSlug视图也很难返回有用但又独特的内容。

答案 1 :(得分:2)

它不是立即可用的,但您可以轻松地创建自己的系统,而不是覆盖模型中的save()方法。例如

def save(self, *args, **kwargs):
    # If there is not already a slug in place...
    if not self.[name-of-slug-field]:
        # Import django's builtin slug function
        from django.template.defaultfilters import slugify
        # Call this slug function on the field you want the slug to be made of
        self.[name-of-slug-field] = slugify(self.[field-to-slugify])
    # Call the rest of the old save() method
    super([model-name], self).save(*args, **kwargs)

您需要更改方括号中的内容,使其与模型相关。

[name-of-slug-field]是模型中保存实际slug的字段(例如'this-is-slugged')

[field-to-slugify]是您要构建slug的字段(在您的情况下,它可能是title

[model-name]是此方法所在模型的名称

该代码的最后一行是我认为唯一可能复杂的位,它只是将旧save()方法的其余部分添加到其位置,因此当您调用save()时,它仍然在物理上提交更改到数据库。

显然,这些更改只会在服务器端进行,因此用户不会“看到”它们发生,所以如果你想模仿Django管理面板的工作原理(即,slug会自动出现在文本框中) slug),你需要加入mazelife的Ajax代码。