目录
3. 编写视图文件:mydemo/myapp/views.py
Model是MVC框架中重要的一部分, 负责在数据库中存取数据
它实现了数据模型与数据库的解耦,即不需要依赖于特定的数据库
通过简单的配置就可以轻松更换数据库
在models.py中定义模型类,要求继承自models.Model(注意:
addtime=models.DateTimeField(default=datetime.now)在后面执行迁移文件可能会报错:
AttributeError: module 'datetime' has no attribute 'now'
需要改成addtime=models.DateTimeField(default=datetime.datetime.now()))
- from django.db import models
- from datetime import datetime
-
- # Create your models here.
- class Users(models.Model):
- #id = models.AutoField(primary_key=True) #主键可省略不写
- name = models.CharField(max_length=32)
- age = models.IntegerField(default=20)
- phone = models.CharField(max_length=16)
- addtime=models.DateTimeField(default=datetime.now)
- #class Meta:
- # db_table = "myapp_users" # 指定表名
把应用加入settings.py文件的installed_app项
编辑myweb/settings.py文件,并将项目应用文件名添加到该INSTALLED_APPS设置。
- INSTALLED_APPS = [
- 'django.contrib.admin',
- 'django.contrib.auth',
- 'django.contrib.contenttypes',
- 'django.contrib.sessions',
- 'django.contrib.messages',
- 'django.contrib.staticfiles',
- 'myapp', #或全称:myapp.apps.MyappConfig
- ]
生成迁移文件
- python3 manage.py makemigrations
-
- django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module: No mo
- dule named 'MySQLdb'.
- Did you install mysqlclient or MySQL-python?
- 安装上面"配置Mysql数据库"的第五步配置,或安装:pip install mysqlclient后就可以了
-
- 若执行python manage.py makemigrations命令(也可能人比较皮,把migrations文件夹给删了),会提示"No changes detected." 可能有用的解决方式如下:
-
- 先 python manage.py makemigrations --empty yourappname 生成一个空的initial.py
- 再 python manage.py makemigrations 生成原先的model对应的migration file
执行迁移
python3 manage.py migrate
使用模型类进行crud操作
- from django.shortcuts import render
- from django.http import HttpResponse
- from myapp.models import Users
- # Create your views here.
- def index(requeest):
- #添加操作
- ob = Users() #实例化一个新对象(空对象)
- ob.name = "张三"
- ob.age = 20
- ob.phone = '123456789'
- ob.save() #新对象就是添加,已存在对象则是修改
-
- #删除操作
- mod = Users.objects #获取users的model对象
- user = mod.get(id=1) #获取id值为1的数据信息
- print(user.name)
- user.delete()
-
- #修改操作
- ob = Users.objects.get(id=2)
- ob.name = "小刘"
- ob.age = 26
- ob.save()
-
- #数据查询
- mod = Users.objects #获取Users模型的model操作对象
- ulist = mod.all() #获取所有数据
- ulist = mod.filter(name='小刘') #获取name值为小刘的信息
- ulist = mod.filter(age=20) #获取所有age=20的信息
- ulist = mod.order_by("age") #按age升序排序
- ulist = mod.order_by("age")[:2] #按age升序排序,只获取前两条
- for u in ulist:
- print(u.id,u.name,u.age,u.phone,u.addtime)
- return HttpResponse("首页")
增删改查操作要一条一条的执行, 可以进行注释。
1.当前选择的数据库支持字段的类型
2.渲染管理表单时使用的默认html控件
3.在管理站点最低限度的验证
1.不能是Python的保留关键字
2.由于Django的查询方式,不允许使用连续的下划线
objects:是Manager类型的对象,用于与数据库进行交互
__str__(self):重写object方法,此方法在将对象转换成字符串时会被调用
save( ):将模型对象保存到数据表中
delete( ):将模型对象从数据表中删除
返回查询集的方法,称为过滤器
写法:
- filter(键1=值1,键2=值2)
- 等价于
- filter(键1=值1).filter(键2=值2)
返回单个值的方法
限制查询集
查询集返回列表,可以使用下标的方式进行限制,等同于sql中的limit和offset子句
注意:不支持负数索引
使用下标后返回一个新的查询集,不会立即执行查询
如果获取一个对象,直接使用[0],等同于[0:1].get(),但是如果没有数据,[0]引发IndexError异常,[0:1].get()引发DoesNotExist异常
- #这会返回前5个对象 LIMIT 5
- Entry.objects.all()[:5]
- #这将返回第六个到第十个对象 OFFSET 5 LIMIT 5
- Entry.objects.all()[5:10]
查询集的缓存
在新建的查询集中,缓存为空,首次对查询集求值时,会发生数据库查询,django会将查询的结果存在查询集的缓存中,并返回请求的结果,接下来对查询集求值将重用缓存的结果
情况一:这构成了两个查询集,无法重用缓存,每次查询都会与数据库进行一次交互,增加了数据库的负载
- print([e.title for e in Entry.objects.all()])
- print([e.title for e in Entry.objects.all()])
情况二:两次循环使用同一个查询集,第二次使用缓存中的数据
- querylist=Entry.objects.all()
- print([e.title for e in querylist])
- print([e.title for e in querylist])
何时查询集不会被缓存:当只对查询集的部分进行求值时会检查缓存,但是如果这部分不在缓存中,那么接下来查询返回的记录将不会被缓存,这意味着使用索引来限制查询集将不会填充缓存,如果这部分数据已经被缓存,则直接使用缓存中的数据
比较运算符
exact:表示判等,大小写敏感;如果没有写“ 比较运算符”,表示判等
filter(isDelete=False)
contains:是否包含,大小写敏感
exclude(btitle__contains='传')
startswith、endswith:以value开头或结尾,大小写敏感
exclude(btitle__endswith='传')
isnull、isnotnull:是否为null
filter(btitle__isnull=False)
在前面加个i表示不区分大小写,如iexact、icontains、istarswith、iendswith
in:是否包含在范围内
filter(pk__in=[1, 2, 3, 4, 5])
gt、gte、lt、lte:大于、大于等于、小于、小于等于
filter(id__gt=3)
year、month、day、week_day、hour、minute、second:对日期间类型的属性进行运算
- filter(bpub_date__year=1980)
- filter(bpub_date__gt=date(1980, 12, 31))
跨关联关系的查询:处理join查询
语法:模型类名 <属性名> <比较>
注:可以没有__<比较>部分,表示等于,结果同inner join
可返向使用,即在关联的两个模型中都可以使用
filter(heroinfo_ _hcontent_ _contains='八')
聚合函数
使用aggregate()函数返回聚合函数的值
函数:Avg,Count,Max,Min,Sum
- from django.db.models import Max
- maxDate = list.aggregate(Max('bpub_date'))
count的一般用法:
count = list.count() 进入数据库创建数据表:myapp_users
- CREATE TABLE `myapp_users` (
- `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
- `name` varchar(32) NOT NULL,
- `age` tinyint(3) unsigned NOT NULL DEFAULT '20',
- `phone` varchar(16) DEFAULT NULL,
- `addtime` datetime(6) NOT NULL,
- PRIMARY KEY (`id`)
- ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
添加几条测试数据
- # 创建项目框架mydemo
- $ django-admin startproject mydemo
-
- $ cd mydemo
-
- # 在项目中创建一个myapp应用
- $ python manage.py startapp myapp
-
- # 创建模板目录
- $ mkdir templates
- $ mkdir templates/myapp
-
- $ cd ..
-
- $ tree myweb
-
- mydemo
- ├── mydemo
- │ ├── __init__.py
- │ ├── settings.py
- │ ├── urls.py
- │ └── wsgi.py
- ├── manage.py
- ├── myapp
- │ ├── admin.py
- │ ├── apps.py
- │ ├── __init__.py
- │ ├── models.py
- │ ├── tests.py
- │ └── views.py
- └── templates
- └── myapp
- ...
- #配置自己的服务器IP地址
- ALLOWED_HOSTS = ['*']
-
- ...
- #添加自己应用
- INSTALLED_APPS = [
- 'django.contrib.admin',
- 'django.contrib.auth',
- 'django.contrib.contenttypes',
- 'django.contrib.sessions',
- 'django.contrib.messages',
- 'django.contrib.staticfiles',
- 'myapp',
- #或'myapp.apps.MyappConfig', #或者直接写 myapp
- ]
- ...
-
- # 配置模板路径信息
- 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',
- ],
- },
- },
- ]
-
-
- ...
- # 数据库连接配置
- DATABASES = {
- 'default': {
- 'ENGINE': 'django.db.backends.mysql',
- 'NAME': 'mytest',
- 'USER': 'root',
- 'PASSWORD': '',
- 'HOST': 'localhost',
- 'PORT': '3306',
- }
- }
4.1 编辑mydemo/myapp/models.py
- from django.db import models
-
-
- class Users(models.Model):
- #id = models.AutoField(primary_key=True) #主键可省略不写
- name = models.CharField(max_length=32)
- age = models.IntegerField(default=20)
- phone = models.CharField(max_length=16)
- addtime=models.DateTimeField(default=datetime.now)
-
- def __str__(self):
- return self.name+":"+self.phone
-
- # 自定义对应的表名,默认表名:myapp_users
- #class Meta:
- # db_table="myapp_users"
如果出现报错:
AttributeError: module 'datetime' has no attribute 'now'
需要改成addtime=models.DateTimeField(default=datetime.datetime.now()))
4.2 测试Model类的使用
在项目根目录下执行命令: python manage.py shell
- [root@localhost mydemo]# ls
- mydemo manage.py myapp
-
- [root@localhost mydemo]# python3 manage.py shell
- Python 3.6.1 (default, Jul 18 2017, 01:35:19)
- [GCC 4.4.7 20120313 (Red Hat 4.4.7-18)] on linux
- Type "help", "copyright", "credits" or "license" for more information.
- (InteractiveConsole)
-
- >>> from myapp.models import Users
-
- >>> Users.objects.all()
12345678901>, 13456789023>]> -
- >>> s = Users.objects.get(id=1)
-
- >>> s.id
- 1
-
- >>> s.name
- '张三'
-
- >>> s.age
- 20
-
- >>> s.phone
- '12345678901'
-
- >>>
5.1 编辑mydemo/mydemo/settings.py文件.做 ALLOWED_HOSTS 主机访问配置(若第三步已做可跳过此步骤)
- #此处添加自己的IP地址
- ALLOWED_HOSTS = ['*']
5.2 编写项目主路由urls配置,配置对myapp应用路由的访问连接配置
- from django.contrib import admin
- from django.urls import include,path
-
- urlpatterns = [
- #path('admin/', admin.site.urls),
- path('', include('myapp.urls')),
- ]
5.3 配置当前应用myapp的路由配置
在myapp应用目录下创建一个路由文件urls.py文件,注意此文件编码为utf-8(建议复制一个)。
编辑应用中的路由配置文件:mydemo/myapp/urls.py, 内容如下:
- from django.urls import path
-
- from . import views
-
- urlpatterns = [
- path('', views.index, name='index'),
- ]
5.4 编辑视图文件:mydemo/myapp/views.py,内容如下
-
- #from django.shortcuts import render
- from django.http import HttpResponse
-
- from myapp.models import Users
-
- def index(request):
- try:
- s = Users.objects.get(id=1)
- return HttpResponse(s)
- except:
- return HttpResponse("没有找到对应的信息!")
5.5 测试
项目根目录下运行 pythons manage.py sunserver 0.0.0.0:8000 命令,开启服务:
- [root@localhost mydemo]# python manage.py runserver 0.0.0.0:8000
- Performing system checks...
-
- System check identified no issues (0 silenced).
-
- July 28, 2020 - 14:01:52
- Django version 2.2.11, using settings 'myweb.settings'
- Starting development server at http://0.0.0.0:8000/
- Quit the server with CONTROL-C.
打开浏览器,在浏览其中输入网址测试:http://172.16.142.129:8000
显示结果:张三:12345678901
5 设置模板目录信息:编辑mydemo/mydemo/settings.py文件(若第三步已做可跳过此步骤)
- ...
- 'BACKEND': 'django.template.backends.django.DjangoTemplates',
- 'DIRS': [os.path.join(BASE_DIR,'templates'),],
- 'APP_DIRS': True,
- ...
打开文件:mydemo/myapp/urls.py路由文件,加入六条路由配置信息
- from django.urls import path
-
- from . import views
-
- urlpatterns = [
- path('', views.index, name="index"),
- path('users', views.indexUsers, name="users"), #浏览用户信息
- path('users/add', views.addUsers, name="addusers"), #加载添加用户信息表单
- path('users/insert', views.insertUsers, name="insertusers"), #执行用户信息添加
- path('users/
/del' , views.delUsers, name="delusers"), #执行用户信息删除 - path('users/
/edit' , views.editUsers, name="editusers"), #加载用户信息编辑表单 - path('users/update', views.updateUsers, name="updateusers"), #执行用户信息编辑
- ]
- # 注意:需导入from django.shortcuts import render
-
- from django.shortcuts import render
- from django.http import HttpResponse
-
- from myapp.models import Users
-
- def index(request):
- try:
- list = Users.objects.filter(id__in=[1,3,5])
- s = ','.join([vo.name for vo in list])
-
- #修改(将id值为5的age值改为30)
- #ob = Users.objects.get(id=5)
- #ob.age = 30
- #ob.save()
-
- #删除(删除id为3的信息)
- #ob = Users.objects.get(id=3)
- #ob.delete()
-
- return HttpResponse(s)
- except:
- return HttpResponse("没有找到对应的信息!")
-
- # 浏览用户信息
- def indexUsers(request):
- # 执行数据查询,并放置到模板中
- list = Users.objects.all()
- context = {"stulist":list}
- return render(request,"myapp/users/index.html",context)
-
- # 加载添加信息表单
- def addUsers(request):
- return render(request,"myapp/users/add.html")
-
- # 执行信息添加操作
- def insertUsers(request):
- try:
- ob = Users()
- ob.name = request.POST['name']
- ob.age = request.POST['age']
- ob.phone = request.POST['phone']
- ob.save()
- context = {'info':'添加成功!'}
- except:
- context = {'info':'添加失败!'}
- return render(request,"myapp/users/info.html",context)
-
- # 执行信息删除操作
- def delUsers(request,uid):
- try:
- ob = Users.objects.get(id=uid)
- ob.delete()
- context = {'info':'删除成功!'}
- except:
- context = {'info':'删除失败!'}
- return render(request,"myapp/users/info.html",context)
-
- # 加载信息编辑表单
- def editUsers(request,uid):
- try:
- ob = Users.objects.get(id=uid)
- context = {'user':ob}
- return render(request,"myapp/users/edit.html",context)
- except:
- context = {'info':'没有找到要修改的信息!'}
- return render(request,"myapp/users/info.html",context)
-
- # 执行信息编辑操作
- def updateUsers(request):
- try:
- ob = Users.objects.get(id= request.POST['id'])
- ob.name = request.POST['name']
- ob.age = request.POST['age']
- ob.phone = request.POST['phone']
- #ob.addtime = datetime.now
- ob.save()
- context = {'info':'修改成功!'}
- except:
- context = {'info':'修改失败!'}
- return render(request,"myapp/users/info.html",context)
文件位置:mydemo/templates/myapp/users/index.html
- html>
- <html>
- <head>
- <meta charset="utf-8"/>
- <title>用户信息管理title>
- <script>
- //自定义执行信息删除提示判断,参数uu是成功的删除url地址
- function doDel(uu){
- if(confirm("确定要删除吗?")){
- //网页跳转
- window.location=uu;
- }
- }
-
- script>
- head>
- <body>
- <center>
-
- {% include 'myapp/users/menu.html' %}
-
- <h3>浏览用户信息h3>
- <table width="800" border="1">
- <tr>
- <th>id号th>
- <th>姓名th>
- <th>年龄th>
- <th>电话th>
- <th>添加时间th>
- <th>操作th>
- tr>
- {% for stu in stulist %}
- <tr>
- <td>{{ stu.id }}td>
- <td>{{ stu.name }}td>
- <td>{{ stu.age }}td>
- <td>{{ stu.phone }}td>
- <td>{{ stu.addtime|date:'Y-m-d H:i:s' }}td>
- <td>
- <a href="{% url 'editusers' stu.id %}">编辑a>
- <a href="javascript:doDel('{% url 'delusers' stu.id %}');">删除a>
- td>
- tr>
- {% endfor %}
- table>
- center>
- body>
- html>
文件位置:mydemo/templates/myapp/users/add.html
- html>
- <html>
- <head>
- <meta charset="utf-8"/>
- <title>用户信息管理title>
- head>
- <body>
- <center>
- {% include "myapp/users/menu.html" %}
-
- <h3>添加用户信息h3>
- <form action="{% url 'insertusers' %}" method="post">
- {% csrf_token %}
- <table width="280" border="0">
- <tr>
- <td>姓名:td>
- <td><input type="text" name="name"/>td>
- tr>
- <tr>
- <td>年龄:td>
- <td><input type="text" name="age"/>td>
- tr>
- <tr>
- <td>电话:td>
- <td><input type="text" name="phone"/>td>
- tr>
- <tr>
- <td colspan="2" align="center">
- <input type="submit" value="添加"/>
- <input type="reset" value="重置"/>
- td>
- tr>
- table>
- form>
- center>
- body>
- html>
文件位置:mydemo/templates/myapp/users/edit.html
- html>
- <html>
- <head>
- <meta charset="utf-8"/>
- <title>用户信息管理title>
- head>
- <body>
- <center>
- {% include "myapp/users/menu.html" %}
- <h3>修改用户信息h3>
- <form action="{% url 'updateusers' %}" method="post">
- <input type="hidden" name="id" value="{{ user.id}}"/>
- {% csrf_token %}
- <table width="280" border="0">
- <tr>
- <td>姓名:td>
- <td><input type="text" name="name" value="{{ user.name }}"/>td>
- tr>
- <tr>
- <td>年龄:td>
- <td><input type="text" name="age" value="{{ user.age }}"/>td>
- tr>
- <tr>
- <td>电话:td>
- <td><input type="text" name="phone" value="{{ user.phone }}"/>td>
- tr>
- <tr>
- <td colspan="2" align="center">
- <input type="submit" value="编辑"/>
- <input type="reset" value="重置"/>
- td>
- tr>
- table>
- form>
- center>
- body>
- html>
文件位置:mydemo/templates/myapp/users/menu.html
- <h2>用户信息管理h2>
- <a href="{% url 'users' %}">浏览用户a> |
- <a href="{% url 'addusers' %}">添加用户a>
- <hr/>
文件位置:mydemo/templates/myapp/users/info.html
- html>
- <html>
- <head>
- <meta charset="utf-8"/>
- <title>用户信息管理title>
- head>
- <body>
- <center>
- {% include "myapp/users/menu.html" %}
-
- <h3>{{ info }}h3>
-
- center>
- body>
- html>