说明
1 2 C:\Users\Administrator>python --version Python 3.7.9
创建项目
1 C:\Users\Administrator>python -m pip install Django
1 2 3 4 5 python >>> import django >>> django.get_version() '3.1.3'
1 E:\proj>django-admin startproject StudyDjango
1 2 3 4 5 6 7 8 9 E:\proj\StudyDjango>tree /f │ manage.py │ └─StudyDjango asgi.py settings.py urls.py wsgi.py __init__.py
1 E:\proj\StudyDjango>python manage.py runserver 0.0.0.0:8000
视图和 URL 配置 在先前创建的 StudyDjango
目录下的 StudyDjango
目录新建一个 views.py
文件,并输入代码:
1 2 3 4 5 6 //StudyDjango/StudyDjango/views.py 文件代码: from django.http import HttpResponse def hello(request): return HttpResponse("Hello world ! ")
接着,绑定 URL 与视图函数。打开 urls.py
文件,删除原来代码,将以下代码复制粘贴到 urls.py
文件中:
1 2 3 4 5 6 7 8 // StudyDjango/StudyDjango/urls.py from django.conf.urls import url from . import views urlpatterns = [ url(r'^$', views.hello), ]
完成后,启动 Django 开发服务器,并在浏览器访问打开浏览器并访问:
我们也可以修改以下规则:
1 2 3 4 5 6 7 8 9 10 11 // StudyDjango/StudyDjango/urls.py from django.conf.urls import url from django.urls import path from . import views urlpatterns = [ # url(r'^$', views.hello), path('hello/', views.hello), ]
通过浏览器打开 http://127.0.0.1:8000/hello
,输出结果如下:
模板
1 2 3 // StudyDjango/templates/runoob.html <h1>{{ hello }}</h1>
接下来我们需要向Django说明模板文件的路径,修改HelloWorld/settings.py
,修改 TEMPLATES 中的 DIRS 为 [os.path.join(BASE_DIR, 'templates')]
,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 // StudyDjango/StudyDjango/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', ], }, }, ]
我们现在修改 views.py,增加一个新的对象,用于向模板提交数据:
1 2 3 4 5 6 7 8 // StudyDjango/StudyDjango/views.py from django.shortcuts import render def runoob(request): context = {} context['hello'] = 'Hello World!' return render(request, 'runoob.html', context)
1 2 3 4 5 6 7 8 9 10 11 12 13 // StudyDjango/StudyDjango/urls.py from django.urls import path from . import views urlpatterns = [ # url(r'^$', views.hello), # path('hello/', views.hello), path('runoob/', views.runoob), ]
模型
1 E:\proj\StudyDjango>pip3 install pymysql
本地需要搭建好Mysql环境
Django ORM
本地数据库中需要提前创建数据库,因为ORM 无法操作到数据库级别,只能到表。
使用heidisql连接本地mysql数据库后,新建一个数据库,名称为:runoob
我们在项目的 settings.py 文件中找到 DATABASES 配置项,将其信息修改为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 // StudyDjango/StudyDjango/settings.py DATABASES = { # 'default': { # 'ENGINE': 'django.db.backends.sqlite3', # 'NAME': BASE_DIR / 'db.sqlite3', # } 'default': { 'ENGINE': 'django.db.backends.mysql', # 数据库引擎 'NAME': 'runoob', # 数据库名称 'HOST': '127.0.0.1', # 数据库地址,本机 ip 地址 127.0.0.1 'PORT': 3306, # 端口 'USER': 'root', # 数据库用户名 'PASSWORD': '123456', # 数据库密码 } }
在与 settings.py
同级目录下的 __init__.py
中引入模块和进行配置
1 2 3 4 // StudyDjango/StudyDjango/__init__.py import pymysql pymysql.install_as_MySQLdb()
定义模型 创建APP
Django 规定,如果要使用模型,必须要创建一个 app。我们使用以下命令创建一个 TestModel 的 app:
1 E:\proj\StudyDjango>django-admin startapp TestModel
我们修改 TestModel/models.py
文件,代码如下:
1 2 3 4 5 6 from django.db import models class Test(models.Model): name = models.CharField(max_length=20)
以上的类名代表了数据库表名(test),且继承了models.Model,类里面的字段代表数据表中的字段(name),数据类型则由CharField(相当于varchar)、DateField(相当于datetime), max_length 参数限定长度。
接下来在 settings.py 中找到INSTALLED_APPS这一项,如下:
1 2 3 4 5 6 7 8 9 10 11 // StudyDjango\StudyDjango\settings.py INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'TestModel', # 添加此项 )
1 2 3 4 5 E:\proj\StudyDjango>python manage.py migrate File "D:\app\Python37\lib\site-packages\django\db\backends\mysql\base.py", line 36, in <module> raise ImproperlyConfigured('mysqlclient 1.4.0 or newer is required; you have %s.' % Database.__version__) django.core.exceptions.ImproperlyConfigured: mysqlclient 1.4.0 or newer is required; you have 0.10.1.
1 2 3 4 5 6 E:\proj\StudyDjango> python manage.py migrate # 创建表结构 E:\proj\StudyDjango> python manage.py makemigrations TestModel # 让 Django 知道我们在我们的模型有一些变更 E:\proj\StudyDjango> python manage.py migrate TestModel # 创建表结构
数据库操作 操作模型 新增数据 1 2 3 4 5 6 7 8 9 10 11 // StudyDjango/StudyDjango/testdb.py from django.http import HttpResponse from TestModel.models import Test # 数据库操作 def testdb(request): test1 = Test(name='runoob') test1.save() return HttpResponse("<p>数据添加成功!</p>")
下来我们在 StudyDjango目录中添加 testdb.py 文件到urls.py中
1 2 3 4 5 6 7 8 9 10 11 from django.urls import path from . import views,testdb urlpatterns = [ # url(r'^$', views.hello), # path('hello/', views.hello), path('runoob/', views.runoob), path('testdb/', testdb.testdb), ]
访问 http://127.0.0.1:8000/testdb
就可以看到数据添加成功的提示。
查询数据 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 from django.http import HttpResponse from TestModel.models import Test # 数据库操作 def testdb(request): # 初始化 response = "" response1 = "" # 通过objects这个模型管理器的all()获得所有数据行,相当于SQL中的SELECT * FROM list = Test.objects.all() # filter相当于SQL中的WHERE,可设置条件过滤结果 response2 = Test.objects.filter(id=1) # 获取单个对象 response3 = Test.objects.get(id=1) # 限制返回的数据 相当于 SQL 中的 OFFSET 0 LIMIT 2; Test.objects.order_by('name')[0:2] #数据排序 Test.objects.order_by("id") # 上面的方法可以连锁使用 Test.objects.filter(name="runoob").order_by("id") # 输出所有数据 for var in list: response1 += var.name + " " response = response1 return HttpResponse("<p>" + response + "</p>")
更新 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 from django.http import HttpResponse from TestModel.models import Test # 数据库操作 def testdb(request): # 修改其中一个id=1的name字段,再save,相当于SQL中的UPDATE test1 = Test.objects.get(id=1) test1.name = 'Google' test1.save() # 另外一种方式 #Test.objects.filter(id=1).update(name='Google') # 修改所有的列 # Test.objects.all().update(name='Google') return HttpResponse("<p>修改成功</p>")
删除 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 from django.http import HttpResponse from TestModel.models import Test # 数据库操作 def testdb(request): # 删除id=1的数据 test1 = Test.objects.get(id=1) test1.delete() # 另外一种方式 # Test.objects.filter(id=1).delete() # 删除所有数据 # Test.objects.all().delete() return HttpResponse("<p>删除成功</p>")
路由
Django 项目里多个app目录共用一个 urls 容易造成混淆,后期维护也不方便
在项目名(TestModel)中新增一个 TestModel/urls.py
1 2 3 4 5 6 7 8 from django.urls import path,re_path from django.conf.urls import url from TestModel import views # 从自己的 app 目录引入 views urlpatterns = [ url(r'^userAdd/', views.userAdd), path('userQuery/', views.userQuery), ]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 from django.http import HttpResponse from django.shortcuts import render # Create your views here. from TestModel.models import Test def userAdd(request): test1 = Test(name='runoob') test1.save() return HttpResponse("<p>数据添加成功!</p>") def userQuery(request): # 初始化 response = "" response1 = "" # 通过objects这个模型管理器的all()获得所有数据行,相当于SQL中的SELECT * FROM list = Test.objects.all() # filter相当于SQL中的WHERE,可设置条件过滤结果 response2 = Test.objects.filter(id=1) # 获取单个对象 response3 = Test.objects.get(id=1) # 限制返回的数据 相当于 SQL 中的 OFFSET 0 LIMIT 2; Test.objects.order_by('name')[0:2] # 数据排序 Test.objects.order_by("id") # 上面的方法可以连锁使用 Test.objects.filter(name="runoob").order_by("id") # 输出所有数据 for var in list: response1 += var.name + " " response = response1 return HttpResponse("<p>" + response + "</p>")
StudyDiango/StudyDiango/urls.py
中引用具体项目的url
1 2 3 4 5 6 7 8 9 10 11 12 13 from django.conf.urls import url from django.urls import path, include from . import views,testdb urlpatterns = [ # url(r'^$', views.hello), # path('hello/', views.hello), path('runoob/', views.runoob), path('testdb/', testdb.testdb), path('testModel/', include("TestModel.urls")), ]
浏览器打开http://127.0.0.1:8000/testModel/userQuery/
ORM多表实践 表结构 书籍表 Book :title 、 price 、 pub_date 、 publish(外键,多对一) 、 authors(多对多)
出版社表 Publish :name 、 city 、 email
作者表 Author :name 、 age 、 au_detail(一对一)
作者详情表 AuthorDetail :gender 、 tel 、 addr 、 birthday
创建模型 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 class Book(models.Model): title = models.CharField(max_length=32) price = models.DecimalField(max_digits=5, decimal_places=2) pub_date = models.DateField() # 关联出版社一对多,意思就是一个出版社可以有印刷多本书 publish = models.ForeignKey("Publish", on_delete=models.CASCADE) # 多对多,意思就是多个作者可以编写多本书 authors = models.ManyToManyField("Author") class Publish(models.Model): name = models.CharField(max_length=32) city = models.CharField(max_length=64) email = models.EmailField() class Author(models.Model): name = models.CharField(max_length=32) age = models.SmallIntegerField() # 一对一,意思为一个作者对应一个作者详情 au_detail = models.OneToOneField("AuthorDetail", on_delete=models.CASCADE) class AuthorDetail(models.Model): gender_choices = ( (0, "女"), (1, "男"), (2, "保密"), ) gender = models.SmallIntegerField(choices=gender_choices) tel = models.CharField(max_length=32) addr = models.CharField(max_length=64) birthday = models.DateField()
1 2 E:\proj\StudyDjango> python manage.py makemigrations TestModel # 让 Django 知道我们在我们的模型有一些变更 E:\proj\StudyDjango> python manage.py migrate TestModel # 创建表
注意testmode_book_authors 为book多对多authors的表
插入数据 1 2 3 4 5 6 7 8 # 插入出版社 insert into testmodel_publish(name,city,email) values ("华山出版社", "华山", "hs@163.com"), ("明教出版社", "黑木崖", "mj@163.com") # 先插入 authordetail 表中多数据 insert into testmodel_authordetail(gender,tel,addr,birthday) values (1,13432335433,"华山","1994-5-23"), (1,13943454554,"黑木崖","1961-8-13"), (0,13878934322,"黑木崖","1996-5-20") # 再将数据插入 author,这样 author 才能找到 authordetail insert into testmodel_author(name,age,au_detail_id) values ("令狐冲",25,1), ("任我行",58,2), ("任盈盈",23,3)
ORM添加数据 一对多(外键 ForeignKey) 方式一: 传对象的形式,返回值的数据类型是对象,书籍对象。
步骤:
a. 获取出版社对象
b. 给书籍的出版社属性 pulish 传出版社对象
1 2 3 4 5 6 7 8 9 // testmode/views.py def add_book(request): # 获取出版社对象 pub_obj = models.Publish.objects.filter(pk=1).first() # 给书籍的出版社属性publish传出版社对象 book = models.Book.objects.create(title="菜鸟教程", price=200, pub_date="2010-10-10", publish=pub_obj) print(book, type(book)) return HttpResponse(book)
方式二 : 传对象 id 的形式(由于传过来的数据一般是 id,所以传对象 id 是常用的)。
一对多中,设置外键属性的类(多的表)中,MySQL 中显示的字段名是:外键属性名_id 。
返回值的数据类型是对象,书籍对象。
步骤:
a. 获取出版社对象的 id
b. 给书籍的关联出版社字段 pulish_id 传出版社对象的 id
1 2 3 4 5 6 7 8 9 def add_book(request): # 获取出版社对象 pub_obj = models.Publish.objects.filter(pk=1).first() # 获取出版社对象的id pk = pub_obj.pk # 给书籍的关联出版社字段 publish_id 传出版社对象的id book = models.Book.objects.create(title="冲灵剑法", price=100, pub_date="2004-04-04", publish_id=pk) print(book, type(book)) return HttpResponse(book)
testmodel/urls.py
引用views.py
代码
1 2 3 4 5 6 7 8 9 from django.urls import path,re_path from django.conf.urls import url from TestModel import views # 从自己的 app 目录引入 views urlpatterns = [ url(r'^userAdd/', views.userAdd), path('userQuery/', views.userQuery), path('add_book/', views.add_book), ]
多对多(ManyToManyField):
方式一: 传对象形式,无返回值。
步骤:
a. 获取作者对象
b. 获取书籍对象
c. 给书籍对象的 authors 属性用 add 方法传作者对象
1 2 3 4 5 6 7 8 9 10 def add_books(request): # 获取作者对象 chong = models.Author.objects.filter(name="令狐冲").first() ying = models.Author.objects.filter(name="任盈盈").first() # 获取书籍对象 book = models.Book.objects.filter(title="菜鸟教程").first() # 给书籍对象的 authors 属性用 add 方法传作者对象 # 菜鸟教程这本书有两个作者 book.authors.add(chong, ying) return HttpResponse(book)
方式二: 传对象id形式,无返回值。
步骤:
a. 获取作者对象的 id
b. 获取书籍对象
c. 给书籍对象的 authors 属性用 add 方法传作者对象的 id
1 2 3 4 5 6 7 8 9 def add_books_1(request): # 获取作者对象 chong = models.Author.objects.filter(name="令狐冲").first() # 获取作者对象的id pk = chong.pk # 获取书籍对象 book = models.Book.objects.filter(title="冲灵剑法").first() # 给书籍对象的 authors 属性用 add 方法传作者对象的id book.authors.add(pk)
关联管理器(对象调用) 前提:
多对多(双向均有关联管理器)
一对多(只有多的那个类的对象有关联管理器,即反向才有)
语法格式:
1 2 正向:属性名,如add,create等 反向:小写类名加 _set
一对多只能反向
add 。用于多对多,把指定的模型对象添加到关联对象集(关系表)中。
1 2 3 4 5 6 7 # 方式一:传对象 book_obj = models.Book.objects.get(id=10) author_list = models.Author.objects.filter(id__gt=2) book_obj.authors.add(*author_list) # 将 id 大于2的作者对象添加到这本书的作者集合中 # 方式二:传对象 id book_obj.authors.add(*[1,3]) # 将 id=1 和 id=3 的作者对象添加到这本书的作者集合中 return HttpResponse("ok")
1 2 3 4 ying = models.Author.objects.filter(name="任盈盈").first() book = models.Book.objects.filter(title="冲灵剑法").first() ying.book_set.add(book) return HttpResponse("ok")
create :创建一个新的对象,并同时将它添加到关联对象集之中。
1 2 3 4 5 pub = models.Publish.objects.filter(name="明教出版社").first() wo = models.Author.objects.filter(name="任我行").first() book = wo.book_set.create(title="吸星大法", price=300, pub_date="1999-9-19", publish=pub) print(book, type(book)) return HttpResponse("ok")
remove :从关联对象集中移除执行的模型对象。
1 2 3 4 author_obj =models.Author.objects.get(id=1) book_obj = models.Book.objects.get(id=11) author_obj.book_set.remove(book_obj) return HttpResponse("ok")
clear :从关联对象集中移除一切对象,删除关联,不会删除对象。
1 2 3 # 清空独孤九剑关联的所有作者 book = models.Book.objects.filter(title="菜鸟教程").first() book.authors.clear()
对于 ForeignKey 对象,这个方法仅在 null=True(可以为空)时存在。
ORM 查询 一对多 查询主键为 10 的书籍的出版社所在的城市(正向 )。
1 2 3 4 book = models.Book.objects.filter(pk=10).first() res = book.publish.city print(res, type(res)) return HttpResponse("ok")
1 2 3 4 5 6 pub = models.Publish.objects.filter(name="明教出版社").first() # pub.book_set.all():取出书籍表的所有书籍对象,在一个 QuerySet 里,遍历取出一个个书籍对象。 res = pub.book_set.all() for i in res: print(i.title) return HttpResponse("ok")
一对一 查询令狐冲的电话(正向 )
正向:对象.属性 (author.au_detail) 可以跳转到关联的表(作者详情表)
1 2 3 4 author = models.Author.objects.filter(name="令狐冲").first() res = author.au_detail.tel print(res, type(res)) return HttpResponse("ok")
查询所有住址在黑木崖的作者的姓名(反向 )。
1 2 3 4 addr = models.AuthorDetail.objects.filter(addr="黑木崖").first() res = addr.author.name print(res, type(res)) return HttpResponse("ok")
多对多
1 2 3 4 5 book = models.Book.objects.filter(title="菜鸟教程").first() res = book.authors.all() for i in res: print(i.name, i.au_detail.tel) return HttpResponse("ok")
1 2 3 4 5 author = models.Author.objects.filter(name="任我行").first() res = author.book_set.all() for i in res: print(i.title) return HttpResponse("ok")
基于双下划线的跨表查询 正向:属性名称__跨表的属性名称
反向:小写类名__跨表的属性名称
一对多 正向:查询菜鸟出版社出版过的所有书籍的名字与价格。
1 2 # publish__name 跨表中的name res = models.Book.objects.filter(publish__name="菜鸟出版社").values_list("title", "price")
反向:通过 小写类名__跨表的属性名称(book__title,book__price) 跨表获取数据。
1 2 res = models.Publish.objects.filter(name="菜鸟出版社").values_list("book__title","book__price") return HttpResponse("ok")
多对多 查询任我行出过的所有书籍的名字。
正向 :通过 属性名称__跨表的属性名称(authors__name) 跨表获取数据:
1 res = models.Book.objects.filter(authors__name="任我行").values_list("title")
反向 :通过 小写类名__跨表的属性名称(book__title) 跨表获取数据:
1 res = models.Author.objects.filter(name="任我行").values_list("book__title")
一对一 查询任我行的手机号。
正向 :通过 属性名称__跨表的属性名称(au_detail__tel) 跨表获取数据。
1 res = models.Author.objects.filter(name="任我行").values_list("au_detail__tel")
反向 :通过 小写类名__跨表的属性名称(author__name) 跨表获取数据。
1 res = models.AuthorDetail.objects.filter(author__name="任我行").values_list("tel")
总结
主要介绍了新建项目,应用,路由,连接数据库,对model进行增删改查等操作