Django-博客搭建

作者: 一技破万法 | 来源:发表于2020-07-01 18:45 被阅读0次

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

    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<article_id>[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方式传递指定参数,语法为: (?P<name>pattern), name 可以理解为所要传递的参数的名称,pattern代表所要匹配的模式。例如:

    url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[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<article_id>[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是不是文章作者,只有文章作者才能修改文件。非文章作者返回值如下:



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

    <tr><th><label for="id_title">标题:</label></th><td><input type="text" name="title" value="ff" class="form-control" placeholder="标题" maxlength="100" required id="id_title"></td></tr>
    <tr><th><label for="id_background">背景图片:</label></th><td><input type="text" name="background" class="form-control" placeholder="背景URL, 默认 /static/img/article-bg.png" maxlength="500" id="id_background"></td></tr>
    <tr><th><label for="id_tag_list">Tag list:</label></th><td><input type="text" name="tag_list" value="sddf" class="form-control" placeholder="Tags" id="id_tag_list"></td></tr>
    <tr><th><label for="id_content">正文:</label></th><td><textarea name="content" cols="40" rows="10" class="form-control" placeholder="markdown正文" row="20" id="id_content">
    df</textarea></td></tr>
    

    代码理解后续补上

        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 }}
        <link rel="stylesheet" href="/static/css/hux-blog.min.css">
    {% 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 }}
        <link rel="stylesheet" href="/static/css/hux-blog.min.css">
    {% endblock %}
    
    
    {% block header_title %}标签{% endblock %}
    {% block header_subtitle %}
    <div id="tag_cloud" class="tags">
        {% for tag in tags %}
        <a href="#{{ tag.name }}" style="background-color: rgb(0, 133, 161);">{{ tag.name }}</a>
        {% endfor %}
    </div>
    {% 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-博客搭建

        本文链接:https://www.haomeiwen.com/subject/aitfqktx.html