开发环境
安装最新版的Django版本
Django实际是一个平台搭建工作,内含一些命令,能够快速的完成平台搭建
- 安装最新版本的Django
$ pip install django
- django-admin.py添加到我们的环境变量
方便之后通过Django的命令直接操作
项目创建
1.项目创建
到项目指定目录下
$django-admin.py startproject my_blog
- 建立Django app
到项目指定目录下
$python manage.py startapp article
- 添加APP
在my_blog/my_blog/settings.py(注意:应该是项目根目录底下的配置文件)
INSTALLED_APPS = (
...
'article', #这里填写的是app的名称
)
- 运行程序
到项目指定目录下
$python manage.py runserver localhost:9000
- 命令总结
python manage.py <command> [options] #Django Command
python manange.py -h帮助文档
django-admin.py startproject my_blog #创建项目
python manage.py startapp article #创建app
python manage.py runserver localhost:9000 #启动Django中的开发服务器
项目设置
数据库设置
- Django Model
- 每一个Django Model都继承自django.db.models.Model
- 在Model当中每一个属性attribute都代表一个database field
- 通过Django Model API可以执行数据库的增删改查, 而不需要写一些数据库的查询语句
- 设置数据库
Django项目建成后, 默认设置了使用SQLite数据库, 在 my_blog/my_blog/settings.py 中可以查看和修改数据库设置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
- 创建models
在my_blog/article/models.py下编写如下程序:
from django.db import models
# Create your models here.
class Article(models.Model) :
title = models.CharField(max_length = 100) #博客题目
category = models.CharField(max_length = 50, blank = True) #博客标签
date_time = models.DateTimeField(auto_now_add = True) #博客日期
content = models.TextField(blank = True, null = True) #博客文章正文
#python2使用__unicode__, python3使用__str__
def __str__(self) :
return self.title
class Meta: #按时间下降排序
ordering = ['-date_time']
- 同步数据库
$ python manage.py migrate #命令行运行该命令
$ python manage.py makemigrations
- Django Shell
$ python manage.py shell
Admin
Django有一个优秀的特性, 内置了Django admin后台管理界面, 方便管理者进行添加和删除网站的内容.
- 设置Admin
可以在my_blog/my_blog/settings.py中查看
同时也已经添加了进入后台管理的url, 可以在my_blog/my_blog/urls.py中查看 - 创建超级用户
$ python manage.py createsuperuser
现在可以在浏览器中输入localhost:9000/admin输入账户和密码进入后台管理
Views和URL
- 网页程序的逻辑
request进来->从服务器获取数据->处理数据->把网页呈现出来
- url设置相当于客户端向服务器发出request请求的入口, 并用来指明要调用的程序逻辑
- views用来处理程序逻辑, 然后呈现到template(一般为GET方法, POST方法略有不同)
- template一般为html+CSS的形式, 主要是呈现给用户的表现形式
- 简单Django Views和URL
Django中views里面的代码就是一个一个函数逻辑, 处理客户端(浏览器)发送的HTTPRequest, 然后返回HTTPResponse,那么开始在my_blog/article/views.py中编写简单的逻辑
#现在你的views.py应该是这样
from django.shortcuts import render
from django.http import HttpResponse
# Create your views here.
def home(request):
return HttpResponse("Hello World, Django")
那么如何使这个逻辑在http请求进入时, 被调用呢, 这里需要在my_blog/my_blog/urls.py中进行url设置
from django.conf.urls import url
from django.contrib import admin
from article import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', views.home),
]
url()函数有四个参数, 两个是必须的:regex和view, 两个可选的:kwargs和name
- regex是regular expression的简写,这是字符串中的模式匹配的一种语法, Django 将请求的URL从上至下依次匹配列表中的正则表达式,直到匹配到一个为止。
- View当 Django匹配了一个正则表达式就会调用指定的view逻辑, 上面代码中会调用article/views.py中的home函数
- kwargs任意关键字参数可传一个字典至目标view
- name命名你的 URL, 使url在 Django 的其他地方使用, 特别是在模板中
Django Views和URL更近一步
现在我们这样做, 在my_blog/article/views.py加入如下代码:
def detail(request, my_args):
return HttpResponse("You're looking at my_args %s." % my_args)
在my_blog/my_blog/urls.py中设置对应的url
from django.conf.urls import url
from django.contrib import admin
from article import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', views.home),
url(r'^(?P<my_args>\d+)/$', views.detail, name='detail'),
]
^(?P<my_args>\d+)/$这个正则表达式的意思是将传入的一位或者多位数字作为参数传递到views中的detail作为参数, 其中?P<my_args>定义名称用于标识匹配的内容
Template使用
my_blog(项目根目录)下添加文件名, 文件夹名为templates
在my_blog/my_blog/settings.py下设置templates的位置
TEMPLATE_PATH = os.path.join(BASE_DIR, 'templates')
TEMPLATES = (
...
DIRS: [TEMPLATE_PATH],
)
- 第一个template
templates/test.html 简单第一个 template html文件
注意:要添加<meta charset="utf-8">,否则会出现编码错误
<!--在test.html文件下添加-->
<!DOCTYPE html>
<meta charset="utf-8">
<html>
<head>
<title>Just test template</title>
<style>
body {
background-color: red;
}
em {
color: LightSeaGreen;
}
</style>
</head>
<body>
<h1>Hello World!</h1>
<strong>{{ current_time }}</strong>
</body>
</html>
{{ current_time }}是Django Template中变量的表示方式
在article/views.py中添加一个函数逻辑
def test(request) :
return render(request, 'test.html', {'current_time': datetime.now()})
然后设置对应的url在my_blog/my_blog/urls.py下
url(r'^test/$', views.test),
render()函数中第一个参数是request 对象, 第二个参数是一个模板名称,第三个是一个字典类型的可选参数. 它将返回一个包含有给定模板根据给定的上下文渲染结果的 HttpResponse对象。
- 正式编写template
在template文件夹下增加base.html
<!doctype html>
<meta charset="utf-8">
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="A layout example that shows off a blog page with a list of posts.">
<title>Andrew Liu Blog</title>
<link rel="stylesheet" href="http://labfile.oss.aliyuncs.com/courses/487/pure-min.css">
<link rel="stylesheet" href="http://labfile.oss.aliyuncs.com/courses/487/grids-responsive-min.css">
<link rel="stylesheet" href="http://labfile.oss.aliyuncs.com/courses/487/blog.css">
</head>
<body>
<div id="layout" class="pure-g">
<div class="sidebar pure-u-1 pure-u-md-1-4">
<div class="header">
<h1 class="brand-title">Andrew Liu Blog</h1>
<h2 class="brand-tagline">Snow Memory</h2>
<nav class="nav">
<ul class="nav-list">
<li class="nav-item">
<a class="pure-button" href="https://github.com/Andrew-liu">Github</a>
</li>
<li class="nav-item">
<a class="pure-button" href="http://weibo.com/dinosaurliu">Weibo</a>
</li>
</ul>
</nav>
</div>
</div>
<div class="content pure-u-1 pure-u-md-3-4">
<div>
{% block content %}
{% endblock %}
<div class="footer">
<div class="pure-menu pure-menu-horizontal pure-menu-open">
<ul>
<li><a href="http://andrewliu.tk/about/">About Me</a></li>
<li><a href="http://twitter.com/yuilibrary/">Twitter</a></li>
<li><a href="http://github.com/yahoo/pure/">GitHub</a></li>
</ul>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
上面这段html编写的页面是一个模板, 其中{% block content %} {% endblock %}字段用来被其他继承这个基类模板进行重写
继续在templates文件夹下添加home.html文件
{% extends "base.html" %}
{% block content %}
<div class="posts">
{% for post in post_list %}
<section class="post">
<header class="post-header">
<h2 class="post-title">{{ post.title }}</h2>
<p class="post-meta">
Time: <a class="post-author" href="#">{{ post.date_time }}</a> <a class="post-category post-category-js" href="#">{{ post.category }}</a>
</p>
</header>
<div class="post-description">
<p>
{{ post.content }}
</p>
</div>
</section>
{% endfor %}
</div><!-- /.blog-post -->
{% endblock %}
其中:
- {% for <element> in <list> %}与{% endfor %}成对存在, 这是template中提供的for循环tag
- {% if <elemtnt> %} {% else %} {% endif %}是template中提供的if语句tag
- template中还提供了一些过滤器
修改my_blog/article/views.py, 并删除test.html
def home(request):
post_list = Article.objects.all() #获取全部的Article对象
return render(request, 'home.html', {'post_list' : post_list})
修改my_blog/my_blog/urls.py
注意:会出现no such table的问题,解决办法:
- 运行’manage.py makemigrations’, 这样可以’make new migrations’
- 然后运行’manage.py migrate’, 接着’apply them’
动态URL
目前只有一个主页的空盒子, 而大部分时候我们希望能够让每篇博客文章都有一个独立的页面,Django给我们提供了一个方便的解决方法, 就是动态URL
- 修改my_blog/article/views.py代码:
# -*- coding: utf-8 -*-
from django.shortcuts import render
from django.http import HttpResponse
from article.models import Article
from datetime import datetime
from django.http import Http404
# Create your views here.
def home(request):
post_list = Article.objects.all() #获取全部的Article对象
return render(request, 'home.html', {'post_list' : post_list})
def detail(request, id):
try:
post = Article.objects.get(id=str(id))
except Article.DoesNotExist:
raise Http404
return render(request, 'post.html', {'post' : post})
id是每个博文的唯一标识, 所以这里使用id对数据库中的博文进行查找
- my_blog/my_blog/urls.py中修改url设置:
from django.conf.urls import url
from django.contrib import admin
from article import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', views.home, name = 'home'),
url(r'^(?P<id>\d+)/$', views.detail, name='detail'),
]
- 在templates下建立一个用于显示单页博文的界面 post.html
#post.html
{% extends "base.html" %}
{% block content %}
<div class="posts">
<section class="post">
<header class="post-header">
<h2 class="post-title">{{ post.title }}</h2>
<p class="post-meta">
Time: <a class="post-author" href="#">{{ post.date_time|date:"Y /m /d"}}</a> <a class="post-category post-category-js" href="#">{{ post.category }}</a>
</p>
</header>
<div class="post-description">
<p>
{{ post.content }}
</p>
</div>
</section>
</div><!-- /.blog-post -->
{% endblock %}
可以发现只需要对home.html进行简单的修改, 去掉循环就可以了.
- 修改home.html和base.html, 加入动态链接和主页, 归档, 专题和About Me按钮
<!--home.html-->
{% extends "base.html" %}
{% block content %}
<div class="posts">
{% for post in post_list %}
<section class="post">
<header class="post-header">
<h2 class="post-title"><a href="{% url "detail" id=post.id %}">{{ post.title }}</a></h2>
<p class="post-meta">
Time: <a class="post-author" href="#">{{ post.date_time |date:"Y /m /d"}}</a> <a class="post-category post-category-js" href="#">{{ post.category }}</a>
</p>
</header>
<div class="post-description">
<p>
{{ post.content }}
</p>
</div>
<a class="pure-button" href="{% url "detail" id=post.id %}">Read More >>> </a>
</section>
{% endfor %}
</div><!-- /.blog-post -->
{% endblock %}
- base.html:
<!--base.html-->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="A layout example that shows off a blog page with a list of posts.">
<title>Andrew Liu Blog</title>
<link rel="stylesheet" href="http://labfile.oss.aliyuncs.com/courses/487/pure-min.css">
<link rel="stylesheet" href="http://labfile.oss.aliyuncs.com/courses/487/grids-responsive-min.css">
<link rel="stylesheet" href="http://labfile.oss.aliyuncs.com/courses/487/blog.css">
</head>
<body>
<div id="layout" class="pure-g">
<div class="sidebar pure-u-1 pure-u-md-1-4">
<div class="header">
<h1 class="brand-title"><a href="{% url "home" %}">Andrew Liu Blog</a></h1>
<h2 class="brand-tagline">Snow Memory</h2>
<nav class="nav">
<ul class="nav-list">
<li class="nav-item">
<a class="button-success pure-button" href="/">Home</a>
</li>
<li class="nav-item">
<a class="button-success pure-button" href="/">Archive</a>
</li>
<li class="nav-item">
<a class="pure-button" href="https://github.com/Andrew-liu/my_blog_tutorial">Github</a>
</li>
<li class="nav-item">
<a class="button-error pure-button" href="http://weibo.com/dinosaurliu">Weibo</a>
</li>
<li class="nav-item">
<a class="button-success pure-button" href="/">Pages</a>
</li>
<li class="nav-item">
<a class="button-success pure-button" href="/">About Me</a>
</li>
</ul>
</nav>
</div>
</div>
<div class="content pure-u-1 pure-u-md-3-4">
<div>
{% block content %}
{% endblock %}
<div class="footer">
<div class="pure-menu pure-menu-horizontal pure-menu-open">
<ul>
<li><a href="http://andrewliu.tk/about/">About Me</a></li>
<li><a href="http://twitter.com/yuilibrary/">Twitter</a></li>
<li><a href="http://github.com/yahoo/pure/">GitHub</a></li>
</ul>
</div>
</div>
</div>
</div>
</div>
</body>
</html>