Python版本3.5.2,Django版本1.10
创建一个Django工程,并且生成一个名字为mainsite的app
django-admin.py startproject myblog
python3 manage.py startapp mainsite
文件结构如下:
x-power@xpower-CW65S:~/chen/myblog$ tree ./ ./ ├── mainsite │ ├── admin.py │ ├── __init__.py │ ├── migrations │ │ └── __init__.py │ ├── models.py │ ├── tests.py │ └── views.py ├── manage.py └── myblog ├── __init__.py ├── __pycache__ │ ├── __init__.cpython-35.pyc │ └── settings.cpython-35.pyc ├── settings.py ├── urls.py └── wsgi.py 4 directories, 13 files
介绍一下比较重要的几个文件的用途:
manage.py : Django用于管理网站配置的文件,是一个接受命令行指令的工具集程序。
setting.py : 就像他的名字一样是用于对网站的配置进行设置的。(有些地方可能我的理解也不正确欢迎指正,批评!)
urls.py : 用来设置每一个URL 的网址要对应的函数以及对应的方式,通常是创建一个新的网页的时候首要编辑的文件。
wsgi.py : 是用于部署网站时候用的和主机中网页服务器的沟通接口(如Apache)。
真正的网站运行逻辑都在我们创建的App里面(这里是mainsite),这个App也体现了Django的Reuse的概念。
我们已经创建了App但是Dajngo还是不知道有这个App的,我们在setting.py中加入这个App。
INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'mainsite', )
然后修改最后的时区设置,默认时区是Django的诞生地,我们先让他倒时差,学习中文。
LANGUAGE_CODE = 'zh-CN' TIME_ZONE = 'Asia/Shanghai'
Django自带了一个数据库Sql.lite。是一个超小型数据库,一般情况下都会用其他数据库的。现在我们先用这个数据库。
执行以下文件会看到生成了一个db.sqllite3的文件。
1 x-power@xpower-CW65S:~/chen/myblog$ python3 manage.py migrate 2 Operations to perform: 3 Synchronize unmigrated apps: messages, staticfiles 4 Apply all migrations: admin, auth, sessions, contenttypes 5 Synchronizing apps without migrations: 6 Creating tables... 7 Running deferred SQL... 8 Installing custom SQL... 9 Running migrations: 10 Rendering model states... DONE 11 Applying contenttypes.0001_initial... OK 12 Applying auth.0001_initial... OK 13 Applying admin.0001_initial... OK 14 Applying contenttypes.0002_remove_content_type_name... OK 15 Applying auth.0002_alter_permission_name_max_length... OK 16 Applying auth.0003_alter_user_email_max_length... OK 17 Applying auth.0004_alter_user_username_opts... OK 18 Applying auth.0005_alter_user_last_login_null... OK 19 Applying auth.0006_require_contenttypes_0002... OK 20 Applying sessions.0001_initial... OK
在默认的情况下Django的数据库是通过Model的方式去操作的(这也是我爱Django的一点。),也就是在程序中不会直接面对数据库和数据表,而是先创建好Model,然后通过对Model的操作达到操作数据库的目的。这样做日后可以很方便的更换数据库。(总感觉哪里有点不对,日后就换?)
使用数据库大概分为以下几步:
- 在models.py中定义需要使用的类(继承自models.Model)
- 详细的设置每一个类中的变量,即数据表的每一个字段
- 使用python3 manage.py makemigrations创建数据库和Django的中介文件。
- 使用python3 manage.py migrate 同步更新数据库的内容。
- 操作python定义的类就相当于操作数据库了。
如同my_blog这个名字的意思一样,在这里我们需要有一个储存博文的数据表。
最初的时候models.py文件的内容就是这些。
from django.db import models # Create your models here.
修改之后内容如下:
from django.db import models from django.utils import timezone # Create your models here. class Post(models.Model): title = models.CharField(max_length = 200,verbose_name = '标题') slug = models.CharField(max_length = 200,verbose_name = '作者') body = models.TextField(verbose_name = '内容') pub_date = models.DateTimeField(default = timezone.now,verbose_name = '发表时间') class Meta: verbose_name="文章内容" # 后台表的名称 verbose_name_plural = "文章内容" ordering = ['-pub_date'] # 排序 def __str__(self): return self.title # 在 Admin界面显示的内容
verbose_name 自己试一下应该可以知道是将原来的名字给换了一下,换成中文。
在设计好表之后,执行makemigrations和migrate操作,然后创建一个超级用户,
python3 manage.py createsuperuser
登陆进去添加五篇文章。
数据库有了文章以后,我们就要读取这些资料然后在首页将其显示出来,在这里简单的介绍一下MTV和MVC结构。 models.py主要负责定义要存取的数据模型,以Python的class 类定义,在后端Django会自动把这个类中的设置对应到数据库系统当中去,不管是使用的是何种数据库。如何将这些数据取出来或者时存进去的逻辑则是在View中,下面我们编写mainsite/views.py文件。
from django.shortcuts import render from django.http import HttpResponse from .models import Post # Create your views here. def homepage(request): posts = Post.objects.all() post_list = list() for count,post in enumerate(posts): post_list.append('No.{}:'.format(str(count)) + str(post) + "<br>") return HttpResponse(post_list)
如果项目比较大的话,为了方便组织url我们需要在mainsite文件夹下新建一个urls.py文件。然后添加内容如下:
from django.conf.urls import url from . import views urlpatterns = [ url(r'^$',views.homepage,name = 'homepage'), ]
它使用正则表达式的匹配方式(不懂的话学习一下正则表达式,非常常用),后面跟着使用那个view的路径,最后面的name = ××× 是用于在html文件中跳转页面之用。
然后在myblog下的urls.py中include这个文件。修改myblog/urls.py如下:
from django.conf.urls import include, url from django.contrib import admin urlpatterns = [ url(r'^admin/', include(admin.site.urls)), url(r'',include('miansite.urls',namespace = "mainsite")), ]
然后进入主页面(http://127.0.0.1:8000/)可以看到如下:
为什么只有题目呢? 我们可以查看models.py 其中最后一行 self.title。
我们可以修改views.py文件从而让页面变得更加的美观。
from django.shortcuts import render from django.http import HttpResponse from .models import Post # Create your views here. def homepage(request): posts = Post.objects.all() post_list = list() for count,post in enumerate(posts): post_list.append('No.{}:'.format(str(count)) + str(post) + "<hr>") post_list.append("<small>" + str(post.body) + "</small><br><br>") return HttpResponse(post_list)
差不多一个简单的网页已经出来了,下面说一下工作逻辑,用户提交请求,页面服务器(如Apache),区分是静态文件还是其他,静态文件直接返回内容,其他的话找到setting文件,发现ROOT_URLCONF,然后从中找到相应的url对应的视图,然后视图进行逻辑处理,需要和数据库进行交互的话进行交互,然后将内容放到相应的模板当中。返回给用户。(可能说的有问题,欢迎指正!)
在前面我们的html编码都在views.py文件当中,实际开发的时候是不需要这样做的,将html和后台分开这样才能最大效率,最易维护。如果将其分开的话主要工作为下面几步:
- 在setting.py中设置template文件夹的位置。
- 在urls.py中创建网址和views.py的对应关系。
- 创建html文件,做好排版并安排数据要在页面显示的位置。
- 在views.py中取得数据,以render函数把数据送到指定的模板文件当中。
修改setting文件中的某些内容如下。
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR,'templates')], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ]
templates是在项目的根目录下(BASE_DIR),然后在templates下创建一个index.html文件,内容如下:
<!DOCTYPE html> <html> <head> <meta charset = 'utf-8'> <title>欢迎光临我的博客</title> </head> <body> <h1>欢迎光临我的博客</h1> <hr>{{posts}}<hr> <h3>现在时刻:{{now}}</h3> </body> </html>
相应的views.py的编码如下:
from django.shortcuts import render from django.http import HttpResponse from .models import Post from datetime import datetime # Create your views here. def homepage(request): posts = Post.objects.all() now = datetime.now() post_list = list() return render(request,'index.html',{'posts':posts,'now':now})
效果如下,当然这样瞎扯淡是不行的。
我们修改index.html文件如下:
<!DOCTYPE html> <html> <head> <meta charset = 'utf-8'> <title>欢迎光临我的博客</title> </head> <body> <h1>欢迎光临我的博客</h1> <hr> {% for post in posts %} <p style = 'font-family:微软雅黑;font-size:16pt;font-weigth:bold;'> {{post.title}} </p> <p style = 'font-family:微软雅黑;font-size:10pt;letter-spacing:1pt;'> {{post.body}} </p> {% endfor %} <hr> <h3>现在时刻:{{now}}</h3> </body> </html>
效果如下:
很显然,没有人会直接将全部内容放到首页,将index.html改为如下:
<!DOCTYPE html> <html> <head> <meta charset = 'utf-8'> <title>欢迎光临我的博客</title> </head> <body> <h1>欢迎光临我的博客</h1> <hr> {% for post in posts %} <p style = 'font-family:微软雅黑;font-size:16pt;font-weigth:bold;'> <a href = "{url 'mainsite:post' post.id}">{{post.title}}</a> </p> {% endfor %} <hr> <h3>现在时刻:{{now}}</h3> </body> </html>
上面的链接一行待会解释。
效果如下:
然后开始添加点击链接之后的逻辑处理:
def post(request,post_id): try: post_id = int(post_id) post = Post.objects.get(id = post_id) return render(request,'post.html',{'post':post}) except: return redirect('/')
怎样才知道是用这个view呢?下面开始修改 url.在mainsite下的urls.py文件中添加内容如下:
url(r'post/(?P<post_id>d+)/$',views.post,name = 'post'),#这里的name 就是用于在html 文件中进行跳转的标记。
然后效果如下:
添加post.html如下:
<!DOCTYPE html> <html> <head> <meta charset = 'utf-8'> <title>欢迎光临我的博客</title> </head> <body> <h1>{{post.title}}</h1> <hr> <p style = 'font-family:微软雅黑;font-size:12pt;letter-spacing:2pt;'> {{ post.body }} </p> <hr> <h3><a href = "{% url 'mainsite:homepage' %}">回首页</a></h3> </body> </html>
可以看到index.html和post.html有许多相同的地方,而且对于一个正式的网站往往需要固定的页首和页尾。
一个正式的网站往往每一页都需要一些固定的元素用以强调网站的风格。以本堂课的网站为例,到目前为止需要的.html文件如下:
.html文件关系说明, base.html include header.html和footer.html index.html 和 post.html extends base.html 。
创建base.html文件写入以下内容:
<!DOCTYPE html> <html> <head> <meta charset = 'utf-8'> <title> {% block title %} {% endblock %} </title> </head> <body> {% include 'header.html' %} {% block headmessage %} {% endblock %} <hr> {% block content %} {% endblock %} <hr> {% include 'footer.html' %} </body> </html>
下面添加或修改.html如下
index.html
{% extends 'base.html' %} <!-- 继承自base.html --> {% block title %}欢迎光临我的博客{% endblock %} {% block headmessage %} <h3 style = 'font-family:楷体;'>本站文章列表</h3> {% endblock %} {% block content %} {% for post in posts %} <p style = 'font-family:微软雅黑;font-size:14pt;font-weigth:bold;'> <a href = "{% url 'mainsite:post' post.id %}">{{post.title}}</a> </p> {% endfor %} {% endblock %}
post.html
{% extends 'base.html' %} {% block title %} {{ post.title }} - 文学天地 {% endblock %} {% block headmessage %} <h3 style = 'font-family:微软雅黑;'>{{ post.title }}</h3> <a style = 'font-family:微软雅黑;' href = "{% url 'mainsite:homepage' %}">回首页</a> {% endblock %} {% block content %} <p style = 'font-family:微软雅黑;font-size:12pt;letter-spacing:2pt;'> {{ post.body }} </p> {% endblock %}
footer.html
{% if now %} <p style = 'font-family:微软雅黑;'>现在时刻:{{ now }}</p> {% else %} <p style = 'font-family:微软雅黑;'>本站内容取自互联网,如有侵权请来信通知下架。</p> {% endif %}
header.html
<h1 style = 'font-family:微软雅黑;'>欢迎观临 文学天地</h1>
设计这些东西的时候,你一定感觉到很烦,为什么不写好一个css文件然后引用呢? 下面我们开始说这一类 ”静态文件的处理方法“。
我们采用bootstrap去写。采用CDN
<!-- Latest compiled and minified CSS --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <!-- Optional theme --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous"> <!-- Latest compiled and minified JavaScript --> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
将base.html修改为下面
<!DOCTYPE html> <html> <!-- Latest compiled and minified CSS --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <!-- Optional theme --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous"> <!-- Latest compiled and minified JavaScript --> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script> <head> <meta charset = 'utf-8'> <title> {% block title %} {% endblock %} </title> </head> <body> <div class = 'container-fluid'> {% include 'header.html' %} <div class = 'panel panel-default'> <div class = 'panel-heading'> {% block headmessage %} {% endblock %} </div> <div class = 'panel-body'> {% block content %} {% endblock %} </div> <div class = 'panel-footer'> {% include 'footer.html' %} </div> </body> </html>
然后此时运行起来效果如下:
漂亮了 好几个档次。
接着我们引入Bootstrap中Grid概念,通过row和col的设置做出来一般博客网站的侧边连同样也是在base.html中修改。只修改body的内容
<div class = 'container-fluid'> {% include 'header.html' %} <div class = 'row'> <div class = 'col-sm-2 col-md-2'> <div class = 'panel panel-default'> <div class = 'panel-heading'> <h3> MENU </h3> </div> <div class = 'panel-body'> <div class = 'list-group'> <a href = "{% url 'mainsite:homepage' %}" class = 'list-group-item'>Home</a> <a href = 'http://tar.so/news' class = 'list-group-item'>时事新闻</a> <a href = 'http://drho.tw/news' class = 'list-group-item'>电视新闻</a> </div> <script type = 'text/javascript' src = 'http://feedjit.com/serve/?vv=1515&tft=3&dd=0&wid=&pid=0&proid=0&bc=FFFFFF&tc=000000&;ww=190&wne=6&srefs=0'> </script> <noscript> <a href='http://feedjit.com/'>Live Traffic Stats<a> </noscript> </div> </div> </div> <div class = 'col-sm-8 col-md-8'> <div class = 'panel panel-default'> <div class = 'panel-heading'> {% block headmessage %} {% endblock %} </div> <div class = 'panel-body'> {% block content %} {% endblock %} </div> <div class = 'panel-footer'> {% include 'footer.html' %} </div> </div> </div> </div> </div>