社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
Python的WEB框架有Django、Tornado、Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM、模型绑定、模板引擎、缓存、Session等诸多功能。
系统 : ubuntu 17.10
python : 3.6
Django2.0
为了考虑依赖性问题,将使用virtualenv来搭建对应的环境
安装:
pip install virtualenv
创建虚拟环境
cd project_name_dir
virtualenv venv #venv为虚拟环境的目录名,可以自定义
创建虚拟环境可以指定Python解释器
virtualenv -p python3
or
virtualenv -p /usr/bin/python3.6 env
要开始使用虚拟环境,需要激活
source env/bin/activate
需要退回系统默认环境或者暂停当前的虚拟环境可以使用以下的命令
deactivate
删除虚拟环境,只需要删除上面新建的目录即可。
默认安装的是最后发布的版本
pip install Django
如果需要
指定安装的版本需要下面的命令,比如指定安装版本为2.0的Django。
pip install Django==2.0
创建项目的命令:
django-admin startproject mysite1
然后会在当前目录中新建一个目录,目录结构为:
mysite1
├── manage.py
└── mysite1
├── __init__.py
├── settings.py
├── urls.py
└── wsgi.py
其中的settings.py
为整个Django项目的配置文件,urls.py
整个项目的路由控制文件,wsgi.py
项目部署使用到的文件。
项目运行流程:
具体步骤:
views.py
的文件,内容为from django.http import HttpResponse
def index(request):
return HttpResponse("Hello world")
urls.py
文件,添加一项路由from django.contrib import admin
from django.urls import path
from . import views
urlpatterns = [
path('admin/', admin.site.urls),
path("", views.index)
]
其中的""
代表根目录,如果需要指定路径为test
,可以把""
修改为test/
3. 回到项目的根目录,运行项目
python3 manage.py runserver
默认是8000端口如果需要指定端口可以使用下面的命令
python3 manage.py runserver 8888
如果需要外网访问当前的项目,可以使用下面的命令
python3 manage.py runserver 0.0.0.0:8888
正常的运行流程:
进来的请求转入’/’.
Django通过在ROOT_URLCONF配置来决定根URLconf.
Django在URLconf中的所有URL模式中,查找第一个匹配’/'的条目。
如果找到匹配,将调用相应的视图函数
视图函数返回一个HttpResponse
Django转换HttpResponse为一个适合的HTTP response, 以Web page显示出来
在urls.py
文件中,发现一条url匹配规则path('admin/', admin.site.urls),
这条路由规则匹配的是admin后台,访问127.0.0.1/admin
出现界面
然后我们需要创建一个管理员账号,步骤如下:
python3 manage.py help
可以查看基本的命令Type 'manage.py help <subcommand>' for help on a specific subcommand.
Available subcommands:
[auth]
changepassword
createsuperuser
[contenttypes]
remove_stale_contenttypes
[django]
check
compilemessages
createcachetable
dbshell
diffsettings
dumpdata
flush
inspectdb
loaddata
makemessages
makemigrations
migrate
sendtestemail
shell
showmigrations
sqlflush
sqlmigrate
sqlsequencereset
squashmigrations
startapp
startproject
test
testserver
[sessions]
clearsessions
[staticfiles]
collectstatic
findstatic
runserver
如果没有迁移数据库直接使用命令python3 manage.py createsuperuser
创建管理员用户会爆出这样的错误
django.db.utils.OperationalError: no such table: auth_user
所以需要先迁移数据库,使用以下的命令迁移数据库,Django默认使用的数据库是sqlite3
,可以在settings
中更换。
python3 manage.py migrate
python3 manage.py createsuperuser
然后输入对应的管理员用户名和邮箱以及密码,ok。因为我设置的密码是123456789,所以出现密码过弱的提示。
settings.py
中的LANGUAGE_CODE = 'en-us'
修改LANGUAGE_CODE = 'zh-hans'
小结:
启动服务使用命令runserver
,迁移(同步)数据库使用命令migrate
,创建管理管理员账号使用命令createsuperuser
,查看帮助使用命令help
。
创建一个新的应用(app) : python3 startapp app_name
首先创建一个Django应用,名为article
,创建应用之后还需要在settings.py
中声明应用
python3 manage.py startapp article
声明应用,在settings中对应的列表(INSTALLED_APPS)中添加应用名
此时的目录结构变成了
├── article
│ ├── admin.py
│ ├── apps.py
│ ├── __init__.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
├── db.sqlite3
├── manage.py
└── mysite1
├── __init__.py
├── __pycache__
│ ├── __init__.cpython-36.pyc
│ ├── settings.cpython-36.pyc
│ ├── urls.cpython-36.pyc
│ ├── views.cpython-36.pyc
│ └── wsgi.cpython-36.pyc
├── settings.py
├── urls.py
├── views.py
└── wsgi.py
models.py
文件为:from django.db import models
# Create your models here.
class Article(models.Model):
title = models.CharField(max_length=30)
content = models.TextField()
接着使用命令makemigrations
制造迁移,使用命令migrate
完成迁移。
进入打开数据库,发现如果没有指定主键,Django会自动生成pkey
Article.py
,并注册from django.contrib import admin
from .models import Article
# Register your models here.
admin.site.register(Article)
回到后台,刷新之后出现Article
选项,
并且可以完成增删改查等等操作
小结:
新建一个应用使用命令python3 manage.py startapp app_name
,使用命令python3 manage.py makemigrations
完成数据迁移的制造,之后再使用命令python3 manage.py migrate
完成数据迁移,迁移的数据生成文件在应用目录下的migrations目录下。在应用中的models.py声明模型类,在admin.py文件中修改后台。
from django.shortcuts import render
from django.http import HttpResponse
# Create your views here.
def article_detail(request, article_id):
return HttpResponse("文章id为:%s"%article_id
在引入对应的方法然后添加路由
其中的<int:article_id>
代表article_id是一个整型数据,参数名称必须和article_detail方法的参数名一致。
首先在admin后台向article中添加多条数据
把article/views.py修改为
from django.shortcuts import render
from django.http import HttpResponse
from .models import Article
# Create your views here.
def article_detail(request, article_id):
article = Article.objects.get(id=article_id)
return HttpResponse("文章title为:%s"%article.title)
当然也可以同时显示文章标题和文章内容,article/views.py内容
from django.shortcuts import render
from django.http import HttpResponse
from .models import Article
# Create your views here.
def article_detail(request, article_id):
article = Article.objects.get(id=article_id)
return HttpResponse("文章title为:%s<br>文章的内容为:%s"%(article.title, article.content))
当访问的id超出数据库中id范围会返回一个DoesNotExist
异常
为了程序的健壮性需要在article/views.py
处理异常,一般情况下返回404
from django.shortcuts import render
from django.http import HttpResponse
from .models import Article
# Create your views here.
def article_detail(request, article_id):
try:
article = Article.objects.get(id=article_id)
except Article.DoesNotExist as e:
return HttpResponse("404")
return HttpResponse("文章title为:%s<br>文章的内容为:%s"%(article.title, article.content))
Django中提供了get_object_or_404
方法,如果对象不为空返回对象,对象不存在返回404异常。
from django.shortcuts import get_object_or_404
...
blog = get_object_or_404(Blog,pk=blog_pk)
from django.shortcuts import render
from django.http import HttpResponse
from .models import Article
# Create your views here.
def article_detail(request, article_id):
try:
article = Article.objects.get(id=article_id)
context = {}
context["article_obj"] = article
return render(request, "article_detail.html", context)
except Exception as e:
raise
并且在article应用的根目录中新建一个目录template
,这个目录中存放html模板文件。例如新建一个模板文件为article_detail.html
,内容为:
<html>
<head>
<title>article_detail</title>
</head>
<body>
<h3>{{article_obj.title}}</h3>
<p>{{article_obj.content}}</p>
</body>
</html>
其中的render(request, "article_detail.html", context)
方法一共有三个参数,第一个为request
:存放与请求相关的信息,第二个"article_detail.html"
为使用的模板文件名称,第三个context
则是存放模板所需要的参数字典对象。与render
方法相类似的方法还有render_to_response("article_detail.html", context)
主要参数只有两个模板文件名和参数字典,request对象会自动传过去。
而在模板文件中使用到脚本传过来的参数的使用方法是{{参数字典对象.参数的key}}
。
而在django.shortcuts
模块中还有一个非常常用的方法get_object_or_404
,如果存在对象返回对象,否则返回404.可以精简代码。
精简后的article/views代码
from django.shortcuts import render, render_to_response, get_object_or_404
from django.http import HttpResponse
from .models import Article
# Create your views here.
def article_detail(request, article_id):
article = get_object_or_404(Article, id=article_id)
context = {}
context["article_obj"] = article
#return render(request, "article_detail.html", context)
return render_to_response("article_detail.html", context)
In [1]: def test_locals(var):
...: a = 1
...: print(locals())
...:
In [2]: test_locals(2)
{'a': 1, 'var': 2}
locals()函数的特性可以在views视图中使用
比如存在这样的一个视图方法
def current_datetime(request):
now = datetime.datetime.now()
return render_to_response('current_datetime.html', {'current_date': now})
我们可以利用locals函数进行偷懒,但是这个偷懒的方法是有代价的,在下面例子中locals()还包含request
def current_datetime(request):
current_date = datetime.datetime.now()
return render_to_response('current_datetime.html', locals())
```requestrequest
- 模板文件的for循环,类似的还用if
现在写一个文章列表界面,首先需要在article/views.py中添加一个方法`article_list(request)`
```python
def article_list(request):
articles = Article.objects.all()
context = {}
context["articles"] = articles
return render(request, "artilce_list.html", context)
然后修改路由配置,添加一项配置
path("article/", article_list),
然后在article/templates
中新增加一个模板article_list.html
<html>
<head>
<title>article_list page</title>
</head>
<body>
{%for article in articles%}
<a href="/article/{{article.id}}">{{article.title}}</a><br>
{%endfor%}
</body>
</html>
其中{{article.id}}
可以修改为{{article.pk}}
,pk即是主键的缩写,建议使用{{article.pk}}
urls.py
文件,在这个文件中配置好路由信息之后,再在主的路由配置文件中通过include包含子路由配置文件的内容。即是在urls.py
文件中注释代码的第三种配置方法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'))
详细步骤:
urls.py
文件from django.urls import path
from .views import article_detail, article_list
urlpatterns = [
path("<int:article_id>", article_detail),
path("", article_list),
]
from django.contrib import admin
from django.urls import path, include
from . import views
urlpatterns = [
path('admin/', admin.site.urls),
path("test/", views.index),
path("article/", include("article.urls"))
]
在真正的Django项目中,可能有五个,十个,二十个应用程序或更多。Django如何区分它们之间的URL名称?例如,polls应用程序有一个detail 视图,因此同一项目中的应用程序可能适用于博客。如何使Django知道在使用模板标签时为url创建哪个应用视图 ?{% url %}
答案是为URLconf添加名称空间。在polls/urls.py 文件中,继续并添加一个app_name以设置应用程序命名空间:
#urls.py
from django.urls import path
from . import views
app_name = 'polls' # 命名空间
urlpatterns = [
path('', views.index, name='index'),
path('<int:question_id>/', views.detail, name='detail'),
path('<int:question_id>/results/', views.results, name='results'),
path('<int:question_id>/vote/', views.vote, name='vote'),
]
在模板中使用命名空间
<li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>
问题描述:进入后台之后发现字段名显示的是Article object (1),更加合理的应该是显示文章的标题。
解决方法:在对应的models类中添加对应的__str__()
方法并且返回对应的字段。
from django.db import models
# Create your models here.
class Article(models.Model):
title = models.CharField(max_length=30)
content = models.TextField()
def __str__(self):
return self.title
运行结果
如果需要显示多个字段的话,则需要修改对应应用中的admin.py
from django.contrib import admin
from .models import Article
# Register your models here.
class ArticleAdmin(admin.ModelAdmin):#增加实现admin.ModelAdmin的类
list_display = ("id", "title", "content")
admin.site.register(Article, ArticleAdmin)#增加对应的admin类
运行效果(此时的id为逆序)
因为默认排序为逆序,假如需要自定义排序的方法需要在admin类中添加ording
from django.contrib import admin
from .models import Article
# Register your models here.
class ArticleAdmin(admin.ModelAdmin):
list_display = ("id", "title", "content")
ordering = ("id",) # id正序排序,注意是元祖不是括号
admin.site.register(Article, ArticleAdmin)
需要逆序的话(默认):ordering = ("-id",)
同时可以装饰器来装饰admin定制类
from django.contrib import admin
from .models import Article
# Register your models here.
@admin.register(Article) # 增加的admin装饰器,代码清晰很多了
class ArticleAdmin(admin.ModelAdmin):
list_display = ("id", "title", "content")
ordering = ("-id",)
admin.site.register(Article, ArticleAdmin)
问题描述:在一开始模型设计时可能出现问题,或者是业务需求的改变,需要向数据库中增加一些字段,比如前面创建的article的model举例,models中只有标题和内容,现在我们需要向里面增加一个字段:创建文章的时间(create_data)
步骤:
from django.db import models
# Create your models here.
class Article(models.Model):
title = models.CharField(max_length=30)
content = models.TextField()
create_data = models.DateTimeField(auto_now__add=True) ## 新增的字段
def __str__(self):
return self.title
重新运行之后,刷新界面报错
之后执行制造迁移(makemigrations),和迁移(migrate)即可,在admin.py增加显示的项目,效果
继续修改models.py文件,添加最后更新时间
from django.db import models
# Create your models here.
class Article(models.Model):
title = models.CharField(max_length=30)
content = models.TextField()
create_date = models.DateTimeField(auto_now_add=True)
last_update_date = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
其中的DateTimeField的参数auto_now_add适合用在功能类似创建时间字段中,他的时间只会自动生成一次。而DateTimeField的参数设置为auto_now则适合在更新时间字段,每一次执行的更新数据库操作都会更新时间。
常见的还有设置外键models.ForeignKey
等等
用两个括号括起来的文字(例如{{person_name}})称为变量.此处插入指定变量的值.
用大括号和百分号包围的文字(例如{%if xxxxx%})被称为模板标签.标签(tag)定义比较明确,即: 仅通知模板系统完成某些工作的标签。模板标签一般都有结束标签比如if的结束标签是{%endif%}
一般最简单的设置url的方法这这样的
{% for blog in blogs%}
<h3><a href="blog/{{blog.pk}}">{{blog.title}}</a></h3>
{%endfor%}
Django还提供一个url标签,首先在urls.py文件设置url时需要设置一个路由的别名
urlpatterns = [
path("", blog_list, name = "home"),
]
接着在模板文件中可以使用url标签调用对应的url
<a href="{%url 'home'%}">
结果和下面的方法一样,但是建议使用url标签
<a> href="/"</a>
{% for blog in blogs%}
<h3><a href="blog/{{blog.pk}}">{{blog.title}}</a></h3>
{% empty %}
<p>暂时没有博客</p>
{%endfor%}
当内容不为空时直接输出内容
进入后台把文章全部删除之后,刷新页面
给标签增加一个 reversed 使得该列表被反向迭代:
{% for athlete in athlete_list reversed %}
...
{% endfor %}
Django不支持退出循环操作。 如果我们想退出循环,可以改变正在迭代的变量,让其仅仅包含需要迭代的项目。 同理,Django也不支持continue语句,我们无法让当前迭代操作跳回到循环头部。
在每个{% for %}
循环里有一个称为forloop
的模板变量。这个变量有一些提示循环进度信息的属性。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!