Django学习笔记
2015-05-03 19:21
483 查看
一、概述
Django是一个开放源代码的Web应用框架,由Python写成。采用了MVC的软件设计模式,即模型M,视图V和控制器C。Django遵循BSD版权。
二、安装
参见:https://docs.djangoproject.com/en/1.8/intro/install/需要3步:
1)首先安装python
2)安装pip
3)安装Django的生产版
验证是否安装成功:
python -c "import django; print(django.get_version())"
注1:用easy_install也可以安装。
注2:当环境里有多个版本的python时,需要将Django安装到哪个python中,就要用哪个python下的easy_install、pip进行安装django。安装pip时,通过执行安装脚本的python的版本来决定将pip安装到哪个python中。
三、从零开始
1)创建一个项目:
django-admin startproject mysite
目录结构如下:
mysite/ manage.py mysite/ __init__.py settings.py urls.py wsgi.py
目录结构说明:
外层的mysite/根目录仅仅是项目所在的位置,它的命名和Django本身无关;你可以把它改名为任何你喜欢的名字。
manage.py:一个命令行工具,可以使你用多种方式对Django项目进行管理。你可以在django-admin.py and manage.py读到所有关于manage.py的使用细节。
内层的mysite/目录实际上是你的项目里的一个Python包。这个目录的名字就是Python包的名字。你将使用这个名字从这个Python包中导入模块或者类等等(例如mysite.urls)。
mysite/__init__.py:这是一个空文件。它告诉Python,这个目录应该被看做一个Python包。(如果你是一个Python初学者,阅读官方文档中关于包的更多知识。)
mysite/settings.py:Django项目的配置文件。Django配置将告诉你这些配置项的作用。
mysite/urls.py:这个Django项目的URL声明;你的Django站点的“目录”。你可以在URL调度中读到更多关于URLs的资料。
mysite/wsgi.py:一个WSGI兼容的Web服务器的一个入口。用来连接你的项目和相关Web服务器。查看怎样部署WSGI获得更多细节。
修改settings.py
LANGUAGE_CODE = 'zh-CN' TIME_ZONE = 'Etc/GMT-8'
2)为INSTALLED_APPS(settings.py的配置项)创建必要的数据库文件:
python manage.py migrate
此命令参照 INSTALLED_APPS 设置,并在你的 settings.py 文件所配置的数据库中创建必要的数据库表。
每创建一个数据库表你都会看到一条消息。
3)启动web server
python manage.py runserver 0.0.0.0:41188 # 使用如下方法让web server在终端断开后也可以稳定提供服务 nohup python manage.py runserver 0.0.0.0:41188 & # 停止的方法?先找到PID,然后kill ps aux | grep python kill -9 xxx
该方法通过参数指定了web server的ip和端口,如上的设置会监听所有公共 IP 地址,从而可以在其他电脑上访问到该web server。此时,已经访问如上地址和端口,可以看到默认页面:”It worked!“
只是修改了python文件内容,则web server会自动加载对应的python代码;但如果新增加了文件等,就需要重启该web server来生效了。
4)创建应用
在manage.py的同级目录下执行以下命令来创建一个应用polls:python manage.py startapp polls
目录结构如下:
polls/ __init__.py admin.py migrations/ __init__.py models.py tests.py views.py
5)创建models
models即代表了DB的表结构,它们使用python类进行描述。编辑polls/models.py文件,添加以下内容:
from django.db import models #from django.utils import timezone class Question(models.Model): question_text = models.CharField(max_length=200) pub_date = models.DateTimeField('date published') ### print model's info when using Django API #def __str__(self): # __unicode__ on Python 2 # return self.question_text ### a query, using Django API #def was_published_recently(self): return self.pub_date >= timezone.now() - datetime.timedelta(days=1) class Choice(models.Model): question = models.ForeignKey(Question) choice_text = models.CharField(max_length=200) votes = models.IntegerField(default=0) ### print model's info when using Django API #def __str__(self): # __unicode__ on Python 2 # return self.choice_text
每个模型都由继承自 django.db.models.Model 子类的类来描述。 每个模型都有一些类变量,每一个类变量都代表了一个数据库字段。
每个字段由一个 Field 的实例来表现 – 比如 CharField 表示字符类型的字段和 DateTimeField 表示日期时间型的字段。这会告诉 Django 每个字段都保存了什么类型的数据。一些 Field 实例是需要参数的。 例如 CharField 需要你指定 :attr:`~django.db.models.CharField.max_length`。这不仅适用于数据库结构,以后我们还会看到也用于数据验证中。一个 Field 实例可以有不同的可选参数; 在本例中,我们将 votes 的
default 的值设为 0 。
每一个 Field 实例的名字就是字段的名字或者<字段名_类型>(如: question_text 或者 pub_date ),而表名则是<应用名_表名>。你可以在初始化 Field 实例时使用第一个位置的可选参数来指定人类可读的名字。在本例中,我们仅定义了一个符合人类习惯的字段名 Poll.pub_date 。
上面的语句创建的表应该是这个样子:(在后面激活models时可以看到)
BEGIN; CREATE TABLE "polls_choice" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "choice_text" varchar(200) NOT NULL, "votes" integer NOT NULL); CREATE TABLE "polls_question" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "question_text" varchar(200) NOT NULL, "pub_date" datetime NOT NULL); CREATE TABLE "polls_choice__new" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "choice_text" varchar(200) NOT NULL, "votes" integer NOT NULL, "question_id" integer NOT NULL REFERENCES "polls_question" ("id")); INSERT INTO "polls_choice__new" ("choice_text", "votes", "id", "question_id") SELECT "choice_text", "votes", "id", NULL FROM "polls_choice"; DROP TABLE "polls_choice"; ALTER TABLE "polls_choice__new" RENAME TO "polls_choice"; CREATE INDEX "polls_choice_7aa0f6ee" ON "polls_choice" ("question_id"); COMMIT;
6)激活models
首先,将polls应用添加到我们的工程之中。编辑mysite/settings.py文件,添加polls到INSTALLED_APPS配置项中,例如下面:INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'polls', )
然后,执行命令,创建DB的数据表
# 创建migrations,保存路径类似:polls/migrations/0001_initial.py。0001_initial.py是由下面的命令执行结果中查看到的 python manage.py makemigrations polls # 根据migrations,生成SQL语句,对照SQL语句确认无误。也可以运行python manage.py check来进行检查 python manage.py sqlmigrate polls 0001 # 执行变更,创建DB的数据表 python manage.py migrate
Migrations机制使得我们开发过程中,变更models时,无需删除DB再重新建立,该机制会更新你的DB完成models变更的同步,并且不会丢失数据。
综上,变更models的三部曲为:
1. 修改models.py文件
2. 执行python manage.py makemigrations,生成变更的migrations
3. 执行python manage.py migrate,将migrations应用到DB的变更
之所以单独分离出第二步来生成变更的migrations,是为了将这些migrations纳入版本控制系统,从而方便以后的开发和维护。
7)使用Django的API
我们需要进入 Python 的交互式 shell 中来操作 Django 提供给你的 API。不同于简单的输入 “python” 进入的 shell 环境,通过manage.py的方式,因为 manage.py 设置了 DJANGO_SETTINGS_MODULE 环境变量,该变量给定了 Django 需要导入的 settings.py 文件所在路径。
python manage.py shell
操作DB的一些语句
# 导入刚刚的models >>> from polls.models import Question, Choice # 打印Question里的所有数据 >>> Question.objects.all() [] # 新建一条Question数据,并保存 >>> from django.utils import timezone >>> q = Question(question_text="What's new?", pub_date=timezone.now()) >>> q.save() # 打印刚刚新建的数据的相关属性 >>> q.id 1 >>> q.question_text "What's new?" >>> q.pub_date datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<UTC>) # 修改刚刚新建的数据 >>> q.question_text = "What's up?" >>> q.save() # 打印Question里的所有数据,此处直接打印出object是因为没有为models类定义__str__方法 >>> Question.objects.all() [<Question: Question object>] # 添加__str__()方法后 >>> Question.objects.all() [<Question: What's up?>] # 使用filter函数进行查询 >>> Question.objects.filter(id=1) [<Question: What's up?>] >>> Question.objects.filter(question_text__startswith='What') [<Question: What's up?>] # 使用get函数进行简单查询并返回一条结果供直接使用,如果没有结果则会报一个异常 >>> current_year = timezone.now().year >>> Question.objects.get(pub_date__year=current_year) <Question: What's up?> >>> Question.objects.get(id=2) Traceback (most recent call last): ... DoesNotExist: Question matching query does not exist. # 使用pk作为主键的简写,这里的主键是id >>> Question.objects.get(pk=1) <Question: What's up?> # 调用model类的函数 >>> q = Question.objects.get(pk=1) >>> q.was_published_recently() True # 通过Question获取choice_set并新建choice,以自动和当前Question做关联 >>> q = Question.objects.get(pk=1) >>> q.choice_set.all() [] >>> q.choice_set.create(choice_text='Not much', votes=0) <Choice: Not much> >>> q.choice_set.create(choice_text='The sky', votes=0) <Choice: The sky> >>> c = q.choice_set.create(choice_text='Just hacking again', votes=0) >>> c.question <Question: What's up?> >>> q.choice_set.all() [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>] >>> q.choice_set.count() 3 # 查看Choice >>> Choice.objects.filter(question__pub_date__year=current_year) [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>] # 删除一条数据 >>> c = q.choice_set.filter(choice_text__startswith='Just hacking') >>> c.delete()
8)创建管理员账户
运行如下命令来创建管理员账户:python manage.py createsuperuser
管理员页面是默认开启的,只需要访问/admin目录就可以看到登录界面。
9)把polls应用添加到管理页面
打开polls/admin.py文件,添加类似以下的内容:from django.contrib import admin from .models import Choice, Question admin.site.register(Question) admin.site.register(Choice) ### 指定更多的表现形式 #class QuestionAdmin(admin.ModelAdmin): fields = ['pub_date', 'question_text'] #admin.site.register(Question, QuestionAdmin)
此时再进入管理页面就可以看到polls应用的models了,并可以进行直观操作对应的数据。
10)创建View
在 Django 应用程序中,View(视图)是一“类”具有特定功能和模板的网页。每个View就是一个简单的 Python 函数(或方法, 对于基于类的Views情况下)。Django 会通过检查所请求的 URL (确切地说是域名之后的那部分 URL)来匹配一个View。Django 是通过 ‘URLconfs’ 从 URL 获取到视图的。而 URLconf 是将 URL 模式 ( 由正则表达式来描述的 ) 映射到视图的一种配置。
首先,编辑polls/views.py,添加以下内容:
from django.http import HttpResponse def index(request): return HttpResponse("Hello, world. You're at the polls index.")
然后,在polls目录下创建一个urls.py文件来保存URLconf,内容为polls使用到的url到view的映射:
from django.conf.urls import url from . import views urlpatterns = [ url(r'^$', views.index, name='index'), ]
最后,在根URLconf的配置里加入polls的URLconf。编辑mysite/urls.py文件,添加之后的内容类似:
from django.conf.urls import include, url from django.contrib import admin # 通过namespace避免了多个应用时,通过name来引用url时多个应用之间的混淆 urlpatterns = [ url(r'^admin/', include(admin.site.urls)), url(r'^polls/', include('polls.urls')), #url(r'^polls/', include('polls.urls', namespace="polls")), ]
此时,再访问/polls路径就可以看到刚才在views.py里添加的内容提示了。
11)URLconf的url()函数详解
url() 函数有四个参数,两个必须的: regex 和 ``view``, 两个可选的: ``kwargs``, 以及 ``name``。a. regex 是 regular expression 的简写, 在 Django 中就是是 url path(不含 GET 和 POST 参数,以及域名的部分)的匹配模式。 Django 将请求的 URL Path从上至下依次匹配列表中的正则表达式,直到匹配到一个为止。注:这些正则表达式在 URLconf 模块第一次加载时会被编译,即生成urls.pyc文件,因此它们速度超快。
b. View指定了被调用的视图(python函数或者类方法),当 Django 匹配了一个正则表达式就会调用指定的视图功能,包含一个 HttpRequest 实例作为第一个参数,正则表达式 “捕获” 的一些值的作为其他参数。
c. kwargs是一个保存关键字参数的词典,该词典参数会被传入到视图中。不推荐使用该方法。
d. 通过name参数来命名你的 URL ,让你在 Django 的其他地方明确地引用它,特别是在模板中。 这一强大的功能可允许你通过一个文件就可全局修改项目中的 URL 模式。
12)更多视图的实例
1. 通过URL捕获参数修改polls/views.py,增添以下内容:
def detail(request, question_id): return HttpResponse("You're looking at question %s." % question_id) def results(request, question_id): response = "You're looking at the results of question %s." return HttpResponse(response % question_id) def vote(request, question_id): return HttpResponse("You're voting on question %s." % question_id)
修改polls/urls.py,增添以下内容:
from django.conf.urls import url from . import views urlpatterns = [ # ex: /polls/ url(r'^$', views.index, name='index'), # ex: /polls/5/ url(r'^(?P<question_id>[0-9]+)/$', views.detail, name='detail'), # ex: /polls/5/results/ url(r'^(?P<question_id>[0-9]+)/results/$', views.results, name='results'), # ex: /polls/5/vote/ url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'), ]
此时,再访问上面示例的链接,会将5作为参数question_id传递给view。
13)创建模板和使用模板的视图
创建polls/templates目录,根据Django的默认配置,它会去每个应用的目录寻找子目录templates来引入模板。创建模板文件:polls/templates/polls/index.html,而引用该文件时则可以使用路径:polls/index.html。
为什么要在templates下创建polls子目录?因为如果直接在templates下建立模板文件index.html,则在有多个应用并均有该文件时,引用该模板文件就会出现混淆。
index.html的内容如下:
{% if latest_question_list %} <ul> {% for question in latest_question_list %} <!-- <li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li> --> <!-- 以下方式避免了硬编码url --> <li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li> <!-- 以下方式为使用namespace方式 --> <li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li> {% endfor %} </ul> {% else %} <p>No polls are available.</p> {% endif %}
同理,建立polls/templates/polls/detail.html文件:
{{ question }}
然后更新polls/veiws.py文件,以让index视图引用该模板:
from django.http import HttpResponse from django.template import RequestContext, loader from django.http import Http404 from django.shortcuts import render from .models import Question def index(request): latest_question_list = Question.objects.order_by('-pub_date')[:5] template = loader.get_template('polls/index.html') context = RequestContext(request, { 'latest_question_list': latest_question_list, }) return HttpResponse(template.render(context)) ### render is shortcut for template.render #def index(request): # latest_question_list = Question.objects.order_by('-pub_date')[:5] # context = {'latest_question_list': latest_question_list} # return render(request, 'polls/index.html', context) def detail(request, question_id): try: question = Question.objects.get(pk=question_id) except Question.DoesNotExist: raise Http404("Question does not exist") return render(request, 'polls/detail.html', {'question': question}) ### get_object_or_404 is shortcut for try-except 404 #def detail(request, question_id): # question = get_object_or_404(Question, pk=question_id) # return render(request, 'polls/detail.html', {'question': question})
14)处理form请求
修改polls/templates/polls/detail.html文件增加简单的form:<h1>{{ question.question_text }}</h1> {% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %} <form action="{% url 'polls:vote' question.id %}" method="post"> {% csrf_token %} {% for choice in question.choice_set.all %} <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" /> <label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br /> {% endfor %} <input type="submit" value="Vote" /> </form>
该form的action表示其会提交给vote视图进行处理,所以我们修改polls/views.py文件,实现vote视图如下:
from django.shortcuts import get_object_or_404 from django.core.urlresolvers import reverse from django.http import HttpResponseRedirect from .models import Choice, Question # ... ... def vote(request, question_id): p = get_object_or_404(Question, pk=question_id) try: selected_choice = p.choice_set.get(pk=request.POST['choice']) except (KeyError, Choice.DoesNotExist): # Redisplay the question voting form. return render(request, 'polls/detail.html', { 'question': p, 'error_message': "You didn't select a choice.", }) else: selected_choice.votes += 1 selected_choice.save() # Always return an HttpResponseRedirect after successfully dealing # with POST data. This prevents data from being posted twice if a # user hits the Back button. return HttpResponseRedirect(reverse('polls:results', args=(p.id,)))说明:
1. request.POST 是一个类似字典的对象,可以让你 通过关键字名称来获取提交的数据。request.POST 的值永远是字符串形式的。
2. Django 也同样的提供了通过 request.GET 获取 GET 数据的方法
3. 如果 choice 未在 POST 数据中提供,则 request.POST['choice'] 将抛出 KeyError
4. 当成功的处理了 POST 数据后你应该总是返回一个 HttpResponseRedirect 对象,原因如上面的注释所解释。
5. reverse() 函数将URLConf的name转换为实际的URL。 此函数有助于避免在视图中硬编码 URL 的功能。
15)使用样式
在polls目录下新建static子目录,和寻找模板目录机制一样,Django的默认配置会去每个应用下搜索static目录作为静态文件的目录,可以存放js、css和图片等。同样,在static中再新建polls子目录,在polls子目录下新建一个mystyle.css文件,其路径为:polls/static/polls/mystyle.css,而引用时可以使用路径:/static/polls/mystyle.css。
该css文件内容为:
li a { color: green; }
在模板文件polls/index.html的头部增加以下代码:
<link rel="stylesheet" type="text/css" href="/static/polls/mystyle.css" />
刷新页面/polls/页面,可以看到mystyle.css的样式生效了。
四、更多帮助
1. API参考
API Reference2. Topic指南
Topic Guides3. 问题指南
How-to Guides4. FAQ
FAQ相关文章推荐
- 菜鸡的Django学习笔记(二)如何创建第一个博客页面
- Django框架学习笔记(28.文件上传详解)
- Python框架之Django学习笔记(五)
- Django 学习笔记2 模板
- Django学习笔记(四)
- python学习笔记1 (python+django)
- Django学习笔记(1) -- Settings全局变量使用
- django学习笔记1--django的安装与工程创建
- Pyhton_Django学习笔记(二) Django站点管理
- django学习笔记(一):Python2.7 、Django1.2下载及安装
- Django 学习笔记(1)
- python 学习笔记二十 django项目bbs论坛
- Django的select_related查询学习笔记
- Django框架学习笔记(8.对应路由名称和路由分发)
- Pyhton_Django学习笔记(三) 视图和URL配置
- Django Web开发学习笔记(1)
- python+django+mysql学习笔记 (一) – 安装篇
- The Definitive Guide To Django 2 学习笔记(五) 第四章 模板 (一)基本模板系统
- Django REST Framework 学习笔记
- Django 学习笔记-STATIC