前言
在学习Python的过程中,觉得有必要学一学Python做web开发,而django作为一种优秀的Python Web框架,自然成为了我的首选,经过不到一个月的学习,总算搞清楚了django的大部分结构和基本的语法,如果你想学django,就和我一起来做一个用django开发的小型个人博客吧!
了解django
django是遵循MVC设计模式的框架,MVC是Model、View、Controller这三个单词的缩写,分别代表了模型,视图,控制器。对于我个人的理解来讲,模型用来与数据库进行交互,视图用来封装html、js、css,控制器则用来处理程序的请求、逻辑结构等。
准备工作
Python3+django2.0+PycharmPro2018
创建项目
你可以使用Pycharm创建,更加方便。
你也可以使用命令行创建,django-admin startproject myblog,当然前提是你已经安装了django,并且cd到了你想把项目创建到哪个目录的具体位置。一行命令创建了一个myblog的项目,接下来我们就该创建app了,先来讲下app与项目之间的关系。
项目和app之间的关系
对于django来说,项目只是一个大框架,他的具体功能还需要在app里面实现,app所对应的就是一个一个的功能模块,比如拿chabug来说,有用户模块,也有文章模块,也有专题模块。
你可以进入到项目的目录,然后这样来创建app python3 manage.py startapp blog
运行
在Pycharm里面你只需要点击右上角的运行按钮就可以运行了,默认是运行在本地的8000端口,也就是127.0.0.1:8000,如果你需要在命令行里面运行,你可以这样python3 manage.py runserver 8000,当然这样运行的只能在本地访问,如何把我们的项目发布出去对公网用户开放呢?下面会讲到。
项目结构
manage.py 项目管理脚本,你可以通过python3 manage.py help查看你能够干什么 settings.py 项目的设置都存放在这 urls.py 这个是用来配置项目的url,例如127.0.0.1/chabug/,或者127.0.0.1/chuyu wsgi.py 部署的时候用到的,一般上用不到
URL与视图
视图
视图一般写在APP的views.py中,并且第一个参数永远是request对象,这个对象包含了一些请求信息,比如:请求方法GET、POST,头部headers信息等等,然后视图必须返回一个HttpResponseBase,比如下面这个:
from django.shortcuts import render,HttpResponse
def hello(request):
return HttpResponse("hello")
当然,你现在并不能在浏览器中看到HttpResponse返回的hello,因为我们还没有定义urls.py中的内容,下面就跟我来配置一波把!
URL映射
from django.contrib import admin
from django.urls import path
urlpatterns = [
path('admin/', admin.site.urls),
]
这是默认的配置,其中admin这一条是django系统自带的映射后台,不用管他。我们来添加一条url来映射我们的hello,首先从app导入views.py
form blog import views
然后添加一条映射关系
from django.contrib import admin
from django.urls import path
from blog import views
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.hello),
]
django会自动从urlpatterns中寻找当前请求url所对应的规则,返回相应的信息。
这个时候在访问127.0.0.1:8000则会出现我们在视图中返回的HttpResponse信息hello
URL传参
两种方法
views.py
def A(request,id):
text = "你请求的id是:%s " % id
return HttpResponse(text)
urls.py
from django.contrib import admin
from django.urls import path
from blog import views
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.hello),
path('A/<id>', views.A),
]
你可以这样访问127.0.0.1/A/id
第二种
views.py
def B(request):
id = request.GET.get['id']
text = "你请求的id是:%s " % id
return HttpResponse(text)
urls.py
from django.contrib import admin
from django.urls import path
from blog import views
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.hello),
path('B/', views.B),
]
你可以这样访问 127.0.0.1:8000/B/?id=1
URL反转
之前我们都是通过url来访问视图函数。有时候我们知道这个视图函数,但是想反转回他的url。这时候就可以通过 reverse 来实现。示例代码如下:
reverse("list")
> /book/list/
传递参数
reverse("book:detail",kwargs={"book_id":1})
> /book/detail/1
URL和视图我们就暂时讲到这里,接下来我们要开始写了,模板的知识会融在其中。
创建模型
from django.db import models class Article(models.Model): title = models.CharField(max_length=50) #文章标题 category = models.CharField(max_length=50, blank=True) #文章分类 datetime = models.DateTimeField(auto_now_add=True) #文章发表日期 content = models.TextField(blank=True, null=True) #文章内容 def __str__(self): return self.title class Meta: ordering = ['-datetime'] #以日期倒序
创建完模型后我们需要把模型同步到数据库中
python3 manage.py makemigrations python3 manage.py migrate
然后在admin.py中注册下我们创建的模型
from django.contrib import admin from blog.models import Article # Register your models here. admin.site.register(Article)
注册模型让我们在django自带的后台管理中显示出来127.0.0.1:8000/admin
发布文章什么的都可以在这操作。
URL设计
我直接贴我的代码
from django.contrib import admin
from django.urls import path
from blog import views
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.index, name='index'),
path('<int:id>/', views.detail, name='detail'),
path('archives/', views.archives, name='archives'),
path('tag/<str:tag>', views.tags, name='tag'),
path('search/', views.search, name='search')
]
视图设计
from django.shortcuts import render, redirect
from blog.models import Article
from django.http import Http404
# 首页视图,展示所有的文章
def index(request):
sessionid = request.COOKIES.get('sessionid')
post_list = Article.objects.all()
return render(request,'index.html',{'post_list': post_list, 'sessionid':sessionid})
#文章详情视图,展示详细的文章内容
def detail(request,id):
try:
post=Article.objects.get(id=id)
except:
raise Http404
return render(request,'post.html',{'post':post})
#文章归档
def archives(request):
try:
post_list = Article.objects.all()
except Article.DoesNotExist :
raise Http404
return render(request, 'archives.html', {'post_list': post_list, 'error': False})
#分类作为标签,展示同分类下的文章
def tags(request, tag):
post_list = Article.objects.filter(category__iexact=tag)
return render(request,'tags.html', {'post_list': post_list})
#搜索
def search(request):
if 's' in request.GET:
s=request.GET['s']
if not s:
return render(request,'index.html')
else:
post_list=Article.objects.filter(title__icontains=s)
if len(post_list)==0:
return render(request, 'archives.html',{'post_list':post_list,'error':True})
else:
return render(request, 'archives.html',{'post_list':post_list,'error':False})
return redirect('index')
模板设计
父模板导航条完成
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Index{% block title %} - MyBlog{% endblock %}</title>
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="http://picturebag.qiniudn.com/blog.css">
<link rel="stylesheet" href="{% static "vim.css" %}">
{% block head %}{% endblock %}
<style>
img{
margin-top: -20px;
max-height: 60px;
max-width: 150px;
}
.panel-body{
width: 750px;
margin-left: auto;
margin-right: auto;
}
</style>
</head>
<body>
<nav class="navbar navbar-default">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<a class="navbar-brand" href="{% url 'index' %}">
<img src="{% static 'logo.png' %}" alt="logo">
</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li class="active"><a href="{% url 'index' %}">首页<span class="sr-only">(current)</span></a></li>
<li><a href="{% url 'archives' %}">归档</a></li>
</ul>
<form class="navbar-form navbar-right" action="/search/" method="get">
<div class="form-group">
<input type="text" class="form-control" placeholder="Search" name="s">
</div>
<button type="submit" class="btn btn-default">搜索</button>
</form>
<ul class="nav navbar-nav navbar-right">
{% block nav %}
{% if sessionid %}
<li><a href="/admin">进入后台</a></li>
{% else %}
<li><a href="/admin">登陆</a></li>
{% endif %}
{% endblock %}
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
{% block content %}
{% endblock %}
<footer class="footer hidden-xs">
<div class="container">
Copyright © 2013 ChaBug. All Rights Reserved.
</div>
</footer>
</body>
</html>
首页完成
{% extends 'base.html' %}
{% block content %}
<div class="container">
{% for post in post_list %}
<div class="panel-body">
<div class="entry-header page-header">
<div class="entry-title h4">
<a href="{% url 'detail' id=post.id %}">{{ post.title }}</a>
</div>
<div class="entry-meta">
<p>Time:<time>{{ post.datetime|date:"Y-m-d" }}</time>
分类:<a href="{% url 'tag' tag=post.category %}">{{ post.category }}</a>
</p>
</div>
<div class="entry-content" itemprop="description">
{% load markdown_deux_tags %}
{{ post.content|truncatechars_html:50 }}
<a href="{% url 'detail' id=post.id %}">Read More</a>
</div>
</div>
</div>
{% endfor %}
</div>
{% endblock %}
归档页面
{% extends "base.html" %}
{% block content %}
<div class="container">
{% if error %}
<h1>没找到相关文章</h1>
{% else %}
<section class="posts-collapse" id="post">
<span class="archive-move-on"></span>
<span class="archive-page-counter">
OK! 共找到 {{ post_list.count }} 篇日志。 继续努力。
</span>
</section>
{% endif %}
{% for post in post_list %}
<article class="post post-type-normal">
<header class="post-header">
<div class="entry-title h4">
<a href="{% url 'detail' id=post.id %}"> <span itemprop="name">{{ post.title }}</span></a>
</div>
<div class="post-meta">
<time class="post-time">{{ post.datetime|date:"Y-m-d" }}</time>
</div>
</header>
</article>
{% endfor %}
</div>
{% endblock %}
我把归档和同分类文章用了同一个模板,通过if判断来展示不同的页面。
标签页面
{% extends 'base.html' %}
{% block content %}
<div class="container">
分类:<b>{{ post_list.first.category }}</b>下有{{ post_list.count }}篇日志。 继续努力。
{% for post in post_list %}
<div class="panel-body">
<div class="entry-header page-header">
<div class="entry-title h4">
<a href="{% url 'detail' id=post.id %}">{{ post.title }}</a>
</div>
<div class="entry-meta">
<p>Time:<time>{{ post.datetime|date:"Y-m-d" }}</time>
分类:<a href="{% url 'tag' tag=post.category %}">{{ post.category }}</a>
</p>
</div>
<div class="entry-content" itemprop="description">
{% load markdown_deux_tags %}
{{ post.content|truncatechars_html:50 }}
<a href="{% url 'detail' id=post.id %}">Read More</a>
</div>
</div>
</div>
{% endfor %}
</div>
{% endblock %}
文章页面
{% extends 'base.html' %}
{% block content %}
<div class="container">
<div class="panel-body">
<div class="entry-header page-header">
<h1 class="entry-title">{{ post.title }}</h1>
</div>
<div class="entry-meta">
<p>Time:<time>{{ post.datetime|date:"Y-m-d" }}</time>
分类:<a href="{% url 'tag' tag=post.category %}">{{ post.category|title }}</a>
</p>
</div>
<div class="entry-content">
{% load markdown_deux_tags %}
{{ post.content|markdown }}
</div>
</div>
</div>
{% endblock %}
markdown语法
安装markdown插件,
pip3 install django-markdown-deux
然后需要在settings.py中设置
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'article', 'markdown_deux' ]
在模板中像我那样调用
<div class="entry-content">
{% load markdown_deux_tags %}
{{ post.content|markdown }}
</div>
后记
我们的django开发个人博客总算是结束了,前端模板写的不好,你们可以自己写一波好看的。
原创文章,作者:Y4er,未经授权禁止转载!如若转载,请联系作者:Y4er

![[Y4er]6月份作业之Django开发个人博客](https://ae01.alicdn.com/kf/Uf8bc8505674e4a058d3c52481e6fc567E.png)
微信扫一扫
支付宝扫一扫 