Django快速入门教程
Django
此文档基于Django3.0
简介
django是一个基于python的开源web框架,旨在简化开发者开发过程,使得开发起来快速简洁。采用了MVT软件设计模式(Model模型、View视图、Template模板)
这里MTV模型
Template呈现给用户,用户通过Template发送请求给View,View获取Model的数据并将数据反馈给Template,Template接着渲染给用户。很像MVC。
下面快速上手一个Django项目
python的安装和django库的安装忽略
创建项目
使用命令,进入想要放置项目的地方,输入以下命令创建名为demo项目
django-admin startproject demo
使用pycharm
这里注意创建项目或后面的应用名称不要使用python、django内建模块、关键字等
目录
创建完毕可以看到项目结构如下
|-- demo
|-- manage.py
|-- demo
|-- __init__.py
|-- settings.py
|-- urls.py
|-- wsgi.py
|-- asgi.py #pycharm创建时无此项
|-- templates #命令创建无此项,可自行创建
- manage.py作用与django-admin作用一样,并且只作用于你的项目,django-admin可以进入命令行状态输入django-admin help查看用法
- settings.py是项目配置文件,包含所有配置项
- urls.py是项目的URL声明处,url和视图在这里进行映射,访问对应url就能得到相应视图,下面URL调度器会详细讲解
- wsgi.py作为你的项目运行在wsgi兼容的服务器上的入口
- templates目录存放模板,在Django中视图的概念是一类具有相同功能和模板的网页集合,如果我们使用python代码编写页面,那么就不能复用并且想要修改内容必须更改代码,所以使用模板将页面从代码中分离。简而言之就是在templates存放各个模板网页,其中数据通过后端代码传递。(MTV中的Templates)
启动项目
命令模式,进入项目目录
python manager.pu runserver
Pycharm可以直接使用UI按钮。
至此,就可以直接运行这个项目,就能在http://127.0.0.1:8000/看到Django提供的默认视图
数据库配置
Django对许多数据库都有很好的支持,如MySQL、postgresql等,其提供了同意接口。这里就先对mysql进行讲解。首先需要安装mysql,其次安装mysql的python驱动
pip install mysqlclient
然后在项目配置中修改Databases配置项
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', # 或者使用 mysql.connector.django
'NAME': 'xxx',
'USER': 'root',
'PASSWORD': 'xxx',
'HOST': 'localhost',
'PORT': '3306',
}
}
许多默认应用都依赖于至少一个数据表,所以在配置完数据库中需要创建一些表。
python manage.py migrate
这个命令会找寻settings中的INSTALLED_APPS列表中的所有应用,并创建必要的数据表信息以及迁移,如下图由于没有创建新的应用,所以只迁移了默认的数据表
可以进入mysql查看迁移结果
配置完数据库,接下来可以使用模型了,模型必须要在应用中使用,不过在使用应用前我们可以先创建一个Django自带管理工具
管理工具
由于Django为了方便开发者进行开发,于是其为我们省略了许多例如对用户增删改查的繁琐工作,其全自动的根据模型创建后台界面,也就是管理界面。管理工具也是项目中的一个应用,他是面向管理者准备的
首先我们需要激活这个应用。去掉urls.py中的注释
from django.contrib import admin
from django.urls import pathurlpatterns = [
path('admin/', admin.site.urls),
]
如上图,由于前面我们知道url是负责映射url和视图的,那么我们运行项目后就可以通过’admin/‘找到控制面板。此时访问http://127.0.0.1:8000/admin会发现需要输入用户名密码,下面创建管理员的用户名密码
创建管理员账号,进入命令界面
python manage.py createsuperuser
接着输入其需要的信息
Username: xxx
Email address: xxx
Password: xxx
然后大功告成,启动项目进入http://127.0.0.1:8000/admin
后面可以在应用中将模型注册到管理工具中,这样我们在管理界面就可以对应用的模型进行增删改了。
创建应用
在一个项目中,可以包含多个应用,比如一个博客系统的项目就能包含博客、论坛等应用,在Django中每个应用都是一个Python包,也就是带有__ init __.py的文件的目录,我们可以在项目中按需创建新的应用
命令模式
django-admin startapp article
或者使用
python manager.py startapp article
Pycharm手动创建麻烦,使用
能看到新的应用目录为
|-- article
|-- migrations/
|-- templates/ #自行新建
|-- __init__.py
|-- admin.py
|-- apps.py
|-- models.py
|-- urls.py #需新建
|-- tests.py
|-- views.py
- migrations目录,放置迁移代码(也就是定义数据表结构的地方),都是自动生成的
- views.py存放MTV中的视图模型,在这里将数据整合到模板
- admin.py是Django管理界面,可以在此将模型注册到管理工具中
- test.py 编写测试用例的地方
创建应用后,需要在项目settings.py文件中安装应用。
INSTALLED_APPS = [
'django.contrib.admin',
...
'article', #这里添加你的应用
]
模型
提了这么多次模型,模型是什么呢,可以理解为类,而每个类对应与数据库中的一张或多张表。所以模型也就是数据库结构设计和附加的其它元数据。
模型是真实数据的简单明确的描述。它包含了储存的数据所必要的字段和行为
创建模型
我们进入到应用的models.py中编写,根据自己需求编写,这里简单就写个文章类包含文章内容、文章题目、发布时间以及作者类包含作者名字。事实上,存储文章内容可以使用其他类型的数据库。
我们使用的模型类都要继承自django.db.models.Model,每个模型类都跟可以有一些变量和方法,变量就代表数据库中的一个字段。而具体字段类型可以去Django官网查看。注意到下面Article类中有ForeignKey字段,很明显是外键的意思。
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=50)
class Article(models.Model):
author = models.ForeignKey(Author, on_delete=models.CASCADE)
article_text = models.CharField(max_length=200)
article_head = models.CharField(max_length=50)
pub_date = models.DateTimeField('date published')
外键
下面是外键定义
def __init__(self, to, on_delete, related_name=None, related_query_name=None,
limit_choices_to=None, parent_link=False, to_field=None,
db_constraint=True, **kwargs):
- to参数指向其关联的类(表)
on_delete是指删除某条数据时关联外键的操作,常用的有以下值
- 级联:models.CASCADE
当关联表中的数据删除时,该外键也删除 - 置空:models.SET_NULL
当关联表中的数据删除时,该外键置空(前提是外键可为空值也就是null = True,否则会报错) 设置默认值:models.SET_DEFAULT
当关联表中的数据删除时,该外键置为默认值(前提是外键有默认值,否则会报错)
设置为其他值:models.SET(xxx)
如果传递了可调用对象,那么结果就是调用结果
- 级联:models.CASCADE
迁移
Django会根据我们定义的模型去创建对应数据表和接口。
接下来就是迁移,首先让Django知道我们的模型有些变更
python manage.py makemigrations article
然后进行迁移
python manage.py migrate
接着会看到DJango在为我们创建数据表,并且如果没有设置表的主键,其自动添加id作为主键
Creating table Article #我们自定义的表
……
此时我们看Article应用中的migrations目录下出来一个0001__initial.py
如下:可以看到Django为我们保存了这次迁移,事实上,以后只要有数据库结构改动(也就是对模型改动),迁移后都会新增文件保存到migrations目录。
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Author',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=50)),
],
),
migrations.CreateModel(
name='Article',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('article_text', models.CharField(max_length=200)),
('article_head', models.CharField(max_length=50)),
('pub_date', models.DateTimeField(verbose_name='date published')),
('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='article.Author')),
],
),
]
由于开发时我们可能需对每次迁移做了什么记录,于是我们也可以指定每次迁移后migrations目录下新增的记录迁移的文件名称。
python manage.py makemigrations article --name testModel
# 出现结果:
Migrations for 'article':
article\migrations\0001_testModel.py
- Create model Author
- Create model Article
使用Django API
我们可以进入交互界面执行API而不是在项目中编写启动调试
python manage.py shell
不直接使用python是因为manage.py包含了环境变量,如果没有环境变量而导入我们的model类会遇到下面的问题。
django.core.exceptions.ImproperlyConfigured: Requested setting INSTALLED_APPS, but settings are not configured. You must either define the environment variable DJA
NGO_SETTINGS_MODULE or call settings.configure() before accessing settings.
进入交互界面后可以尝试接口了,接口完整使用方法在这里。下面介绍几种常用的
# 首先导入模型
In [1]: from article.models import Author,Article
# 定义一个author对象
In [2]: author = Author(name='ace')
# 保存至数据库
In [3]: author.save()
# 导入时间库
In [4]: from django.utils import timezone
# 设置时间
In [5]: time = timezone.now()
# 创建article对象
In [6]: article = Article(author=author,article_text = 'nothins',article_head='first article',pub_date=time)
# 保存article对象
In [7]: article.save()
# 查看所有数据
In [8]: Article.objects.all()
Out[8]: <QuerySet [<Article: Article object (1)>]>
# 删除对象
In [9]: article.delete()
Out[9]: (1, { 'article.Article': 1})
管理页面中加入应用
from django.contrib import admin
from article.models import Article,Author
admin.site.register(Article)
admin.site.register(Author)
不过这时我们进去会发现
ARTICLE列表中的数据是对象形式的,也就是我们需要为这个类添加一个str方法,这样获取输出对象时就会调用str方法:
class Author(models.Model):
def __str__(self):
return self.name
name = models.CharField(max_length=50)
class Article(models.Model):
def __str__(self):
return self.article_head + " by " + self.author.name
author = models.ForeignKey(Author, on_delete=models.CASCADE)
article_text = models.CharField(max_length=200)
article_head = models.CharField(max_length=50)
pub_date = models.DateTimeField('date published')
这样再看管理界面:
管理界面还有许多实用用法,比如自定义表格格式等
URL调度器
在使用视图前需要先明白url调度器的作用,在与项目名同名的应用目录(此处为demo/demo)中的urls.py时负责对url与视图进行映射的。
简言之,DJango获取用户请求后,根据请求的url查询URL调度器中找寻映射关系(也就是匹配urlpatterns),如果匹配到则调用相关视图,否则调用错误处理视图。这个视图是一个Python 函数或基于类的视图或包含的其他URL调度器中的视图 。
在urls.py可以看到如下注释
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
在我们开启管理工具后,可以看到初始URL调度器如下:
from django.contrib import admin
from django.urls import path
urlpatterns = [
path('admin/', admin.site.urls),
]
也就是当用户发送请求为 http://127.0.0.1:8000/admin ,则根据获取的url为’admin’,找寻这里的urlpatterns中的
path('admin/', admin.site.urls)
于是调用django.contrib.admin.sites.py中的urls,也就进入到Django为我们提供的管理页面。
路径匹配
如果使用变量作为url匹配路径则可写为如下:
from django.contrib import admin
from django.urls import path
urlpatterns = [
path('inedx/<int:id>/', views.inedx, name='index'),
path('<int:id>/', views.detail, name='detail'),
]
则在视图中需要改为
def detail(request,id):
...
这样就可以将路径中的id传到视图。而很明显这个id需要时int类型。还有以下类型可以选用
- str :匹配非空字符串,包括路径分割符’/’,方法< str:xxx >,也可省略str:写为< xxx >
- int:匹配0或正整数
- slug:匹配任意由ascii、数字、下划线、连字号的字符串
- uuid:匹配uuid
视图
视图就是将数据整合进入模板然后反馈给用户,首先先讲没有模板直接反馈数据给用户。
可以看应用中的views.py,我们编写一个hello方法,返回HttpResponse类型,这样当url匹配到时就能得到一个包含’Hello world !’的视图。每个视图函数至少要有一个参数,通常被叫作request。 这是一个触发这个视图、包含当前Web请求信息的对象,是类django.http.HttpRequest的一个实例,一个视图功能必须返回一个HttpResponse。 一旦做完,Django将完成剩余的转换Python的对象到一个合适的带有HTTP头和body的Web Response,(例如,网页内容)。
:demo/article/views.py
from django.http import HttpResponse
def hello(request):
return HttpResponse("Hello world ! ")
接下来在应用URL调度器中添加映射关系,如果应用目录中没有urls.py则自行添加
:demo/article/urls.py
from django.urls import path
from . import views
app_name = 'article'
urlpatterns = [
path('hello/', views.hello),
]
应该很好理解,当匹配到’hello‘时调用views中的hello函数。但是注意这里添加了app_name,这个是命名空间,防止不同应用的重名url引起冲突,如果不同应用没有冲突url可以不加。
下面将应用的url调度器包含到与项目同名的应用url调度器中
:demo/demo/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('article/', include('article.urls')),
]
然后重启项目,访问http://127.0.0.1:8000/article/hello/可看到结果
如果需要动态内容,由于上面已经说了视图返回的HttpResponse将传递的信息构为一个有响应头和响应体的响应,于是我们可以在这个函数中添加动态内容
from django.http import HttpResponse
import datetime
def hello(request):
now = datetime.datetime.now()
html = "<html><body>It is now %s.</body></html>" % now
return HttpResponse(html)
可以看到根据时间不同获得的数据不同。
但是这样需要在代码中添加html语言不够松耦合,也就是想要改变界面还是需要更改代码。这就引出了模板,后面会讲解。
Django提供的快捷函数
- render() 渲染
render(request, template_name, context=None, content_type=None, status=None, using=None)
将给定的模板与给定的上下文字典组合在一起,并以渲染的文本返回一个 HttpResponse 对象。
- redirect() 重定向
redirect(to, *args, permanent=False, **kwargs)
返回一个HttpResponseRedirect到URL去传递参数。
参数可为
一个model对象,将调用model的get_absolute_urls将被调用
from django.shortcuts import redirect
def my_view(request):
...
obj = MyModel.objects.get(...)
return redirect(obj)
一个视图名称
def my_view(request):
...
return redirect('some-view-name', foo='bar')
一个URL,重定向
def my_view(request):
...
return redirect('/some/url/')
- get_object_or_404()
get_object_or_404(klass,*args,**kwargs)
根据参数获取模型的对象,就是使用给定模型的get()函数,如果不存在则会引发Http404而不是DoesNotExist异常
- get_list_or_404()
get_list_or_404(klass, *args, **kwargs)
返回给定模型管理器上 filter() 转换为列表的结果,如果结果列表为空,则引发 Http404。
模板
模板具体概念在上面已经讲了,在Django中视图的概念是一类具有相同功能和模板的网页集合,如果我们使用python代码编写页面,那么就不能复用并且想要修改内容必须更改代码,所以使用模板将页面从代码中分离。简而言之就是在templates存放各个模板网页,其中数据通过后端代码传递。(MTV中的Templates)。
所以我们可以在每个应用中新建一个templates目录,也可以直接在项目中新建templates目录。我才用的是项目中新建templates目录也就是’demo/templates/’
如果使用Pycharm建的项目则自动采取项目新建并且无需设置,如果不是Pycharm键的话需要在项目设置文件中修改内容,就是告知Django我们的模板目录在哪里
:demo/settings.py
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',
],
},
},
]
接着我们就可以在这里新建模板,也就是html文件,不过需要使用的语法除了HTML语言还有就是Django模板标签。
Django 模板语言
变量:
变量从上下文中输出一个值,类似字典的对象,键值对存储。变量使用{ {,}}My name is {
{name}}
给出上下文为{‘name’:‘ace’}时,该模板显示为
My name is ace
字典查找,属性查找和列表索引查找均以点表示法实现:
{
{ my_dict.key }}
{
{ my_object.attribute }}
{
{ my_list.0 }}
- 标签
标签在渲染过程中提供了任意逻辑。
这个定义是故意含糊的。例如,标签可以输出内容,用作控制结构,例如“ if”语句或“ for”循环,从数据库中获取内容,甚至可以访问其他模板标签。
标签被{%
与%}
这样的包裹
例如条件控制语句
{% if condition1 %}
... display 1
{% elif condiiton2 %}
... display 2
{% else %}
... display 3
{% endif %}
所有的标签都可以在这里找到
- 过滤器
过滤器转换变量和标记参数的值,相当于将标记参数作为过滤变量的条件
{ {value|first}}
如果value为[‘a’,‘b’,‘c’],则由于将first作为过滤器我们获取的就是value的第一个值也就是’a’
所有过滤器可以在此找到
注释
{# xxxxx #}
整合模型、视图、模板的简单例子
模型如上面的时Article和Author,我们将模板做成一篇博客的样子
url调度器
:demo/article/urls.py
from django.urls import path
from . import views
app_name = 'article'
urlpatterns = [
path('hello/', views.hello),
path('<author>/<title>',views.get_article)
]
视图添加根据作者和名称查找,注意到注释中使用了get_object_or_404函数,跟下面的异常捕获部分作用是一样的
def get_article(request, author, title):
# author_id = get_object_or_404(Author, name=author)
# article = get_object_or_404(Article, article_head=title,author=author_id)
try:
author_id = Author.objects.get(name=author)
article = Article.objects.get(article_head=title, author=author_id)
except Author.DoesNotExist or Article.DoesNotExist:
raise Http404("Article does not exist")
return render(request, 'article.html', {'article': article})
模板(简洁版没有引入css)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>$Title$</title>
</head>
<body>
<h1>{
{ article.article_head }}</h1>
<h2>{
{ article.author.name }} published on {
{ article.pub_date }}</h2>
<p>
{
{ article.article_text }}
</p>
</body>
</html>
接下来就大功告成了。
Django官方文档地址:https://docs.djangoproject.com/
Github地址:https://github.com/django/django
还没有评论,来说两句吧...