一个公司是由公司中的各部部门来组成的,每一个部门拥有特定的职能,部门与部门之间通过相互的配合来完成让公司运转起来。
一个软件框架是由其中各个软件模块组成的,每一个模块都有特定的功能,模块与模块之间通过相互配合来完成软件的开发。
软件框架是针对某一类软件设计问题而产生的。
MVC最初是由施乐公司旗下的帕罗奥多研究中心中的一位研究人员给 smalltalk语言发明的一中软件设计模式。
MVC的产生理念: 分工。让专门的人去做专门的事。
MVC的核心思想: 解耦。
MVC的思想被应用在的web开发的方面,产生了web MVC框架。
通过浏览器注册用户信息。
M:Model,模型, 和数据库进行交互。
V:View,视图, 产生html页面。
C:Controller,控制器, 接收请求,进行处理,与M和V进行交互,返回应答。
Django是劳伦斯出版集团的开发人员为开发新闻内容网站而设计出来的一个软件,它遵循MVC思想,但是有自己的一个名词,叫做MVT。
Django遵循快速开发和DRY原则。Do not repeat yourself.不要自己去重复一些工作。
M:Model,模型, 和MVC中M功能相同,和数据库进行交互。
V:View,视图, 和MVC中C功能相同,接收请求,进行处理,与M和T进行交互,返回应答。
T:Template,模板, 和MVC中V功能相同,产生html页面。
问题:同一台机器中的两个不同的项目,依赖不同版本的包,使用的环境也不一样,这个问题怎么解决?
之前安装python包的命令: sudo pip3 install 包名
包的安装路径:/usr/local/lib/python3.5/dist-packages
在同一个python环境中安装同一个包的不同版本,后安装的包会把原来安装的包覆盖掉。这样,如果同一台机器上两个项目依赖于相同包的不同版本,则会导致一些项目运行失败。
解决的方案就是:虚拟环境。
虚拟环境是真实python环境的复制版本。
在虚拟环境中使用的python是复制的python,安装python包也是安装在复制的python中。
1)sudo pip install virtualenv
#安装虚拟环境
2)sudo pip install virtualenvwrapper
#安装虚拟环境扩展包
3)编辑家目录下面的.bashrc文件,添加下面两行。
export WORKON_HOME=$HOME/.virtualenvs
source /usr/local/bin/virtualenvwrapper.sh
4)使用source .bashrc使其生效一下。
创建虚拟环境命令:
mkvirtualenv 虚拟环境名
创建python3虚拟环境:
mkvirtualenv -p python3 django_py3
进入虚拟环境工作:
workon 虚拟环境名
查看机器上有多少个虚拟环境:
workon 空格 + 两个tab键
退出虚拟环境:
deactivate
删除虚拟环境:
rmvirtualenv 虚拟环境名
虚拟环境下安装包的命令:
pip install 包名
注意:不能使用sudo pip install 包名,这个命令会把包安装到真实的主机环境上而不是安装到虚拟环境中。
查看虚拟环境中安装了哪些python包:
`pip list`
`pip freeze`
1.安装虚拟环境
pip install virtualenv
2.安装虚拟环境扩展包
pip install vritualenvwraper-win
pip install virtualenvwrapper-win
3、指定虚拟环境的python解释器
virtualenv -p C:\python36\python.exe
3、 创建虚拟环境,
mkvirtualenv dj_py3
4、配置环境变量
通过计算机–>属性–>高级系统设置–>环境变量–>在系统变量中新建“变量名”:WORKON_HOME,变量值:“你自定义的路径”
5、列出所有虚拟环境
`lsvirtualenv`
6、进入虚拟环境
`workon venv `
7、退出虚拟环境
deactivate
8、删除虚拟环境
rmvirtuatenv 虚拟环境名称
rmvirtualenv 虚拟环境名称
安装django:
pip install django==1.8.2
包安装:
pip install python包名
虚拟环境包导出(用于备份?)
pip freeze >pack.txt
虚拟环境恢复
pip install -r pack.txt
命令:django-admin startproject 项目名
注意:创建应用必须先进入虚拟环境。
项目目录如下:
dj_py3) python@ubuntu:~/Desktop/djproject3$ django-admin startproject demo1
(dj_py3) python@ubuntu:~/Desktop/djproject3$ cd demo1/
(dj_py3) python@ubuntu:~/Desktop/djproject3/demo1$ tree
.
├── manage.py
└── demo1
├── __init__.py
├── settings.py
├── urls.py
└── wsgi.py
manage.py
是项目管理文件,通过它管理项目。_init_.py
是一个空文件,作用是这个目录demo1可以被当作包使用。settings.py
是项目的整体配置文件。urls.py
是项目的URL配置文件。wsgi.py
是项目与WSGI兼容的Web服务器入口,详细内容会在布署中讲到。。一个项目由很多个应用组成的,每一个应用完成一个功能模块。
创建应用的命令如下:python mange.py startapp 应用名称
(dj_py3) python@ubuntu:~/Desktop/djproject3/demo1$ python manage.py startapp news
(dj_py3) python@ubuntu:~/Desktop/djproject3/demo1$ tree
.
├── manage.py
├── demo1
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-35.pyc
│ │ └── settings.cpython-35.pyc
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── news
├── admin.py
├── __init__.py
├── migrations
│ └── __init__.py
├── models.py
├── tests.py
└── views.py
_init.py_
是一个空文件,表示当前目录news可以当作一个python包使用。tests.py
文件用于开发测试用例,在实际开发中会有专门的测试人员,这个事情不需要我们来做。models.py
文件跟数据库操作相关。views.py
文件跟接收浏览器请求,进行处理,返回页面相关。admin.py
文件跟网站的后台管理相关。migrations
文件夹之后给大家介绍。应用创建成功后,需要注册才可以使用,也就是建立应用和项目之间的关联,在项目/settings.py
中INSTALLED_APPS下添加应用的名称就可以完成注册。
初始项目的INSTALLED_APPS如下图:
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'news',
)
运行开发web服务器命令:
python manage.py runserver
我们之前操作数据库是通过写sql语句,那么能不能不写sql语句就可以操作数据库呢? 可以,就是通过接下来要给大家讲的ORM框架。
O是object,也就类对象的意思,R是relation,翻译成中文是关系,也就是关系数据库中数据表的意思,M是mapping,是映射的意思。在ORM框架中,它帮我们把类和数据表进行了一个映射,可以让我们通过类和类对象就能操作它所对应的表格中的数据。ORM框架还有一个功能,它可以根据我们设计的类自动帮我们生成数据库中的表格,省去了我们自己建表的过程。
django中内嵌了ORM框架,不需要直接面向数据库编程,而是定义模型类,通过模型类和对象完成数据表的增删改查操作。
使用django进行数据库开发的步骤如下:
下面我们以保存图书信息为例来给大家介绍Django中进行数据库开发的整个流程。
模型类定义在models.py文件中,继承自models.Model类。
说明:不需要定义主键列,在生成时会自动添加,并且值为自动增长。
根据设计,在models.py中定义模型类如下:
from django.db import models
class NewsInfo(models.Model):
title = models.CharField(max_length=40)
content = models.CharField(max_length=5000)
b_date = models.DateField()
迁移前目录结构如下图:
.
├── manage.py
├── demo1
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-35.pyc
│ │ └── settings.cpython-35.pyc
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── news
├── admin.py
├── __init__.py
├── migrations
│ └── __init__.py
├── models.py
├── tests.py
└── views.py
迁移由两步完成:
生成迁移文件命令如下:
python manage.py makemigrations
生成迁移文件
├── migrations
│ ├── 0001_initial.py
执行生成迁移文件命令后,会在应用news目录下的migrations目录中生成迁移文件。
生成迁移文件后的目录结构:
.
├── manage.py
├── demo1
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-35.pyc
│ │ └── settings.cpython-35.pyc
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── news
├── admin.py
├── __init__.py
├── migrations
│ ├── 0001_initial.py
│ ├── __init__.py
│ └── __pycache__
│ └── __init__.cpython-35.pyc
├── models.py
├── __pycache__
│ ├── admin.cpython-35.pyc
│ ├── __init__.cpython-35.pyc
│ └── models.cpython-35.pyc
├── tests.py
└── views.py
打开上图中的迁移文件,内容如下:
class Migration(migrations.Migration):
dependencies = [
]
operations = [
migrations.CreateModel(
name='NewsInfo',
fields=[
('id', models.AutoField(verbose_name='ID', primary_key=True, serialize=False, auto_created=True)),
('title', models.CharField(max_length=20)),
('content', models.TextField()),
('b_date', models.DateField()),
],
),
]
Django框架根据我们设计的模型类生成了迁移文件,在迁移文件中我们可以看到fields列表中每一个元素跟newsInfo类属性名以及属性的类型是一致的。同时我们发现多了一个id项,这一项是Django框架帮我们自动生成的,在创建表的时候id就会作为对应表的主键列,并且主键列自动增长。
执行迁移命令如下:python manage.py migrate
(dj_py3) python@ubuntu:~/Desktop/djproject3/demo1$ python manage.py migrate
Operations to perform:
Synchronize unmigrated apps: staticfiles, messages
Apply all migrations: contenttypes, auth, admin, sessions, news
Synchronizing apps without migrations:
Creating tables...
Running deferred SQL...
Installing custom SQL...
Running migrations:
Rendering model states... DONE
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying sessions.0001_initial... OK
Applying news.0001_initial... OK
当执行迁移命令后,Django框架会读取迁移文件自动帮我们在数据库中生成对应的表格。
迁移后目录结构如下图:
.
├── db.sqlite3
├── manage.py
├── demo1
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-35.pyc
│ │ └── settings.cpython-35.pyc
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── news
├── admin.py
├── __init__.py
├── migrations
│ ├── 0001_initial.py
│ ├── __init__.py
│ └── __pycache__
│ ├── 0001_initial.cpython-35.pyc
│ └── __init__.cpython-35.pyc
├── models.py
├── __pycache__
│ ├── admin.cpython-35.pyc
│ ├── __init__.cpython-35.pyc
│ └── models.cpython-35.pyc
├── tests.py
└── views.py
Django默认采用sqlite3数据库,上图中的db.sqlite3就是Django框架帮我们自动生成的数据库文件。 sqlite3是一个很小的数据库,通常用在手机中,它跟mysql一样,我们也可以通过sql语句来操作它。
生成的数据表的默认名称为:应用名字_类名
例:
news_newsinfo
完成数据表的迁移之后,下面就可以通过进入项目的shell,进行简单的API操作。如果需要退出项目,可以使用ctrl+d快捷键或输入quit()。
进入项目shell的命令:python manage.py shell
(dj_py3) python@ubuntu:~/Desktop/djproject3/demo1$ python manage.py shell
Python 3.5.2 (default, Nov 23 2017, 16:37:01)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>>
首先引入news.models 中的类:
from news.models import NewsInfo
查询所有体育新闻信息:
>>> NewsInfo.objects.all()
因为当前并没有数据,所以返回空列表
>>> NewsInfo.objects.all()
[]
新建新闻对象:
>>> b = NewsInfo()
>>> b.title = '斯坦科维奇杯:中国男篮红队胜突尼斯队'
>>> b.content = '8月14日,在广东深圳举行的2018年斯坦科维奇杯洲际篮球赛的首日比赛中,中国男篮红队以77比72战胜突尼斯队'
b.b_date=datetime.date(2018,8,15)
b.save()
(改)
b = NewsInfo()
b.title = '斯坦科维奇杯:中国男篮红队胜突尼斯队'
b.content = '8月14日,在广东深圳举行的2018年斯坦科维奇杯洲际篮球赛的首日比赛中,中国男篮红队以77比72战胜突尼斯队'
b.b_date='2018-8-15'
b.save()
再次查询所有信息:
>>> NewsInfo.objects.all()
查找该条新闻信息并查内容:
>>> b=NewsInfo.objects.get(id=1)
>>> b
<NewsInfo: NewsInfo object>
>>> b.id
1
>>> b.title
'斯坦科维奇杯:中国男篮红队胜突尼斯队'
>>> b.content
'8月14日,在广东深圳举行的2018年斯坦科维奇杯洲际篮球赛的首日比赛中,中国男篮红队以77比72战胜突尼斯队'
>>> b.b_date
datetime.date(2018, 8, 15)
修改该条新闻信息:
>>> b.b_date=date(2018,8,1)
>>> b.save()
>>> b.b_date
datetime.date(2018, 8, 1)
删除该条新闻信息:
>>> b.delete()
>>> NewsInfo.objects.all()
[]
假设我们要设计一个新闻网站,我们需要编写展示给用户的页面,网页上展示的新闻信息是从哪里来的呢?是从数据库中查找到新闻的信息,然后把它展示在页面上。但是我们的网站上的新闻每天都要更新,这就意味着对数据库的增、删、改、查操作,那么我们需要每天写sql语句操作数据库吗? 如果这样的话,是不是非常繁琐,所以我们可以设计一个页面,通过对这个页面的操作来实现对新闻数据库的增删改查操作。那么问题来了,老板说我们需要在建立一个新网站,是不是还要设计一个页面来实现对新网站数据库的增删改查操作,但是这样的页面具有一个很大的重复性,那有没有一种方法能够让我们很快的生成管理数据库表的页面呢?有,那就是我们接下来要给大家讲的Django的后台管理。Django能够根据定义的模型类自动地生成管理页面。
使用Django的管理模块,需要按照如下步骤操作:
本地化是将显示的语言、时间等使用本地的习惯,这里的本地化就是进行中国化,中国大陆地区使用简体中文,时区使用亚洲/上海时区,注意这里不使用北京时区表示。
打开test1/settings.py文件,找到语言编码、时区的设置项,将内容改为如下:
LANGUAGE_CODE = 'zh-hans' #使用中国语言
TIME_ZONE = 'Asia/Shanghai' #使用中国上海时间
创建管理员的命令如下,python manage.py createsuperuser
按提示输入用户名、邮箱、密码。
这里我设置的账号是python,密码是123qwe,邮箱随便输入一个
(dj_py3) python@ubuntu:~/Desktop/djproject3/demo1$ python manage.py createsuperuser
Username (leave blank to use 'python'): python
Email address: [email protected]
Password:
Password (again):
Superuser created successfully.
(dj_py3) python@ubuntu:~/Desktop/djproject3/demo1$
接下来启动服务器: python manage.py runserver iP地址:端口号
(dj_py3) python@ubuntu:~/Desktop/djproject3/demo1$ python manage.py runserver 192.168.93.169:7777
Performing system checks...
System check identified no issues (0 silenced).
August 15, 2018 - 10:03:29
Django version 1.8.2, using settings 'demo1.settings'
Starting development server at http://192.168.128.132:7777/
Quit the server with CONTROL-C.
打开浏览器,在地址栏中输入如下地址后回车。
python manage.py runserver 192.168.13.128:7777
http://192.168.13.128:7777/admin/
http://192.168.93.169:7777/admin/
输入前面创建的用户名、密码完成登录。
登录成功后界面如下,但是并没有模型类newsinfo的数据信息的管理入口,接下来进行第三步操作。
登录后台管理后,默认没有我们创建的应用中定义的模型类,需要在自己应用中的admin.py文件中注册,才可以在后台管理中看到,并进行增删改查操作。
打开news/admin.py文件,编写如下代码:
from django.contrib import admin
from .models import NewsInfo
admin.site.register(NewsInfo)
到浏览器中刷新页面,可以看到模型类newsInfo的管理了。
点击类名称"newsInfo"可以进入列表页,默认只有一列。
在列表页中点击"增加"可以进入增加页,Django会根据模型类的不同,生成不同的表单控件,按提示填写表单内容后点击"保存",完成数据创建,创建成功后返回列表页。
在列表页中点击某行的第一列可以进入修改!
按照提示进行内容的修改,
修改成功后进入列表页。在修改页点击“删除”可以删除一项。
点击执行后进入确认页面,删除后回来列表页面。
在列表页只显示出了NewsInfo object,对象的其它属性并没有列出来,查看非常不方便。 Django提供了自定义管理页面的功能,比如列表页要显示哪些值。
打开News/admin.py文件,自定义类,继承自admin.ModelAdmin类。
class newsInfoAdmin(admin.ModelAdmin):
list_display = ['id', 'title', 'b_date']
admin.site.register(newsInfo,newsInfoAdmin)
from django.contrib import admin
from .models import NewsInfo
class NewsInfoAdmin(admin.ModelAdmin):
list_display = ['id','title','b_date']
admin.site.register(NewsInfo,NewsInfoAdmin)
后台管理页面做好了,接下来就要做公共访问的页面了。当我们刚刚在浏览器中输入 http://192.168.128.132:7777/admin之后,浏览器显示出了后台管理的登录页面,那有没有同学想过这个服务器是怎么给我们找到这个页面并返回呢?/admin/是我们想要请求的页面,服务器在收到这个请求之后,就一定对应着一个处理动作,这个处理动作就是帮我们产生页面内容并返回回来,这个过程是由视图来做的。
对于django的设计框架MVT,用户在URL中请求的是视图,视图接收请求后进行处理,并将处理的结果返回给请求者。
使用视图时需要进行两步操作:
* 1.定义视图函数
* 2.配置URLconf
视图就是一个Python函数,被定义在views.py中。
视图的必须有一个参数,一般叫request,视图必须返回HttpResponse对象,HttpResponse中的参数内容会显示在浏览器的页面上。
打开news/views.py文件,定义视图index如下
from django.http import HttpResponse
def index(request):
return HttpResponse('这个是index页面')
请求者在浏览器地址栏中输入url,请求到网站后,获取url信息,然后与编写好的URLconf逐条匹配,如果匹配成功则调用对应的视图函数,如果所有的URLconf都没有匹配成功,则返回404错误。
一条URLconf包括url规则、视图两部分:
需要两步完成URLconf配置:
在news/应用下创建urls.py文件,定义代码如下:
from django.conf.urls import url
from news import views
urlpatterns = [
url(r'^$', views.index),
]
包含到项目中:打开demo1/urls.py文件,为urlpatterns列表增加项如下:
url(r'^',include('news.urls')),
demo1/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('news.urls')),
]
视图和URLconf都定义好了,接下来在浏览器地址栏中输入网址:
http://192.168.128.132:8000/
http://192.168.93.169:7777/
网页显示效果如下图,视图被成功执行了。
在news/views.py的index函数中先把模型类里面的数据查询出来,然后返回到页面上,
修改views.py中的代码,如下
from django.shortcuts import render
# Create your views here.
from django.http import HttpResponse
from .models import NewsInfo
def index(request):
s_info = NewsInfo.objects.all()
content = [[item.title,item.content] for item in s_info]
return HttpResponse(content)
在重新请求页面:192.168.128.132:7777
如何向请求者返回一个漂亮的页面呢?
肯定需要用到html、css,如果想要更炫的效果还要加入js,问题来了,这么一堆字段串全都写到视图中,作为HttpResponse()的参数吗?这样定义就太麻烦了吧,因为定义字符串是不会出任何效果和错误的,如果有一个专门定义前端页面的地方就好了。
解决问题的技术来了:模板。
在Django中,将前端的内容定义在模板中,然后再把模板交给视图调用,各种漂亮、炫酷的效果就出现了。
为应用news下的视图index创建模板index.html,在项目目录下新建一个名为templates的文件夹,在该文件夹下面新建一个和应用同名的文件夹,结构目录如下:
设置查找模板的路径:打开demo1/settings.py文件,设置TEMPLATES的DIRS值
'DIRS': [os.path.join(BASE_DIR, 'templates')],
打开templates/news/index.html文件,定义代码如下:
首页
{{title}}
{%for i in list%}
{{i}}
{%endfor%}
在模板中输出变量语法如下,变量可能是从视图中传递过来的,也可能是在模板中定义的。
{{变量名}}
在模板中编写代码段语法如下:
{%代码段%}
调用模板分为三步骤:
打开news/views.py文件,调用上面定义的模板文件
from django.http import HttpResponse
from django.template import loader,RequestContext
def index(request):
# 1.获取模板
template=loader.get_template('news/index.html')
# 2.定义上下文
context=RequestContext(request,{'title':'新闻列表','list':range(10)})
# 3.渲染模板
return HttpResponse(template.render(context))
打开浏览器刷新页面,显示效果如下图:(如果不行,重启试试)
视图调用模板都要执行以上三部分,于是Django提供了一个函数render封装了以上代码。 方法render包含3个参数:
打开news/views.py文件,调用render的代码如下:
from django.shortcuts import render
def index(request):
context={'title':'新闻列表','list':range(10)}
return render(request,'news/index.html',context)
基本知识点都学完了,接下来完成示例项目。
现在还需要的代码包括三个方面,三个方面顺序不分先后。
编写news/views.py文件如下:
from django.shortcuts import render
from news.models import NewsInfo
#首页,展示所有新闻标题
def index(reqeust):
#查询所有新闻
context_list = NewsInfo.objects.all()
#将新闻列表传递到模板中,然后渲染模板
return render(reqeust, 'news/index.html', {'context_list': context_list})
#详细页,接收每条新闻的id编号,根据编号查询到本条新闻的详细信息并展示
def detail(request,bid):
#根据id查询到对应的新闻信息
s = NewsInfo.objects.get(id=int(bid))
#获取新闻的详细数据
context = {
'title' : s.title,
'date':s.b_date,
'context':s.content
}
# 调用模板渲染数据,并返回页面
return render(request,'news/detail.html',context)
编写news/urls.py文件如下:
from django.conf.urls import url
#引入视图模块
from .views import *
urlpatterns = [
#配置首页url
url(r'^$',index),
#配置详细页url,\d+表示多个数字,小括号用于取值,建议复习下正则表达式
url(r'^(\d+)/$',detail),
]
编写templates/news/index.html文件如下:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页title>
head>
<body>
<h1>{{h1}}h1>
{%for context in context_list%}
<li><a href="/{{context.id}}">{{context.title}}a>{{context.b_date}}li>
<br>
{%endfor%}
body>
html>
编写templates/news/detail.html文件如下:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>详情页title>
head>
<body>
<h1>{{title}}h1>
<hr>
<p>{{context}}p>
<br>
<span>{{date}}span>
<br>
<h3><a href="/">返回首页a>h3>
body>
html>
未完待续。。。
最后:
文章为18年python全栈学习资料记录转载,侵告删