一、简介
Django,发音为[`dʒæŋɡəʊ],是用python语言写的开源web开发框架,并遵循MVC设计。其核心思想是分工、解耦,让不同的代码块之间降低耦合,增强代码的可扩展性和可移植性,实现向后兼容。
M全拼为Model,与MVC中的M功能相同,负责和数据库交互,进行数据处理。
V全拼为View,与MVC中的C功能相同,接收请求,进行业务处理,返回应答。
T全拼为Template,与MVC中的V功能相同,负责封装构造要返回的html。
二、django的环境搭建
1、安装python环境
安装python
1.1 —不要默认安装,点击第二个选项,记得点击添加环境变量,不然得手动去添加。
1.2—python版本如果是64位的就用windows下的cmd,如果是32位的就得用system32里面的,不然可能会报错。
1.3—win10有时候需要用管理员权限打开,否则会报错
2、安装vietualenv(创建和管理虚拟空间)
2.1、安装命令:
pip install virtualenv
2.2、创建虚拟空间:
virtualev [空间名称]
3、安装virtualenvwrapper(用来辅助virtualenv,更加灵活)
3.1—安装:
pip insall virtualenvwrapper
3.2—添加环境边变量:
WORKON_HOME C:\aaa 那么将来创建的虚拟空间默认就在aaa里面
3.3—创建命令:
mkvirtualenv[空间名]
3.4—切换空间:
workon xxx
3.5—查看里面有哪些包:
pip list
4、安装django
4.1、安装命令:
pip install django
4.2、备注:如果要安装在新的空间里面,必须先cd 进入到虚拟空间的根目录下,再使用命令
4.3、django创建第一个项目:django-admin startproject [项目名称]
4.4、运行服务:python manage.py runserver 0.0.0.0:8000
4.5、运行:打开浏览器,输入127.0.0.1:8000
三、创建diango项目:
1、diango-admin startproject 项目名
1.1、进入到安装了django虚拟环境中,然后执行命令
django-admin startproject[项目名]
#这样就可以创建一个新项目
创建一个app
django-admin startapp app名称
1.2、运行项目:cmd中进入到项目所在目录,然后运行
python manage.py runserver
2、在pycharm中建立项目
2.1、在pycharm中新建文件,选择django,选择工作目录,创建即可
2.2、运行:直接点击右上角绿色三角按钮
备注:如果状态栏出现多个项目,则会出现重复服务器,监听会出现问题,代码在不断更改,可能出现运行问题。
在项目配置中只用单一实例的这个选项,避免以上的问题。
3、运行端口制定
3.1、python manage.py runserver 9000
在浏览器中输入127.0.0.1:9000才可以访问
3.2、如过在其它的电脑来访问,那么可以定义,任何网络形式都可以访问。
python manage.py 0.0.0.0:8000
3.3、在右边项目名称点击一下,点击边编辑配置,输入host:0.0.0.0,换电脑可访问。
3.4、在settings.py中设置allowed_hosts中加入自己本机的IP地址(别人访问才能正确访问)
4、项目结构分析
manage.py是专门用来管理这个项目,和项目进行交互的(可通过python manage.py help来产看)
seettings.py;保存项目所有的配置信息
urls.py:用来做url与视图函数做映射的,以后来的请求就从这个文件中找到对应的视图函数
wsgi.py:是用来做部署的,不需要修改
5、视图函数:
5.1、视图函数的第一个参数必须是request
5.2、视图函数的第一个返回值必须是django.http.response.HttprResponsebase的子类的对象
5.3、views:
from django.shortcuts import render
from django.http import HttpResponse
def book(request):
return HttpResponse('图书首页')
def book_detail(request,book_id):
#可以从数据库来查询ID对应的图书的名称
text="您获取的图书的ID是: %s" %book_id
return HttpResponse(text)
6、url中添加参数
6.1、采用在URL中使用变量的方式:在path的第一个参数中使用<参数名>的方式可以传递参数,然后在视图函数中也要写一个参数,视图中的参数必须和URL中的参数必须保持一致,不然你就找不到这个参数,另外URL中可以传递多个参数
urls:
from django.contrib import admin
from django.urls import path
from book import views
urlpatterns = [
path('admin/', admin.site.urls),
path('book/',views.book),
path("book/detail/" ,views.book_detail)
]
浏览器访问:
127.0.0.1:8000/book/detail/1
path("book/detail///" ,views.book_detail)
多个参数同样在views中也要定义参数
def book_detail(request,book_id,category_id):#多个参数需加入方法
#可以从数据库来查询ID对应的图书的名称
text="您获取的图书的ID是: %s, 图书类别是%s" %(book_id,category_id) #多个参数赋值
return HttpResponse(text)
浏览器访问:
127.0.0.1:8000/book/detail/1/2
6.2 多个app的url引用
主url文件
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('test/',include('views_demo.urls')),
]
app的视图层
from django.shortcuts import render
from django.http import HttpResponse
def hello(request):
return HttpResponse('hello world!')
app的子url配置
from django.contrib import admin
from django.urls import path
from views_demo import views
urlpatterns = [
path('admin/', admin.site.urls),
path('hello/',views.hello),
]
访问:
http://127.0.0.1:8000/test/hello/
6.3、视图层采用查询字符串的方式获取值
def 视图方法(request): #必须有request
元素=request.Get.get(‘参数’)
text=‘作者的id是: %s’%元素
return HttpResponse(text)
在URL中不需要单独的匹配查询字符串的部分,只需要在视图函数中用以下的方式来传递获取。
获取get传参的单个值
request.Get.get('参数名称')
获取post传参的单个值
request.Post.get('name')
获取post传参的多个值
request.Post.getlist('name')
urls
path('book/author/',views.author_detail)
views
def author_detail(request):
author_id=request.GET.get('id')
text='作者的ID是 %s' % author_id
return HttpResponse(text)
浏览器输入
http://127.0.0.1:8000/book/author/?id=4
6.4 命名空间
我们先给每个子路由起个名字
每个子路由中指定app_name
app_name='app01'
每个app的相关的url路径后面加name属性
app01/url
path('hello/',views.hello,name = 'hello'),
path('bye/',views.bye,name='bye'),
app02/url
path('hello/',views.hello,name = 'hello'),
然后在主路由使用include分发路由的时候,给每个子路由指定一个命名空间,这样就可以区分出每个子路由中的同名路由了
path("v01/",include("app01.urls",'app01')), # 主路由在使用include分发路由的时候,指定每个子路由的命名空间
path("v02/",include("app02.urls",'app02')) ,
视图中可以使用"命名空间:路由名"的方式来解析url
def hello(request):
print(reverse("app01:bye")) # 可以使用"命名空间:路由名"的方式来解析url
return HttpResponse('我是app02中的hello')
7、原生语句操作数据库
原生语句操作数据库
#设置seetting.py
DATABASES = {
'default': {
#数据引擎,可不同的数据库
'ENGINE': 'django.db.backends.mysql',
#数据库的名字
'NAME': 'django_db1',
#链接数据库的用户名
'USER' : 'root',
#链接数据库的密码
'PASSWORD':'root',
#数据库的IP地址
'HOST':'127.0.0.1',
#数据库的端口号
'PORT':'3306' } }
#views.py
from django.shortcuts import render
from django.db import connection
def index(request):
cursor=connection.cursor()
#cursor.execute("insert into book(id,name,author) values(null,'三国演义','罗贯中')")
cursor.execute("select * from book")
rows=cursor.fetchall()
for row in rows:
print(row) return render(request,'index.html')
课外知识:常用的正则表达式符号匹配
. (dot) 任意单一字符
\d 任意一位数字
[A-Z] A 到 Z中任意一个字符(大写)
[a-z] a 到 z中任意一个字符(小写)
[A-Za-z] a 到 z中任意一个字符(不区分大小写)
+ 匹配一个或更多 (例如, \d+ 匹配一个或 多个数字字符)
[^/]+ 一个或多个不为‘/’的字符
* 零个或一个之前的表达式(例如:\d? 匹配零个或一个数字)
* 匹配0个或更多 (例如, \d* 匹配0个 或更多数字字符)
{1,3} 介于一个和三个(包含)之前的表达式(例如,\d{1,3}匹配一个或两个或三个数字)
DTL比html更智能
#渲染模板
如果在浏览器中无法正常读取html的内容,需要在seetting中设置参数
–创建一个index.html
'DIRS': [os.path.join(BASE_DIR, 'Templates')],
解析:
–DIRS这是一个列表,在这个列表中可以存放所有的模板路径,在视图函数views中使用render或render_to_string渲染模板的时候就从这个路径中查找文模板
–如果在当前新建的APP下面新建了一个Templates文件夹,其中新建了index.html那么如果不做上面的更改就可以在seetting.py中的installed_apps加入当前的app名称,那么即可访问当前的app
–app_dirs默认是TRUE,会默认从installes_apps中找templatesw文件中查找模板
–查找顺序
DIRS–>istalled_app中有没有–>没有的话抛异常
#渲染方式
–views.py
from django.shortcuts import render
def index(request):
# html=render_to_string("index.html")
# return HttpResponse(html)
return render(request,'index.html')
以上是两种渲染方式,第二种更简单直接
–urls
> from django.urls import path from front import views
> urlpatterns = [
> path('', views.index), ]
在浏览器访问127.0.0.0:8000
url标签的使用方式
views
from django.shortcuts import render
from django.http import HttpResponse
def index(request):
return render(request,'index.html')
def book(request):
return HttpResponse('读书页面')
def movie(request):
return HttpResponse('电影页面')
def city(request):
return HttpResponse('同城页面')
def book_detail(request,book_id,fenlei):
text='最受欢迎的图书编号是 %s ,分类是 %s' % (book_id,fenlei)
return HttpResponse(text)
def login(request):
next=request.GET.get('next')
login_text='您已经登录成功,已跳转页面到 %s'% next
return HttpResponse(login_text)
url
path('', views.index,name='/'),
path('book/', views.book,name='book'),
path('movie/', views.movie,name='movie'),
path('city/', views.city,name='city'),
path('book/detail///' , views.book_detail,name='detail'),
path('login/', views.login,name='login'),
index
<style>
.nav{
overflow: hidden;
}
.nav li{
float: left;
list-style: none;
margin: 0 20px;
}
</style>
<body>
<ul class="nav">
<li><a href="{% url '/' %}">首页</a></li>
<li><a href="{% url 'book' %}">读书</a></li>
<li><a href="{% url 'movie' %}">电影</a></li>
<li><a href="{% url 'city' %}">同城</a> </li>
<li><a href="{% url 'detail' book_id=1 fenlei=2 %}">最火的一篇文章</a> </li>
<li><a href="{% url 'login' %}?next=/">登录</a> </li>
</ul>
</body>
模板和视图分离
1、设置seeting的路径
'DIRS': [os.path.join(BASE_DIR, 'templates')],
views
from django.shortcuts import render_to_response
新建views.py
from django.shortcuts import render
def index(request):
context_me={
'username':'pengsgikui'
}
return render(request,'index.html',context=context_me)
解析:
引入render
定义了一个字典,里面的元素是username赋值
返回的时候context是render的一个参数,把context_me赋值给context
创建templates文件夹,新建index。html文件 ,
###返回的参数要用{{变量}}来表示
<body>
{{username}}
</body>
URLS
from django.urls import path
from . import views
urlpatterns = [
path('', views.index),
]
访问127.0.0.1:800
##第二种访问形式:.的形式
定义一个类
class person():
def __init__(self,username):
self.username=username
def index(request):
p=person("kaka")
context_me={
'person':p
}
return render(request,'index.html',context=context_me)
index.html
<body>
{{ person.username }}
</body>
def index(request):
context_me={
'person':{
'username':'shshi'
}
}
return render(request,'index.html',context=context_me)
index.html
<body>
{{ person.username }}
</body>
以列表返回一个字典所有的键
dict.keys()
在index.html中{{person.keys}} 显示结果:dict_keys([‘username’])
##不要在字典中使用字典的属性做名称
##访问列表中的元素,可用{{字典.key}}的方式,例如:person.1
context_me={
'persons':[
'程咬金',
'阿珂',
'鲁班七号'
]
}
return render(request,'index.html',context=context_me)
<body>
{{ persons.1 }}
</body>
元组也可以用同样的方法读取
context_me={(
'persons':
'程咬金',
'阿珂',
'鲁班七号' )}
if/else
{% if %}
标签检查(evaluate)一个变量,如果这个变量为真(即,变量存在,非空,不是布尔值假),系统会显示在 {% if %} 和 {% endif %} 之间的任何内容,例如:
{% if today_is_weekend %}
<p>Welcome to the weekend!</p>
{% endif %}
{% else %} 标签是可选的:
一定要用 {% endif %} 关闭每一个 {% if %} 标签。
django判断语句
1、所有的标签都在{% %}中
2、if标签有闭合标签{%if %} {%endif%}
3、if标签支持python所有的运算符
views
def index(request):
context={
'age':19
}
return render(request,'index.html',context=context)
index.html
<body>
{% if age < 18 %}
<p>您是未成年人,不允许进入网吧!</p>
{% elif age == 18 %}
<p>您是成年人可以进入网吧!</p>
{% else %}
<p>您已经是成年,该承担家庭责任,尽量不要进网吧!</p>
{% endif %}
</body>
第二种方式:判断条件在不在列表中
views
context={
'heros':[
'项羽',
'鲁班七号',
'米莱迪' ]}
index.html
{% if '鲁班七号' in heros %}
<p>鲁班七号正在待命</p>
{% else %}
<p>鲁班七号在睡觉!</p>
{% endif %}
{% for %} 允许我们在一个序列上迭代。 与Python的 for 语句的情形类似,循环语法是 for X in Y ,Y是要迭代的序列而X是在每一个特定的循环中使用的变量名称。 每一次循环中,模板系统会渲染在 {% for %} 和{% endfor %} 之间的所有内容。
例如,给定一个运动员列表 athlete_list 变量,我们可以使用下面的代码来显示这个列表:
<ul>
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% endfor %}
</ul>
for in标签
如果只取key:
{% for key in person.keys %}
如果只取vlues:
{% for vlue in person.vlues %}
反序排列:reversed
取整个字典的key和vlue则按下边
views
'person':{
'username': '李星星',
'age': 30,
'height': 180
}
index.html
{% for key,vlues in person.items %}
<ul>
<li>{{ key }}:{{ vlues }}</li>
</ul>
{% endfor %}
案例:
table输出书名,作者,价格
context={
'books':[
{
'name': '三国演义',
'author': '罗贯中',
'price': 260
}, {
'name': '西游记',
'author': '吴承恩',
'price': 320
},s
{
'name': '三国演义',
'author': '罗贯中',
'price': 260
}, {
'name': '西游记',
'author': '吴承恩',
'price': 320
} ],
index.html
<table>
<th>
<tr>
<td>序号</td>
<td>书名</td>
<td>作者</td>
<td>价格</td>
</tr>
{% for book in books %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ book.name }}</td>
<td>{{ book.author }}</td>
<td>{{ book.price }}</td>
</tr>
{% endfor %}
</th>
</table>
forloop.counter
总是一个表示当前循环的执行次数的整数计数器。 这个计数器是从1开始的,所以在第一次循环时 forloop.counter 将会被设置为1。
{% for item in todo_list %}
<p>{{ forloop.counter }}: {{ item }}</p>
{% endfor %}
forloop.counter0 类似于 forloop.counter ,但是它是从0计数的。 第一次执行循环时这个变量会被设置为0。
forloop.first 是一个布尔值,如果该迭代是第一次执行,那么它被置为[]
是一个布尔值;在最后一次执行循环时被置为True。 一个常见的用法是在一系列的链接之间放置管道符(|),另一个常见的用途是为列表的每个单词的加上逗号。
{% ifequal %} 标签比较两个值,当他们相等时,显示在 {% ifequal %} 和 {% endifequal %} 之中所有的值。
下面的例子比较两个模板变量 user 和 currentuser :
{% ifequal user currentuser %}
<h1>Welcome!</h1>
{% endifequal %}
就像HTML或者Python,Django模板语言同样提供代码注释。 注释使用 {# #} :
{# This is a comment #}
如果要实现多行注释,可以使用{% comment %} 模板标签,就像这样:
{% comment %}
This is a
multi-line comment.
{% endcomment %}
**
**
模板过滤器是在变量被显示前修改它的值的一个简单方法。 过滤器使用管道字符,如下所示:
{{ name|lower }}
显示的内容是变量 {{ name }} 被过滤器 lower 处理后的结果,它功能是转换文本为小写。
过滤管道可以被* 套接* ,既是说,一个过滤器管道的输出又可以作为下一个管道的输入,如此下去。
下面的例子实现查找列表的第一个元素并将其转化为大写。
{{ my_list|first|upper }}
有些过滤器有参数。 过滤器的参数跟随冒号之后并且总是以双引号包含。
例如:
{{ bio|truncatewords:"30" }}
这个将显示变量 bio 的前30个词。
addslashes : 添加反斜杠到任何反斜杠、单引号或者双引号前面。 这在处理包含JavaScript的文本时是非常有用的。
date : 按指定的格式字符串参数格式化 date 或者 datetime 对象,
范例:
{{ pub_date|date:"F j, Y" }}
格式参数的定义在附录F中。
length : 返回变量的长度。 对于列表,这个参数将返回列表元素的个数。 对于字符串,这个参数将返回字符串中字符的个数。 你可以对列表或者字符串,或者任何知道怎么测定长度的Python 对象使用这个方法(也就是说,有 len() 方法的对象)
过滤器add/cut/date的使用方法
#为什么要使用过滤器
因为在DTL中不能使用函数的调用:函数()。因此不能给函数传递参数,而过滤器其实就是一个函数,并且可以接收一个参数,并传递另外一个参数对现在的参数进行处理,也就是说最多可以传递两个参数
#Add参数
将两个参数进行相加或字符串拼接或元组拼接
def add_view(request):
context={
'value1':['a',2],
'value2':['b',5]
}
return render(request,'add_view.html',context=context)
path('add/',views.add_view),
{{ value1|add:value2 }}
#cut函数
将值1里面的某个和值2相同的字符删除为空
#replace 类似,只是不替换字符,而是直接替换为空字符串,就是把原来的这个字符串删除掉
def cut_view(request):
context={
'value1':'html',
'value2':'h'
}
return render(request,'cut_view.html',context=context)
url
path('cut/',views.cut_view),
html
{{ value1|cut:value2 }}
#date
格式化时间
from datetime import datetime
def date_view(request):
comtext={
'today':datetime.now()
}
return render(request,'date_view.html',context=comtext)
url
path('date/',views.date_view),
html
{{ today|date:'Y/m/d G:m:s' }}
**
**
在已经安装了的 app 下创建一个文件夹叫做 static ,然后再在这个 static 文件夹下创建一个当前 app 的名字的文件夹,再把静态文件放到这个文件夹下。例如你的 app 叫做 book ,有一个静态文件叫做 zhiliao.jpg ,那么路径为 book/static/book/zhiliao.jpg 。(为什么在 app 下创建一个 static 文件夹,还需要在这个 static 下创建一个同 app 名字的文件夹呢?原因是如果直接把静态文件放在 static 文件夹下,那么在模版加载静态文件的时候就是使用 zhiliao.jpg ,如果在多个 app 之间有同名的静态文件,这时候可能就会产生混淆。而在 static 文件夹下加了一个同名 app 文件夹,在模版中加载的时候就是使用 app/zhiliao.jpg ,这样就可以避免产生混淆。)
如果有一些静态文件是不和任何 app 挂钩的。那么可以在 settings.py 中添加 STATICFILES_DIRS ,以后 DTL 就会在这个列表的路径中查找静态文件。
设置默认查找静态文件的路径为:
STATICFILES_DIRS = [os.path.join(BASE_DIR,"static")]
在模版中使用 load 标签加载 static 标签。比如要加载在项目的 static 文件夹下的 style.css 的文件。那么示例代码如下:
{% load static %}
<link rel="stylesheet" href="{% static 'style.css' %}">
from django.db import models
#Create your models here.
#如果将一个普通的类变成一个可以映射到数据库中的orm模型,那么必须要将父类设置为models。model或者它的子类
class Book(models.Model):
#1. id :int 自然增长
id=models.AutoField(primary_key=True)
#2.name varchar 100
name=models.CharField(max_length=100,null=False)
#3 author varchar 100
author=models.CharField(max_length=100,null=False)
#4 price float
price=models.FloatField(null=False,default=0)
#生成迁移脚本文件 #
python manage.py makemigrations
#将生成的脚本映射到数据库中
python manage.py migrate
ORM增删改查
views:
from django.shortcuts import render
from .models import Book
from django.http import HttpResponse
#Create your views here.
def index(request):
#使用ORM添加一条数据 #
book=Book(name='西游记',author='吴承恩',price=2100)
book.save()
#根据主键查询
book=Book.objects.get(pk=1)
print(book)
#根据其他条件查询 #
books=Book.objects.filter(name='西游记').first()
print(books)
#删除数据 #
books=Book.objects.get(pk=1)
books.delete()
#修改某条数据
books=Book.objects.get(pk=2)
books.price=300
books.save()
return HttpResponse('数据添加成功')
#配置URL urlpatterns = [ path(’’, views.index,name=‘index’), ]
访问127.0.0.1:8000访问即可
#所有查询的动作都是通过使用模型的OBJEXTS来完成的