Django-博客搭建

本人未专门学过前端后端知识,只是一知半解,这篇文章主要作为扒源代码的思路,具体细节并未详细介绍!!!

Blog搭建

博客系统使用python编写,基于Django和clean-blog前段框架编写。
本文主要是修改DCblog并通过源码进行阶段性扫盲!!!

DCblog app

查看urls.py文件

urlpatterns = [
    path('admin/', admin.site.urls),
    url(r'^$', views.index, name='index'),
    url(r'^about/', views.about_view, name='about'),
    url(r'^article/', include('article.urls'), name='article'),
    url(r'^tag/', include('tag.urls'), name='tag'),
    url(r'^author/', include('author.urls'), name='author'),
]

urlpatterns += staticfiles_urlpatterns()
handler404 = 'dcblog.views.page404'
handler500 = 'dcblog.views.page500'

下面主要对这几个url进行介绍

url(r'^$', views.index, name='index'),

这儿根目录调用的是article.views.index,内容如下:
'''
def index(request):
paginator = Paginator(Article.objects.all(), 10)#实例化一个分页对象
page = request.GET.get('page')#获取页码
try:
articles = paginator.page(page)#获取某页对应的记录
except PageNotAnInteger:
articles = paginator.page(1)#如果页码不是整数,取第一页
except EmptyPage:
articles = paginator.page(paginator.num_pages)#如果页码太大,没有相应记录,取最后一页
return render(request, 'home.html', context={
'articles': articles
})
'''
打开home.html,里面内容介绍如下:
首先介绍Django的模板继承,也就是

{% extends 'base.html' %}

这儿继承的是base.html模板,查看base.html模板就能发现,这是博客的骨架。打开base.html,如下图:


这儿大家就可以根据自己的需要修改文字或者是图片,除了base.html文件中出现的文字,其他的都在dcblog/settings.py文件的DCBLOG_CONFIG中。
下面回到home.html文件中。
在继承base.html模板后,home.html继续做填充,填充方法如下:

{% extends "master.html" %}
 
{% block content1 %}
    content1里填充的内容
{% endblock %}

这儿填充的内容主要是显示页码内的文章和跳转页码。

具体细节可以看代码注释

url(r'^about/', views.about_view, name='about')

这儿调用的是about_view函数,代码如下:

def about_view(request):
    return render(request, 'about.html')

这儿没什么好说的,打开about.html文件。这儿依然是使用继承模板,然后发现如下代码:

{% extends 'base.html' %}
{% block header_id %}tag-heading{% endblock %}
{% block header_title %}一技破万法{% endblock %}
{% block header_subtitle %} 生活不止眼前的苟且, 还有诗和远方. {% endblock %}
{% block background-image %}{{ SITE_ABOUT_BACKGROUND }}{% endblock %}
{% block content %}

extend就是继承父模板,然后下面进行复写、填充。其中block是在子模版中可能会被覆盖掉的位置。在上面的例子中,block标签定义了三个可以被子模版内容填充的block,分别是 header_title 、header_subtitle和background-image。

{% extends 'base.html' %}
{% block header_id %}tag-heading{% endblock %}
{% block header_title %}一技破万法{% endblock %}
{% block header_subtitle %} 生活不止眼前的苟且, 还有诗和远方. {% endblock %}
{% block background-image %}{{ SITE_ABOUT_BACKGROUND }}{% endblock %}
{% block content %}

下面就是分块填写文字和链接,应该都能看懂了。

url(r'^article/', include('article.urls'), name='article'),
url(r'(?P[0-9]+)/$', views.detail, name='detail'),

首先介绍一下Django中的URL模块

  1.  Django处理请求的方式
    

1) Django通过URLconf模块来进行判断。通常情况下,这就是ROOT_URLCONF配置的价值,但是如果请求携带了一个urlconf的属性(通常被中间件设置),那么这个被携带的urlconf将会替代ROOT_URLCONF的配置。
2) Django会调用Python模块并寻找各种urlpatterns。这是一个属于django.conf.urls.url()实例的python列表。
3) Django会遍历每个URL pattern,自上而下,并且选取收割匹配请求URL的pattern。
4) 一旦匹配某个url pattern的正则表达式,Django将导入并调用相关的view(这是一个简单的python函数,或者是一个class-based view)
这个view将会传递下列参数:

  • 一个HttpRequest的实例
  • 如果匹配了URL中一个no named group,那么参数将会按根据URL中的位置一一对应
  • 如果匹配了URL中一个named group,且参数传递是通过named group来匹配的,那么参数将会被指定的kwargs代替。
    5) 如果没有任何一个正则表达式被匹配,那么Django会抛出异常,并报错。
  1.  URL中的named  group
    

URL可以通过named group方式传递指定参数,语法为: (?Ppattern), name 可以理解为所要传递的参数的名称,pattern代表所要匹配的模式。例如:

url(r'^articles/(?P[0-9]{4})/(?P[0-9]{2})/$', views.month_archive),

那么year,month将会对应views传递过来的year,month的值,而后面紧跟的则代表正则表达匹配的模式。

  1. URL的反向解析
    通常来说在处理完一个表单之后,网页会发生跳转。通常写URL我们都避免硬编码,这样不方便后期的调整。通常我们需要从URL获取两种内容,最主要是view能够通过URL获取一些标识并处理,另一些信息则是传递过来的参数。
    Django提供了一种解决方案,URL mapper是与URL设计一一对应。你可以通过URLconf来实现,并反向使用它。例如,
     由用户通过浏览器发起URL请求,调用view,并将URL中的参数传递给view
     通过view并附上相应参数,找到相应匹配的URL。
    后者我们称之为对URLs的反向解析。反向解析的例子,
url(r'^articles/([0-9]{4})/$', views.year_archive, name='news-year-archive'),

下面对于这个链接进行解析一下:
当在home.html中点击文章时,会跳转到文章界面,其中跳转的路径为:{% url 'article:detail' article.id%}。假设点击最上面一篇文章,地址为:http://x.x.x.x/article/12/,也就是article.id=12,然后跳转到detail函数:

def detail(requests, article_id):
    article = get_object_or_404(Article, pk=article_id)
    # article.content = markdown.markdown(article.content, extensions=[
    #     'markdown.extensions.extra',
    #     'markdown.extensions.codehilite',
    #     'markdown.extensions.toc'
    # ])
    tags = article.tag.all()
    return render(requests, 'article_detail.html', context={
        'article': article,
        'tags': tags
    })

介绍函数: article = get_object_or_404(Article, pk=article_id)
用特定查询条件获取某个对象,成功则返回该对象,否则引发一个 Http404。

get_object_or_404(klass, *args, **kwargs)

参数:

  • klass
    接受一个 Model 类,Manager 或 QuerySet 实例,表示你要对该对象进行查询。
  • kwargs
    查询条件,格式需要被 get() 和 filter() 接受。
    这儿将所有的标签(article和tags)传递到article_detail.html代码中,然后在里面调用。
    打开article_detail.html代码,可以看到如下几部分:
  1. 标签页跳转:显示所有tags,点击跳转到标签页即tags。
  2. 编辑文章:只有登录了才能有这一个选项,点击跳转到edit函数,
url(r'(?P[0-9]+)/edit$', views.edit, name='edit'),

这儿就是编辑文章所对应的url,先进入edit函数看一下:

@login_required(login_url=reverse_lazy('author:login'))
def edit(request, article_id):
    article = get_object_or_404(Article, pk=article_id)
    if article.author != request.user and request.user.is_superuser:
        return HttpResponseForbidden(render_to_response('error.html', {
            'status_code': 403,
            'message': 'Forbidden :('
        }))
    form = ArticleForm(request.POST or None, instance=article)
    if request.method == 'POST' and form.is_valid():
        form.save()
        return HttpResponseRedirect(reverse_lazy('article:detail', kwargs={
            'article_id': form.instance.id
        }))
    context={
        'form': form,
        'header_id': 'tag-heading',
        'title': '编辑文章',
        'subtitle': form.instance.title,
        'background': form.instance.background or settings.DCBLOG_CONFIG.get('SITE_ARTICLE_BACKGROUND'),
        'submit': '保存编辑'
    }
    return render(request, 'generic_form.html', context=context)

这儿首先读取article,然后判断登录的user是不是文章作者,只有文章作者才能修改文件。非文章作者返回值如下:



往下接着读代码,这儿添加一个表单
表单内容为:





代码理解后续补上

    form = ArticleForm(request.POST or None, instance=article)
    if request.method == 'POST' and form.is_valid():
        form.save()
        return HttpResponseRedirect(reverse_lazy('article:detail', kwargs={
            'article_id': form.instance.id
        }))

然后将参数传递给generic_form.html代码

{% extends "base.html" %}
{% block head %}
    {{ block.super }}
    
{% endblock %}

{% block background-image %}{% spaceless %}
    {% if background %}
        {{ background }}
    {% else %}
        {{ SITE_FORM_BACKGROUND }}
    {% endif %}
{% endspaceless %}{% endblock %}
{% if header_id %}
    {% block header_id %}{{ header_id }}{% endblock %}
{% endif %}
{% block header_title %}{{ title }}{% endblock %}
{% block header_subtitle %}{{ subtitle }}{% endblock %

在这段代码中,就是将context中的内容显示出,然后下面就是细化每个模块,这儿
调用form表单,也就是上面表单内容,创建四个窗口并输入。然后创建一个保存编辑按钮。


url(r'^tag/', include('tag.urls'), name='tag'),

进入tag/urls.py函数,可以看到:


app_name = 'tag'
urlpatterns = [
    url(r'^$', views.tag_index, name='tag_index'),
]

进入views.py函数:


def tag_index(request):
    tags = Tag.objects.all()
    return render(request, 'tag.html', {'tags': tags})

这儿调用的是tag.html代码,进入html代码:

{% extends 'base.html' %}
{% block head %}
    {{ block.super }}
    
{% endblock %}


{% block header_title %}标签{% endblock %}
{% block header_subtitle %}
{% for tag in tags %} {{ tag.name }} {% endfor %}
{% endblock %} {% block background-image %}{{ SITE_TAG_BACKGROUND }}{% endblock %}

这儿就是把title改成标签,然后将所有标签进行排列



其中每个标签都带有herf,分别跳到下面每个标签模块,下面每个标签模块都有一个标签名,后面for排列出该标签的文章,点击文章调用article:detail article.id显示文章。

url(r'^author/', include('author.urls'), name='author'),

进入author/urls.py中, 总共三个二级url,分别对应登录、注册、注销三部分

url(r'^login/', views.login_view, name='login'),

查看login_view函数

@login_denied
def login_view(request):
    form = LoginForm(request.POST or None)
    if request.method == 'POST' and form.is_valid():
        username = form.cleaned_data['username']
        password = form.cleaned_data['password']
        user = User.objects.filter(username=username).first()
        if user and user.check_password(password):
            login(request, user)
            return HttpResponseRedirect(reverse_lazy('index'))
        messages.add_message(request, messages.ERROR, '用户名或密码错误.')
    context = {'form': form,
               'title': '登陆',
               'subtitle': 'login site',
               'submit': '登陆'
               }
    return render(request, 'generic_form.html', context)

这儿调用LoginForm表单,然后将输入添加到表单,再进行对比,显示界面由genetic_form.html进行显示,登录成功之后返回主界面。

url(r'^register/', views.register_view, name='register'),

查看register_view函数

@login_denied
def register_view(request):
    form = RegisterForm(request.POST or None)
    if request.method == 'POST' and form.is_valid():
        form.save()
        return HttpResponseRedirect(reverse_lazy('index'))
    context = {
        'form': form,
        'title': '注册',
        'subtitle': 'register and write',
        'submit': '注册'
    }
    return render(request, 'generic_form.html', context)

这儿调用RegisterForm表单,同上!

url(r'^logout/', views.logout_view, name='logout'),

这儿没什么好讲的,就是退出返回到最原始界面。



到这儿基本上就能看懂这个博客的大体架构了,具体细节部分如果后期还要改再扒!!!

fork自基于Django和clean-blog前端框架的博客系统

一技破万法

你可能感兴趣的:(Django-博客搭建)