Как написать простой блог на Django

Совершенно элементарно. Изучаете html, css, js, python, django, потом пишете :)

А можно просто скопировать исходники моего блога и пользоваться. Но лучше всё-таки не просто пользоваться, а взяв их за основу написать что-то своё. Хотя, сперва не лишним будет ознакомиться со статьёй на Хабре, где подробно описываются самые начала.

Функциональность блога (точнее её отсутствие) вы можете наблюдать самостоятельно. Некоторые возможности скрыты или не бросаются в глаза, поэтому вот их краткий список:

  • Обособленные записи (по аналогии со "страницами" WordPress)
  • Рубрики (не более одной для каждой записи)
  • Редактируемые или автоматически генерируемые meta description
  • Древовидные комментарии (2 вида сортировки: "вложенная" и "плоская")
  • Начальные возможности фильтрации спама по чёрному списку
  • Возможность выводить кусочки html-кода из базы в любом месте шаблона (произвольно наполняемый и более удобный аналог WordPress-овской функции bloginfo)

Комментарии (RSS)

Я вот недавно наткнулся на эту статейку. Несколько часов парился так и ничего не вышло. Просто изначально пытался все сделать с питоном третьим, но сдался и начал заново. Сейчас остановился на том, что я видимо не правильно прикручиваю аккаунт от disqus к приложению.

Буду очень признателен, если поможете.

Ответить Отменить ответ

С disqus я вам не смогу помочь, я им не пользовался и не собираюсь. Попробуйте посмотреть на форуме, там что-то такое было не так давно.

Ответить Отменить ответ

Пытаюсь изучить Django, взял за основу приложение-блог, что в статье на хабре, и смотрю ваши исходники на гитхабе, и пытаюсь реализовать функционал, который в вашем блоге. Правда пока мало что получается.

Ответить Отменить ответ

Тут функционала-то нет никакого. Что конкретно не получается?

Ответить Отменить ответ

Ну, для меня и пагинация - функционал, может я не так понимаю значение этого слова..

Да были проблемы с выводом абсолютного пути категории, но уже разобрался. Есть много разных вопросов, задам один из них: как вывести настройки (Settings). Я так и не пойму, в шаблоне переменная, site_title, откуда она взялась, как передалась в шаблон? Как вывести эти настройки? Я думал, что может в классе настроек, создать что-то типа get_site_name()..

Ответить Отменить ответ

Скорее всего это из серии "научи меня плохому", потому что наверняка есть более правильные пути, но задумка следующая. В базу руками заносится настройка, например с такими параметрами: name='site_title', value='Slave of the Lamp', autoload=True. Настройки, которые имеют autoload=True, подтягиваются в шаблон вот этим кодом (строки 26-29): https://github.com/lampslave/blog/blob/master/lbe/views.py#L26. Чтобы лучше понять, как это работает, прочитайте про mixin-ы.

Ответить Отменить ответ

Ясно, мне как раз этот блок кода не понятен, т.е. как выводится сайдбар (функция get_aside_content и класс AsideMixin). Можете, пожалуйста, прокомментировать этот участок кода? https://github.com/lampslave/blog/blob/master/lbe/views.py#L24-51

Ответить Отменить ответ

get_aside_content просто подтягивает из базы разные нужные данные - страницы, рубрики и т.п. AsideMixin служит для того, чтобы "смешать" результаты работы его собственной функции get_context_data (которая вызывает get_aside_content) с результатами работы get_context_data каждого из видов, которые от этого миксина наследуются, например ArticleDetail.

Ответить Отменить ответ

Ух, спасибо за объяснения, попробовал, работает. Не нравится что настройки блога находятся в сайдбаре. Можно это изменить? Для этого нужно создать новый миксин? А как тогда указывать будет правильно, чтобы отобразить настройки сайта, вне сайдбара?

Ответить Отменить ответ

Расположение элементов меняется в шаблонах (тот же {{site_title}} находится вовсе не в сайдбаре, а в хедере), миксин просто делает данные доступными. Слово "aside" в данном случае не указывает на сайдбар, а обозначает разные данные, не относящиеся напрямую к контенту страницы. Вы можете свободно переименовать и миксин, и функцию, от этого ничего не изменится.

Ответить Отменить ответ

Понятно, спасибо.

Ответить Отменить ответ

Прочитала в разделе "О себе" просьбу писать в комментарии про ошибки с запятыми. Там, где так: "а взяв их за основу написать " , нужно вот так: "а, взяв их за основу, написать ".

Ответить Отменить ответ

если оставить ответ, то кнопка "Отменить ответ" будет подсвечиваться на каждом комменте. Баг или фича?)

Ответить Отменить ответ

В смысле "оставить"? Ссылка предназначена для того, чтобы закрыть форму и получить возможность не отвечать на комментарий, а написать его под остальными. После отправки сообщения страница перезагружается и она исчезает.

Ответить Отменить ответ

а, ну да, у меня на вашем сайте js был отключен, поэтому было вот так:

scrsht

Ответить Отменить ответ

Пытался запустить блог: не получилось. Летом работал.

ошибки: line 250 exec template in namespace

ошибка в синтаксе при загрузке /python3.4/site-packages/recordtype.py ошибка возникает и в прошлой версии блога если загружать этот модуль в питоне, но сам сайт при этом работает. что очень странно. Предположительно разница в версии Джанго. сейчас 1.7 раньше была 1.6, говорят поменялся процесс загрузки в Джанго.

Ответить Отменить ответ

Блог работает на втором питоне, переезжать на третий я пока не собираюсь. Хотя совместимостью надо будет заняться как-нибудь.

Ответить Отменить ответ

Теперь всё должно работать и на третьем тоже.

Ответить Отменить ответ

Сколько у Вас времени ушло на создание этого блога?

Ответить Отменить ответ

Сложно сказать, тем более, что я занимался им не каждый день, а по настроению. Ну и Django попутно изучал.

Ответить Отменить ответ

Пытаюсь реализовать отправку комментариев с помощью CreateView отталкиваясь от Ваших исходников. При попытке отправить коммент, я получаю ошибку: IntegrityError at /comment/add/

null value in column "comment_article_id" violates not-null constraint

не могли бы Вы подсказать, что я делаю не так?

Ответить Отменить ответ

По всей видимости у вас либо с самой формой косяк, либо с её выводом в шаблоне. Идентификатор связанной статьи не передаётся.

Ответить Отменить ответ

я уже всё что только могло в голову прийти перепробовал, но так и не смог определить, что не так. Можете, пожалуйста, посмотреть на код? models.py

class Article(models.Model):
    title = models.CharField(max_length=255)
    content = models.TextField()
    slug = models.SlugField(max_length=150, unique=True)

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse('article_detail', kwargs={'slug':self.slug})

class Comment(models.Model):
    comment = models.TextField()
    comment_article = models.ForeignKey(Article)

    def get_absolute_url(self):
        return reverse('article_detail', kwargs={'slug':self.comment_article.slug})

forms.py

class CommentForm(ModelForm):
    class Meta():
        model = Comment
        fields = ['comment']

views.py

class ArticleDetailView(DetailView):
    model = Article
    context_object_name = 'article'
    template_name = 'article_detail.html'

    def get_context_data(self, **kwargs):
        context = super(ArticleDetailView, self).get_context_data(**kwargs)
        context['comments'] = Comment.objects.filter(comment_article=self.object)
        context['comment_form'] = CommentForm(initial={'comment_article': self.object.pk})
        return context

class AddComment(CreateView):
    model = Comment
    form_class = CommentForm
    template_name = 'article_detail.html'
    http_method_names = ['post']

urls.py

url(r'^(?P<slug>[-\w]+)$', ArticleDetailView.as_view(), name='article_detail'),
url(r'^comment/add/$', AddComment.as_view(), name='comment_add'),

article_detail.html

          {{ article.title }}
          {{ article.content }}
          {% for comment in comments %}
              {{ comment.comment }}
          {% endfor %}
          {% include 'comment_form.html' with form=comment_form %}

и comment_form.html

<form action="{% url 'comment_add' %}" method="POST" role="form">
    {% csrf_token %}
    {{ form.as_p }}
    <input type="submit" class="btn btn-primary" value="Отправить">
</form>
Ответить Отменить ответ

Судя по всему вы просто не совсем правильно передаёте initial в форму, там надо не self.object.pk, а просто self.object. У вас публичного репозитория нет случайно? С кодом в комментариях не очень удобно работать.

Ответить Отменить ответ

Про репозиторий я просто на всякий случай хотел узнать, по идее замена, которую я предложил выше, должна была всё исправить.

Ответить Отменить ответ

К сожалению, это не помогло. Застрял я и не могу выбраться. Вроде сделано так же, как и в Ваших исходниках

Ответить Отменить ответ

Похоже, что я слегка поторопился. Форма действительно проглатывает оба варианта initial, только проблема в том, что эти данные уходят в никуда, поскольку в форме просто нет поля со статьёй :) Добавьте сюда comment_article и всё будет работать.

Ответить Отменить ответ

Так ведь если в форму добавить поле 'comment_article', оно будет отображаться пользователю, что, если я не ошибаюсь, делать неправильно. Что скажите?

Ответить Отменить ответ

Здравствуйте. У меня возникли проблемы при переносе на хостинг вашего проекта. Проблема заключается в том что не все таблицы в базе создаются. выполняю:

pip install -r pipreq.txt
и
python manage.py migrate

БД mysql, создается всего 12 таблиц, припереходе на сайт пишет:

Exception Value: (1146, "Table 'blog.lbe_templatesnippet' doesn't exist")

как понимаю не создалась таблица lbe_templatesnippet Прошу помощи с переносом, уж очень нравится ваш проект.

Ответить Отменить ответ

Возможно, вы забыли добавить lbe в INSTALLED_APPS.

Ответить Отменить ответ

Я клонировал проект, lbe там уже прописан

Ответить Отменить ответ

Тогда, возможно, lbe нет в PYTHONPATH. Запустите питон и попробуйте импортировать lbe.

Ответить Отменить ответ

Поборол makemigrations lbe затем migrate Спасибо за оперативный ответ и ваш проект.

Ответить Отменить ответ

Не за что. Вообще, миграции там есть, может быть они у вас не скопировались почему-то?

Ответить Отменить ответ

Ну главно решил и все работает уже на хостинге. Еще вопрос хочу такую же модерацию коментариев... как настраивали?

Ответить Отменить ответ

Да в общем-то никак, всё уже прописано в коде. Для полного счастья надо забанить ie6 и добавить в чёрный список всякие "копии швейцарских часов" (тут сами посмотрите, чем спамить будут, только не перестарайтесь).

Ответить Отменить ответ

Извините за глупые вопросы. Я только начинаю изучать python и данный фреймворк. У меня такой вопрос: есть в шаблоне base.html теги {{ site_title }} {{ site_copyright }} {{ site_counters }} и насколько я понимаю значение этих тегов привязано к админке. Подозреваю что это пункт "Настройки"... Может я не правильно мыслю? Понимаю что можно просто прописать статические данные в шаблоне но хочу разобраться зачем эти теги, и использовать их. Заранее очень благодарен за помощь.

Ответить Отменить ответ

Ничего страшного, все когда-то начинали, к тому же у меня там комментариев нет совсем, так что разобраться сложновато. Чуть выше был аналогичный вопрос, но там я отвечал по старой реализации. Сейчас используется контекстный процессор, который добавляет в контекст сниппеты ("настройками" они назывались раньше).

Настройки сейчас не используются, возможно даже, что я зря их отделил от сниппетов, можно было использовать Constance вместо обеих моделей и не париться. Хотя на уровне бложика любой велосипед прокатит :)

Ответить Отменить ответ

Сниппеты не такая уж и плохая идея) Про Constance почитаю позже, а "настройки" я так понял можно выпилить с проэкта? или использовать каким то образом?

Ответить Отменить ответ

Не знаю, смотрите сами. Если решите прикрутить отправку почты через Яндекс, то в настройки можно будет логин и пароль записывать. А так они по большому счёту не нужны, настраивать всё равно особо нечего.

Ответить Отменить ответ

Не. Через яндекс не буду т.к пользуюсь "балконным сервачком" а там уже наличие postfix и dovecot предусмотренно. Спасибо за помощь потихоньку начал соображать что к чему.

Ответить Отменить ответ

Здравствуйте,пишу коменты и ответы на них,не могу понять как привязать ответ на коммент к родителю?

Ответить Отменить ответ

У меня привязка идёт через поле parent.

Ответить Отменить ответ

Уважаемый lampslave нашел очень полезным ваш исходник. Ну и как вы разрешили его использовать я использую но столкнулся с вот такой проблемой.

Error during template rendering

In template /home/yoin/projects/grape/blog/templates/blogs.html, error at line 0
Reverse for 'comment_add' with arguments '()' and keyword arguments '{}' not found. 0 pattern(s) tried: []
1     {% extends 'main.html' %}
2     {% load staticfiles%}
3     {%block blog%}
4     
5             <h6>{{blog.blog_pub_date}}</h6>
6     
7             <h4>{{blog.blog_title}}</h4>
8     
9                 
10             <p>{{blog.blog_text}}</p>

Не могу понять в чем проблема.

Ответить Отменить ответ

Я что-то не помню у себя такого шаблона :) Покажите полностью (лучше на github или pastebin каком-нибудь). Вы где-то пытаетесь получить url comment_add и не передаёте в него идентификатор статьи, вот оно и не работает.

Ответить Отменить ответ

Хорошо буду дома кину на гитхаб. А не видите потому что я по примеру вашего шаблона пытался обрисовать свои модели :)

Ответить Отменить ответ

Вот, сильно не ругайте, там жуткая каша! Извините если что я 2 недели как закончил курсы Пайтон, и самостоятельно изучаю Джангу с CSS И HTML http://github.com/YSOin/grape

Ответить Отменить ответ

Кашу легко привести к более адекватному виду просто нажав ctrl+alt+l, хотя конечно лучше сразу писать нормально, вам самому проще будет разбираться. Прочитайте про PEP8 и соблюдайте всё, что там написано, а ещё не следуйте моему примеру и всегда пишите название параметра verbose_name в моделях.

Что касается ошибки, в blogs.html у вас подключается шаблон comments_form.html, в котором резолвится урл comment_add. Джанга не может найти такой урл в конфиге, потому что он закомментирован, вот и показывает ошибку.

Ответить Отменить ответ

Уважаемый lampslave следовал вашим советам и все исправил. Но возникли новые препятствия. На общей странице все отображаеться как и должно. Когда переходим по конкретному ID блога. Там тоже все отбражается, ну практически все... Суть проблемы:

  1. Если в Админке добавить комментарии они видны и под ними появилась кнопка отправить.
  2. Если нажимаем кнопку, получаем ошибку ValueError at /comments/add/

Cannot assign None: "comments.comments_blog" does not allow null values.

  1. Нету поля для написания комментариев пользователем, поможете?

git@github.com:YSOin/grape.git

Ответить Отменить ответ

А вы запись, к которой относятся комментарии, сохраняете, перед тем как комментарии добавлять?

Ответить Отменить ответ

Где у вас можно посмотреть на пример такого действия? Что то не могу найти.

Ответить Отменить ответ

Решил вопрос, вот такой views

def blog_view(request, blog_id):
    n = blog.objects.get(pk=blog_id)
    if request.method == 'POST':
        c = comments()
        c.comments_text=request.POST.get("text", "")
        c.comments_blog=n
        c.save()
    return render(request, 'blogs.html', {'blog': n})

Форму описал в общем шаблоне.

    {% for comments in blog.comments_set.all %}
        <p>{{ comments.comments_text }}</p>
    {% endfor %}
    <div class="form">
        <form action="" method="POST" role="form">
            {% csrf_token %}
            <p><textarea rows="10" cols="45" name="text"></textarea></p>
            <input type="hidden" name="blog_pk" value="{{ blog.pk }}">
            <input type="submit" class="btn btn-primary" value="Отправить">
        </form>
    </div>
Ответить Отменить ответ

Если Вам накладно, мне что-либо объяснять. Скажите прямо, я пойду дальше искать ответы на свои вопросы. Если что извините, за отнятое время.

Ответить Отменить ответ

Привет! Делаю комментарии и почему то, заполненная форма даже в модель не сохраняется, а просто переходит на другой url и выводиться заново и даже там не сохраняет ничего...

Ответить Отменить ответ

У меня, как видите, комментарии работают, посмотрите исходники блога и сравните со своими. Скорее всего вы не сделали вывод ошибок и поэтому не видите, что не понравилось джанге.

Ответить Отменить ответ