Симпатичные и SEO-ссылки в django

В настоящее время я пишу веб-блог, изучая django. Мне нужно представление, чтобы отобразить один блог-пост, и моя первая попытка заключалась в том, чтобы создать для него URL-адрес следующим образом:

myblog.com/blog/view/1

Здесь используется идентификатор блога, чтобы идентифицировать указанный блог-пост.

Теперь, если вы посмотрите на многие блоги/веб-сайт, вы увидите, что они используют заголовок блога в URL-адресе, потому что это больше дружественно поисковой системе, поэтому его легче найти. Это может выглядеть так.

myblog.com/blog/view/a-python-backup-script

Как это реализовать в django?

Бонусный вопрос: Многие сайты также включают месяц и год публикации. Я предполагаю, что это также связано с SEO, но насколько это полезно?

Ответ 1

Добавьте поле бланка в вашу модель блога.

from django.template.defaultfilters import slugify

Class Blog(models.Model):
    title = models.CharField(max_length=40)
    slug = models.SlugField(_('slug'), max_length=60, blank=True)

    #Then override models save method:
    def save(self, *args, **kwargs):
        if not self.id:
            #Only set the slug when the object is created.
            self.slug = slugify(self.title) #Or whatever you want the slug to use
        super(Blog, self).save(*args, **kwargs)

В вашем urls.py

(r'^blog/view/(?P<slug>[-\w]+)/$', 'app.views.blog_view'),

В views.py

def blog_view(request, slug):
    blog = Blog.objects.get(slug=slug)
    #Then do whatever you want

EDIT: я добавил проверку в метод сохранения, так как вы хотите, чтобы slug создавался при создании объекта. Его не следует сохранять каждый раз.

Ответ 2

Убедитесь, что у вашей модели действительно поле пули:

class BlogPost(models.Model):
    slug = models.SlugField(unique=True)

и что у вас есть представление:

from django.shortcuts import get_object_or_404
def blog_detail(request, slug):
    ...
    post = get_object_or_404(BlogPost, slug=slug)
    ...
    render(request, "blog/blog_post.detail.html", { 'blog_post' : post })

а затем в вашем urls.py вы можете указать slug:

url(r'^(?P<slug>[-w]+)/$', 'blog.views.blog_detail', {}, name="blog_detail"),

первый аргумент является регулярным выражением, которое при сопоставлении запускает представление view blog_detail и передает согласованную группу slug из обычного выражения в представление thew (которое, в свою очередь, отображает и возвращает шаблон)

Что касается вашего последнего момента: я считаю, что, как и потенциально быть позитивным с точки зрения SEO, наличие дат в URL-адресе позволяет мне намного легче узнать, является ли сообщение в блоге новым с первого взгляда. Кроме того, в Django очень просто использовать этот подход наряду с основанные на дате общие представления, которые сократят количество просмотров плиты котла код, который вам нужно написать. Это будет пример:

url(r'(?P<year>d{4})/(?P<month>[a-z]{3})/(?P<day>w{1,2})/(?P<slug>[-w]+)/$', 
        'django.views.generic.date_based.object_detail', 
        { template_name = "blog/detail.html", ... }, 
        name="blog_detail"),

Ответ 3

Или, если вы используете представления на основе классов, самое главное, что вы можете сделать:

from django.views.generic import DetailView
from models import Blog

class BlogView(DetailView):
    model = Blog
    template_name = "blog/blog_detail.html"

Затем url выглядит примерно так:

from views import BlogView

url(r'^(?P<slug>[-w]+)/$', BlogView._as_view(), name="blog_detail"),

Обратите внимание, что дженерическое DetailView Django ожидает либо pk, либо slug. Таким образом, использование slug ничем не отличается от использования pk в этом случае.

Ответ 4

Этот аналогичный метод обратно совместим с URL-адресами, в которых нам присваивается числовой идентификатор.

Добавьте поле slug и сохранить в models.py:

from django.template.defaultfilters import slugify

slug = models.SlugField(default='no-slug', max_length=60, blank=True)

def save(self, *args, **kwargs):
    #save a slug if there is no slug or when it 'no-slug' (the default slug)
    if not self.slug or self.slug == 'no-slug':
        self.slug = slugify(self.name)
    super(Project, self).save(*args, **kwargs)

Добавьте второй URL URL в urls.py:

#original:
url(r'^(?P<id>\d+)/$', 'project.views.view', name='view_url'),
#new pattern added under original:
url(r'^(?P<id>\d+)-(?P<slug>[-\w\d]+)/$', 'project.views.view', name='view_url'),

В views.py пусть slug проходит через:

def view(request, mid=None, slug=None):

Затем все, что вам нужно сделать, чтобы использовать этот URL, - это edit models.py:

def get_absolute_url(self):
    return reverse('view_url', args=[self.id, self.slug])

Ответ 5

django-autoslug прекрасно работает для этой цели и имеет множество полезных опций.