Django基础


Django概念

优点

Django的主要目的是简便、快速的开发数据库驱动的网站。它强调代码复用,多个组件可以很方便的以”插件”形式服务于整个框架,Django有许多功能强大的第三方撬件,你甚至可以很方便的开发出自己的工具包。这使得Django具有很强的可扩展性。它还强调快速开发和DRY(DoNotRepeatYourself)原则。

对比Flask框架,Django原生提供了众多的功能组件,让开发更简便快速。

  • 提供项目工程管理的自动化脚本工具
  • 数据库更RM支持(对象奂系映射,英语: Object Relational Mapping )
  • 模板
  • 表单
  • Admin管理站点
  • 文件管理
  • 认证权限
  • session机制
  • 缓存

MVC设计模式

后端服务器被分为M、V、C三个部分

M全拼为Model,主要封装对数据车层的访问,对数据库中的数据进行增、删、改、查操作。 V全拼为View,用于封装结果,生成页面展示的html内容。 C全拼为Controller↑用于接收请求↑处理业务逻辑,与Model和View交互:返回结果。

MVC处理过程

首先前端发送请求到后端服务器

后端服务器的Controller部分接收请求,并业务处理(如密码强度验证,身份认证….登陆操作)

如业务逻辑需要操作数据库,那么就去Model部分,Model作为数据库和Controller的中介,去请求数据库。

数据库返回结果给Model,Model将结果返回给Controller

Controller再将业务处理后的结果返回给View部分,View将要渲染的结果返回给Controller

Controller将结果渲染到前端

MVT设计模式

M全拼为Model,与MVC中的M功能相同,负责和数据库交互,进行数据处理。 V全拼为View,与MVC中的C功能相同,接收请求,进行业务处理,返回应答● T全拼为Template↑与MVC中的V功能相同↑负责封装构造要返回的html。

创建Django项目

创建项目

django-admin startpeoject application
cd application

目录结构│ manage.py

└─application
      asgi.py
      settings.py
      urls.py
      wsgi.py
      __init__.py

  • manager:管理工具(例如创建子应用)
  • settings:设置相关
  • urls:路由相关
  • usgi:程序入口

启动项目

python manage.py runserver

使用其他端口启动(默认8000)python manage.py runserver 127.0.0.1:8001

查看帮助

python manager.

创建子应用

创建

python manage.py startapp login

子应用目录结构│ manage.py

├─application
│ │ asgi.py
│ │ settings.py
│ │ urls.py
│ │ wsgi.py
│ │ __init__.py
│ │
│ └─__pycache__
│         settings.cpython-39.pyc
│         __init__.cpython-39.pyc

└─login
  │ admin.py
  │ apps.py
  │ models.py
  │ tests.py
  │ views.py
  │ __init__.py
  │
  └─migrations
          __init__.py

  • views:视图相关
  • tests:测试相关
  • models:模型相关
  • migrations:迁移相关
  • admin:后台相关
  • apps:当前子应用相关

在settings.py中注册app

INSTALLED_APPS = [
  ‘django.contrib.admin’,
  ‘django.contrib.auth’,
  ‘django.contrib.contenttypes’,
  ‘django.contrib.sessions’,
  ‘django.contrib.messages’,
  ‘django.contrib.staticfiles’,
  ‘login.apps.LoginConfig’ # 自动生成的Config信息
]

  • 子应用名
  • 子应用名.apps.子应用名Config

Django数据库开发

数据库开发的提示

  • IVT设计模式中的Mode1, 专门负责和数据库交互对应(models.py)
  • 由于Model 中内嵌了ORM框架,所以不需要直接面向数据库编程.
  • 而是定义模型类,通过模型类和对象完成数据库表的增删改查
  • ORM框架就是把数据库表的行与相应的对象建立矣联,互相转换使得数据库的操作面向对象

数据库开发的步骤

1.定义模型类 2.模型迁移 3.操作数据库

在ORM框架中,Python中的类对应于数据表,类属性对应于字段,对象对应于数据行

模型定义

  1. 主键id会自动生成,无需自己定义

class account(models.Model):
  name = models.CharField(max_length=20)

  def __str__(self):
      return self.name

模型的类型

模型字段参考 | Django 文档 | Django (djangoproject.com)

字段参数

  • null:(bool类型)是否可以为空
  • max_length:CharField必须有的属性
  • unique:是否唯一
  • default:设置默认值
  • verbose_name:后台可视化的名字

修改默认表名

from django.db import models

# Create your models here.
class account(models.Model):
  name = models.CharField(max_length=20)

  # 修改默认表名
  class Meta:
      db_table = “account_info”

  def __str__(self):
      return self.name

定义候选值

顾名思义,只能在给定的值中选择

使用有序字典from django.db import models

# Create your models here.
class account(models.Model):
  name = models.CharField(max_length=20)
  role = (
      (0,”man”),
      (1,’wuman’)
  )
  gender = models.SmallIntegerField(choices=role)
  # 修改默认表名
  class Meta:
      db_table = “account_info”

  def __str__(self):
      return self.name

外键

book = model.ForeignKey(Bookinfo) # 参数内容为外键具体的类

在设置外键时,需要通过on_ delete选项指明主表删除数据时,对于外键引用表数据如何处理,在django.db.models中包含了可选常量:

  • CASCADE级联删除主表数据时连通一起删除外键表中数据
  • PROTECT保护,通过抛出ProtectedError异常;来阻止删除主表中被外键应用的数据
  • SET_NULL设置为NULL,仅在该字段null=True允许为nul时可用
  • SET_DEFAULT设置为默认值,仅在该字段设置了默认值时可用
  • SET()设置为特定值或者调用特定方法
  • DO_NOTHING不做任何操作,如果数据库前置指明级联性,此选项会抛出IntegrityError异常

数据迁移

配置数据库

在settings.py中配置数据库信息DATABASES = {
  ‘default’: {
      ‘ENGINE’: ‘django.db.backends.sqlite3’,
      ‘NAME’: BASE_DIR / ‘db.sqlite3’,
  }
}

默认sqlite3

修改为MySQL

安装pymysql

pip install pymysql

修改settingsDATABASES = {
  ‘default’: {
      ‘ENGINE’: ‘django.db.backends.mysql’,
      ‘NAME’: BASE_DIR / ‘db.sqlite3’,
  }
}

修改子程序的__init__文件,引入mysqlimport pymysql
pymysql.install_as_MySQLdb()

修改数据库配置信息DATABASES = {
  ‘default’: {
      ‘ENGINE’: ‘django.db.backends.mysql’,
      ‘HOST’:’127.0.0.1′,
      ‘PORT’:’3306′,
      ‘USER’:’root’,
      ‘PASSWORD’:”,
      ‘NAME’:’test_django’ #数据库名
  }
}

随后生成迁移文件,并迁移

生成迁移文件

python manage.py makemigrations

此时会在app目录中的migrations中创建文件

对应数据库中生成表

python manage.py migrate

此时会在数据库中生成数据表

新增数据

方法一:先创建后保存

使用Django的shell进行数据添加

先写好代码from login.models import account
ac = account(
  name=”abcdefg”
)
ac.save()

再运行DjangoShell,粘贴代码,可以看到数据添加成功

因为我们的model已经继承了models.Model类,所以包含增删改查的方法

方法二:直接入库

objects为模型的管理类,可以利用它来增删改查from login.models import account
account.objects.create(
  name=”defgaioj”
)

再用Shell运行代码

更新数据

方法一:先查后改

先查询数据from login.models import account
ac = account.objects.get(id=1)

再更新数据# 修改实例属性
ac.name=’小智’
ac.save()

方法二:直接修改

from login.models import account
account.objects.first(name=’小智’).update(
  name=’新小智’
)

可以修改一个属性,也可以修改多个属性

删除数据

方式一:先查后删

from login.models import account
ac = account.objects.get(id=1)
ac.delete()

方式二:直接删除

from login.models import account
account.objects.filter(name=”新小智”).delete()

查询数据

基本查询

from login.models import account
account.objects.get(id=1)

如果id不存在,会抛出异常account.objects.get(id=100)

需要try一下from login.models import account
try:
  account.objects.get(id=1)
except account.DoesNotExist as e:
  print(e)

获取所有数据

from login.models import account
account.objects.all()

计数查询

account.objects.all().count()

或者account.objects.count()

过滤查询

filter

筛选、过滤,返回n(n>=0)个结果,返回列表account.objects.filter(字段名__运算符=值)

查询书名包含’智’的账户account.objects.filter(name__contains=”智”)

查询书名以:“i”结尾的账户account.objects.filter(name__endwith=”i”)

查询书名为空的账户account.objects.filter(name__isnull=True)

查询编号为1或3或5的账户account.objects.filter(id__in=[1,3,5])

查询编号大于3的账户account.objects.filter(id__gt=3)

  • gt:大于
  • gte:大于等于
  • lt:小于
  • lte:小于等于

查询1988年注册的账户account.objects.filter(date__year=’1988′)

查询1990年1月1日后注册的账户account.objects.filter(date__gt=’1990-1-1′)

时间格式必须是YYYY-MM-DD

get

返回一个结果

查询编号为1的账户account.objects.get(id__exact=1)

  • exact表示准确的、确切的

相当于account.objects.get(id=1)

exclude

排除符合条件后剩下的结果,返回列表

查询id不为1的用户account.objects.exclude(id__exact=3)

F对象

语法格式filter(字段名__运算符=F(‘字段名’))

当两个属性相比较的时候,需要用到F对象

查询体重大于等于年龄的账户。account.objects.filter(weight__gte=F(‘age’))

查询体重大于等于年龄2倍的账户。account.objects.filter(weight__gte=F(‘age’)*2)

Q对象(与、或、非)

当两个条件需要同时满足时,如

查询id大于2并且体重大于20的账户

方式1account.objects.filter(id__gt=2).filter(weight__gt=20)

方式2account.objects.filter(id__gt=2,weight__gt=20)

但是两个条件满足一个即可时,需要使用Q对象

语法格式Q(字段名__运算符=值)
逻辑运算:
与:Q()&Q()
或:Q()|Q()
非:~Q()

查询id大于2或者体重大于20的账户from django.db.models import Q
account.objects.filter(Q(id__gt=2)|Q(weight__gt=20))

查询id不-等于2的账户# 方式一
account.objects.exclude(id=3)
# 方式二
account.objects.filter(~Q(id=3))

聚合函数

常用的聚合函数有

  • Sum
  • Max
  • Min
  • Avg
  • Count

聚合函数需要使用aggragte

语法格式aggragte(聚合函数名(字段名))from django.db.models import Max,Min,Avg,Count,Sum
account.objects.aggregate(Min(‘id’))

排序

account.objects.all().order_by(‘id’)

默认升序account.objects.all().order_by(‘-id’) # 降序

基本关联查询

一对多查询

假设人物表People中对应书籍Book,一个人物对应多个书籍,书籍中不包含人物字段

需求如下:

查询书籍为1的所有人物信息book = BookInfo.objects.get(id=1)
# 调用关联模型(系统自动生成)
book.peopleinfo_set.all()

多对一查询

查询书籍为1的所有人物信息查询人物为1的书籍信息person = PeopleInfo.objects.get(id=1)
person.book # 实例对象,人物表中包含书籍字段

语法格式主表模型(实例对象).关联模型类名小写_set.all()
从表模型(实例对象) .外键

关联查询筛选

一对多

语法格式filter(关联模型类名小写__字段__运算符=值)

查询图书,要求图书人物为郭靖”Book.objects.filter(People__name__exact=‘啊大大’)

或者Book.objects.filter(People__name=’add’)

查询图书,要求图书中人物的描述包合”八”Book.objects.filter(People__describ__contains=”八”)

多对一

语法格式filter(外键__字段__运算符=值)

查询书名为“天龙八部”的所有人物Book.objects.filter(People__name=”天龙八部”)

查询图书阅读量大于30的所有人物Book.objects.filter(readcount__gt=30)

查询结果集

惰性执行

查询集,也称查询结果集、QuerySet,表示从数据库中获取的对象集合。

调用以下函数时,会返回查询集(而不是列表)

  • all
  • filter
  • exclude
  • order_by

两大特性

创建查询集不会访问数据库,直到调用数据时才会访问数据库,调用数据的情况包括迭代、序列化、与if合

例如,当执行如下语句时; 并未进行数据库查询,只是创建了一个查询集booksbooks = Bookinfo.objects.all()

继续执行逼历迭代操作后,才真正的进行了数据库的查询for book in books:
print(book.name)

缓存

配置MySQL日志

MySql数据库日志配置sudo vim /etc/mysqL/mysql.conf.d/mysqld.conf

修改为1general = 1

重启sudo service mysql restart

查看日志tail -f /var/log/mysql/mysql.log

使用同一个查询集,第一次使用时会发生数据库的查询,然后Django会把结果缓存下来,再次使用这个查询集时会使用缓存的数据减少了数据库的查询次数。

情况一: 如下是两个查询集,无法重用缓存,每次查询都会与数据库进行一次交互,增加了数据库的负裁。[book.id for book in Book.objects.all()]
[book.id for book in Book.objects.all()]
[book.id for book in Book.objects.all()]

优化缓存后books = Book.objects.all()
[book.id for book in books]
[book.id for book in books]
[book.id for book in books]

优化后只会查询一次数据库

限制查询集

使用列表切片来限制查询集,不支持负索引

分页查询

from django.core import Paginator
books = Book.objects.all()
p = Paginator(books,2) # 每页2个元素
book_page = p.page(1) # 第一个元素

Django自带后台管理系统

输入http://127.0.0.1:8000/admim

跳转至http://127.0.0.1:8000/admin/login/?next=/admin/

修改配置

在settings.py中修改,将站点语言改为中文LANGUAGE_CODE = ‘en-us’

改为LANGUAGE_CODE = ‘zh-Hans’

时区修改TIME_ZONE = ‘UTC’

改为TIME_ZONE = ‘Asia/Shanghai’

创建超级管理员账户

python manage.py createsuperuser

image-20220330191444033

此时需要在app的admin中注册我们的模型,以便后台可以管理数据from django.contrib import admin
#导入模型类
from login.models import account

# Register your models here.
# 注册模型
admin.site.register(account)

后台可以看到数据了

image-20220330193302540

为了能让数据更具体,需要区对应的model中写构造函数from django.db import models

# Create your models here.
class account(models.Model):
name = models.CharField(max_length=20)

def __str__(self):
return self.name

Django视图View

所谓视图就是函数

函数的第一个参数是请求,是HttpRequest的实例对象

而函数的返回值就是HttpResponse的实例对象,指响应from django.shortcuts import render
# 导入请求、响应类
from django.http import HttpRequest,HttpResponse
# Create your views here.
# 视图就是函数

def index(req):
”’
req:第一个参数是HttpRequest的实例对象,是指请求
”’
return HttpResponse(“index”)

URL匹配(路由)

我们通过浏览器请求一个页面的时候

首先会通过设置在settings的

ROOT_URLCONF = ‘application.urls’

获取到路由的入口

默认是应用名称.urls

path

from django.urls import include,path

再来到urls中

  • urlpatterns是固定写法,值是个列表
  • 在浏览器中输入的路径会顺次匹配,如果匹配成功,会直接引导至相应的模块,如果匹配不成功,则返回404
  • 在url中,IP:端口号以及参数都不参与正则匹配
  • 如果匹配成功,则进入子应用的urlpatterns中继续进行匹配
  • 如果匹配不成功,则终止匹配

urlpatterns = [
path(‘admin/’, admin.site.urls),
]

工程下的urlsurlpatterns = [
path(‘admin/’, admin.site.urls),
path(”, include(‘login.urls’)),
]

子应用login.urlsfrom django.urls import path,include
from login.views import index
urlpatterns = [
path(‘index/’,index)
]

匹配过程:首先请求http://127.0.0.1:8000/index/

会到第二个‘’中,将所有的请求转入log.urls

再匹配到第一项index/

re_path

from django.urls import include,re_path

其中数据元素的规则如下

  • r是指不进行转义
  • ^表示严格的开始
  • $表示严格的结束

上面的url如果使用re_path,则为urlpatterns = [
path(‘admin/’, admin.site.urls),
re_path(r’^’,include(‘login.urls’)),
]urlpatterns = [
re_path(r’^index/$’,index)
]

效果是一样的

Django模板Template

创建模板文件夹

image-20220330203447628

Seetings中关于模板的配置

TEMPLATES = [ { ‘BACKEND’: ‘django.template.backends.django.DjangoTemplates’, ‘DIRS’: [], ‘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’, ], }, }, ]

修改为TEMPLATES = [
{
‘BACKEND’: ‘django.template.backends.django.DjangoTemplates’,
‘DIRS’: [BASE_DIR/’template’],
‘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’,
],
},
},
]

在子应用的views中调用render函数,渲染页面def index(req):
”’
req:第一个参数是HttpRequest的实例对象,是指请求
”’
# 参数为:请求,模板名称
return render(req,’index.html’)

render的第一个参数是请求,第二个参数是模板名称,第三个参数为请求参数内容def index(req):
”’
req:第一个参数是HttpRequest的实例对象,是指请求
”’
name = ‘小智’
context = {
“name”:name
}
# 参数为:请求,模板名称
return render(req,’index.html’,context=context)

在页面中调用插值表达式进行显示<!DOCTYPE html>
<html lang=”zh”>
<head>
<meta charset=”UTF-8″>
<title>Title</title>
</head>
<body>
<h>Hello World {{ name }}</h>
</body>
</html>

后台返回数据给前端显示

首先到views里面,从ORM中获取到数据

并返回HttpResponse的context到前端from django.shortcuts import render
# 导入请求、响应类
from django.http import HttpRequest,HttpResponse
# Create your views here.

# 导入模型类
from login.models import account

# 视图就是函数
def index(req):
”’
req:第一个参数是HttpRequest的实例对象,是指请求
”’

# 获取全部数据
accounts = account.objects.all()
# 构造返回数据
context = {
“accounts”:accounts
}
# 参数为:请求,模板名称
return render(req,’index.html’,context=context)

  • 引入模型类
  • 获取模型对应的所有数据
  • 构造返回数据
  • 通过HttpResponse返回数据到模板

再在模板中调用模板语法来遍历返回的数据<!DOCTYPE html>
<html lang=”zh”>
<head>
<meta charset=”UTF-8″>
<title>Title</title>
</head>
<body>
<h>Hello World</h>
<ul>
{% for account in accounts %}
<li>{{ account.name }}</li>
{% endfor %}
</ul>
</body>
</html>

静态资源配置

新建静态资源文件夹

配置静态资源文件夹位置STATICFILES_DIRS = [
BASE_DIR/’static’
]

这个配置是指css、js等静态文件在这个目录里STATIC_URL = ‘static/’

这个配置是指在请求static这个url的时候,可以访问到静态资源

App相关配置

首先确保在settings中的INSTALLED_APPS中引入了子应用的配置INSTALLED_APPS = [
‘login.apps.LoginConfig’
]

这样配置才会生效

其次,需要在配置中添加配置项from django.apps import AppConfig

class LoginConfig(AppConfig):
default_auto_field = ‘django.db.models.BigAutoField’
name = ‘login’
# 模型命名
verbose_name = “后台相关”

添加后可以看到,由

image-20220331131720576

变为了

image-20220331131734030

DjangoShell

python manage.py shell

实现命令行式编程

数据的增删改查可以通过Shell也可以通过代码实现

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇