【Python之路Day17】django
Python的WEB框架有Django、Tornado、Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM、模型绑定、模板引擎、缓存、Session等诸多功能。
安装环境:
通过“cmd”打开一个新的命令提示符窗口,直接输入:“django-admin.py”,如果提示:“'django- admin.py' 不是内部或外部命令,也不是可运行的程序或批处理文件,那么说明你还没有django环境,请先下载安装,之后配好环境变量。相关参考:http://blog.csdn.net/suofiya2008/article/details/5706057
创建一个django项目
命令:“django-admin.py startproject [projectname]”在当前目录下建立一个名为[projectname]的项目,上图为我创建的名为CrazyMonitor的django项目。
启动与访问:
在当前项目的目录下使用命令python manage.py runserver可以启动当前项目:
程序目录
配置文件
模版
TEMPLATE_DIRS = ( os.path.join(BASE_DIR,'templates'), )
静态文件
STATICFILES_DIRS = ( os.path.join(BASE_DIR,'static'), )
创建APP
python manage.py startapp app01
路由(urls.py):
路由系统
1、每个路由规则对应一个view中的函数
1
2
3
|
url(r '^index/(\d*)' , views.index), url(r '^manage/(?P<name>\w*)/(?P<id>\d*)' , views.manage), url(r '^manage/(?P<name>\w*)' , views.manage,{ 'id' : 333 }), |
2、根据app对路由规则进行一次分类
1
|
url(r '^web/' ,include( 'web.urls' )), |
django中的路由系统和其他语言的框架有所不同,在django中每一个请求的url都要有一条路由映射,这样才能将请求交给对一个的view中的函数去处理。其他大部分的Web框架则是对一类的url请求做一条路由映射,从而是路由系统变得简洁。
在mysite下面创建一个urls.py
from django.conf.urls import url from django.contrib import admin from UserManageSys.views import index, login, register, add_user, del_user urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^index/$', index), url(r'^$', login), url(r'^login/$', login), url(r'^register/$', register), url(r'^user/add/$', add_user), url(r'^user/del/$', del_user), ]
在usermanagesys下面的views里创建上面urls对应的函数
from django.shortcuts import render, redirect from django.http import Http404, HttpResponse from UserManageSys import models # Create your views here. def index(request): user_list_db = models.UserInfo.objects.all() return render(request, 'index.html', {'li': user_list_db}) def login(request): if request.method == 'POST': username = request.POST.get('username', None) password = request.POST.get('password', None) user_exist = models.UserInfo.objects.filter(username=username, password=password).count() if user_exist: request.session['username'] = username return redirect('/index/') else: return render(request, 'login.html') return render(request, 'login.html', {'code': 0}) def register(request): if request.method == 'POST': u = request.POST.get('username', None) p = request.POST.get('password', None) e = request.POST.get('email', None) already_user = models.UserInfo.objects.filter(username=u).count() print(already_user) if already_user: return render(request, 'register.html') else: models.UserInfo.objects.create(username=u, password=p, email=e) return render(request, 'register.html') return render(request, 'register.html') def add_user(request): if request.method == 'POST': u = request.POST.get('username', None) p = request.POST.get('password', None) e = request.POST.get('email', None) print(u, p, e) user_info = {'username': u, 'email': e} already_user = models.UserInfo.objects.filter(username=u).count() print(already_user) if already_user: data = {'status': 1, 'result': '此用户已经存在!', 'data': user_info} return render(request, 'add_user.html', data) else: models.UserInfo.objects.create(username=u, password=p, email=e) data = {'status': 0, 'result': '用户添加成功!', 'data': user_info} return render(request, 'add_user.html', data) return render(request, 'add_user.html') def del_user(request): if request.method == 'POST': u = request.POST.get('username', None) p = request.POST.get('password', None) e = request.POST.get('email', None) print(u, p, e) user_info = {'username': u, 'email': e} already_user = models.UserInfo.objects.filter(username=u).count() print(already_user) if already_user: models.UserInfo.objects.filter(username=u, password=p, email=e).delete() data = {'status': 1, 'result': '用户删除成功!', 'data': user_info} return render(request, 'del_user.html', data) else: data = {'status': 0, 'result': '用户不存在成功!', 'data': user_info} return render(request, 'del_user.html', data) return render(request, 'del_user.html')
动态路由
比如分页:当urls大量过多的时候比如几百个的时候,那么肯定不会去写几百个路由规则
所有这个时候就需要动态urls,使用正则表达式来完成
在usermanagesys下面的urls写入以下内容:
from django.conf.urls import url,include from django.contrib import admin # 导入app下的view函数 from . import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^book/(\d+)$', views.book), // 正则匹配 ]
在usermanagesys下面的views写入以下内容:
from django.shortcuts import render,HttpResponse # Create your views here. def book(request,num): print(num) return HttpResponse(num) 当用户访问http://127.0.0.1:8000/usermanagesys/book/数字的时候 django会在自动把参数传给views里的book函数
多个参数它是已/来分割的
来一个url的加法
1.在usermanagesys下面的urls写入以下内容: from django.conf.urls import url,include from django.contrib import admin #导入app下的view函数 from . import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^book/(\d+)/(\d+)$', views.book), ] 2.在helloapp下面的views写入以下内容: def book(request,num1,num2): print(num1,num2) num = int(num1) + int(num2) return HttpResponse(num) 3.测试访问: http://127.0.0.1:8000/usermanagesys/book/2/1 显示3 http://127.0.0.1:8000/usermanagesys/book/2/10 显示12
动态的路由(Key:value的形式)
1.在usermanagesys下面的urls写入以下内容: from django.conf.urls import url,include from django.contrib import admin #导入app下的view函数 from . import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^book/(?P<k1>\d+)/(?P<k2>\d+)$', views.book), 这里?p<v1>这里的v1就是key,vlaue就是传进去的值, ] 2.在usermanagesys下面的views写入以下内容: from django.shortcuts import render,HttpResponse # Create your views here. def book(request,k1,k2): print(k1,k2) return HttpResponse(k1+k2)
模板
1、模板语言
模板中也有自己的语言,该语言可以实现数据展示
- {{ item }}
- {% for item in item_list %} <a>{{ item }}</a> {% endfor %}
forloop.counter
forloop.first
forloop.last - {% if ordered_warranty %} {% else %} {% endif %}
- 母板:{% block title %}{% endblock %}
子板:{% extends "base.html" %}
{% block title %}{% endblock %} - 帮助方法:
{{ item.event_start|date:"Y-m-d H:i:s"}}
{{ bio|truncatewords:"30" }}
{{ my_list|first|upper }}
{{ name|lower }}
自定义simple_tag
a、在app中创建templatetags模块
b、创建任意 .py 文件,如:xx.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
#!/usr/bin/env python #coding:utf-8 from django import template from django.utils.safestring import mark_safe from django.template.base import resolve_variable, Node, TemplateSyntaxError register = template.Library() @register .simple_tag def my_simple_time(v1,v2,v3): return v1 + v2 + v3 @register .simple_tag def my_input( id ,arg): result = "<input type='text' id='%s' class='%s' />" % ( id ,arg,) return mark_safe(result) |
c、在使用自定义simple_tag的html文件中导入之前创建的 xx.py 文件名
1
|
{ % load xx % } |
d、使用simple_tag
1
2
|
{ % my_simple_time 1 2 3 % } { % my_input 'id_username' 'hide' % } |
e、在settings中配置当前app,不然django无法找到自定义的simple_tag
1
2
3
4
5
6
7
8
9
|
INSTALLED_APPS = ( 'django.contrib.admin' , 'django.contrib.auth' , 'django.contrib.contenttypes' , 'django.contrib.sessions' , 'django.contrib.messages' , 'django.contrib.staticfiles' , 'app01' , |
总结:
filter
限制:传参(只能传两个参数)
支持:模版语言的 if 条件
simple_tag
不支持:模版语言的 if 条件
支持N多个参数
模版的继承
目的:同样的样式模板,不用重复写,
母板:
内容
{% block 名称 %} {% endblock %}
内容
子板:
{% extends '母板html文件名' %}
{% block 名称 %}
具体子页面的内容...
{% endblock %}
具体事例:
html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <link rel="stylesheet" href="..." /> <style> .pg-header{ height: 48px; background-color: cadetblue; } .pg-body{ min-height: 500px; } .pg-body .body-menu{ width: 20%; float: left; } .pg-body .body-content{ width: 80%; float: left; } .pg-footer{ height: 100px; background-color: brown; } .active{ background-color: aquamarine; color: white; } </style> {% block css %}{% endblock %} </head> <body> <div class="pg-header"> 后台系统V1 </div> <div class="pg-body"> <div class="body-menu"> <ul> <li><a id="userinfo" href="/web/userinfo">用户管理</a></li> <li><a id="assets" href="/web/assets">资产管理</a></li> </ul> </div> <div class="body-content"> {% block body %}{% endblock %} </div> </div> <div class="pg-footer"></div> <script src="xxx"></script> {% block js %}{% endblock %} </body> </html>
继承以上模板
{% extends 'layout.html' %} {% block css %} <style></style> {% endblock %} {% block body %} <ul> {% for item in user_list %} <li>{{ item.username }},{{ item.salary }}</li> {% endfor %} </ul> {% endblock %} {% block js %} <script> document.getElementById('userinfo').className = 'active'; </script> {% endblock %}
Form
django中的Form一般有两种功能:
- 输入html
- 验证用户输入
#!/usr/bin/env python # -*- coding:utf-8 -*- import re from django import forms from django.core.exceptions import ValidationError def mobile_validate(value): mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$') if not mobile_re.match(value): raise ValidationError('手机号码格式错误') class PublishForm(forms.Form): user_type_choice = ( (0, u'普通用户'), (1, u'高级用户'), ) user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice, attrs={'class': "form-control"})) title = forms.CharField(max_length=20, min_length=5, error_messages={'required': u'标题不能为空', 'min_length': u'标题最少为5个字符', 'max_length': u'标题最多为20个字符'}, widget=forms.TextInput(attrs={'class': "form-control", 'placeholder': u'标题5-20个字符'})) memo = forms.CharField(required=False, max_length=256, widget=forms.widgets.Textarea(attrs={'class': "form-control no-radius", 'placeholder': u'详细描述', 'rows': 3})) phone = forms.CharField(validators=[mobile_validate, ], error_messages={'required': u'手机不能为空'}, widget=forms.TextInput(attrs={'class': "form-control", 'placeholder': u'手机号码'})) email = forms.EmailField(required=False, error_messages={'required': u'邮箱不能为空','invalid': u'邮箱格式错误'}, widget=forms.TextInput(attrs={'class': "form-control", 'placeholder': u'邮箱'})) def __init__(self, *args, **kwargs): super(SampleImportForm, self).__init__(*args, **kwargs) self.fields['idc'].widget.choices = models.IDC.objects.all().order_by('id').values_list('id','display') self.fields['business_unit'].widget.choices = models.BusinessUnit.objects.all().order_by('id').values_list('id','name') Forms
def publish(request): ret = {'status': False, 'data': '', 'error': '', 'summary': ''} if request.method == 'POST': request_form = PublishForm(request.POST) if request_form.is_valid(): request_dict = request_form.clean() print request_dict ret['status'] = True else: error_msg = request_form.errors.as_json() ret['error'] = json.loads(error_msg) return HttpResponse(json.dumps(ret)) Views
扩展:ModelForm
在使用Model和Form时,都需要对字段进行定义并指定类型,通过ModelForm则可以省去From中字段的定义
class AdminModelForm(forms.ModelForm): class Meta: model = models.Admin #fields = '__all__' fields = ('username', 'email') widgets = { 'email' : forms.PasswordInput(attrs={'class':"alex"}), }
admin
django amdin是django提供的一个后台管理页面,改管理页面提供完善的html和css,使得你在通过Model创建完数据库表之后,就可以对数据进行增删改查,而使用django admin 则需要以下步骤:
- 创建后台管理员
- 配置url
- 注册和配置django admin后台管理页面
1、创建后台管理员
1
|
python manage.py createsuperuser |
2、配置后台管理url(默认是已经设置好的)
1
|
url(r '^admin/' , include(admin.site.urls)) |
3、注册和配置django admin 后台管理页面
a、在admin中执行如下配置
1
2
3
4
5
6
7
8
|
from django.contrib import admin from app01 import models admin.site.register(models.UserType) admin.site.register(models.UserInfo) admin.site.register(models.UserGroup) admin.site.register(models.Asset) |
b、设置数据表名称
class UserType(models.Model): name = models.CharField(max_length=50) class Meta: verbose_name = '用户类型' verbose_name_plural = '用户类型'
c、打开表之后,设定默认显示,需要在model中作如下配置
class UserType(models.Model): name = models.CharField(max_length=50) def __unicode__(self): #显示设定的字段名字,而不是objct,好区分 return self.name
from django.contrib import admin from app01 import models class UserInfoAdmin(admin.ModelAdmin): list_display = ('username', 'password', 'email') admin.site.register(models.UserType) admin.site.register(models.UserInfo,UserInfoAdmin) admin.site.register(models.UserGroup) admin.site.register(models.Asset)
d、为数据表添加搜索功能
from django.contrib import admin from app01 import models class UserInfoAdmin(admin.ModelAdmin): list_display = ('username', 'password', 'email') search_fields = ('username', 'email') admin.site.register(models.UserType) admin.site.register(models.UserInfo,UserInfoAdmin) admin.site.register(models.UserGroup) admin.site.register(models.Asset)
e、添加快速过滤
from django.contrib import admin from app01 import models class UserInfoAdmin(admin.ModelAdmin): list_display = ('username', 'password', 'email') search_fields = ('username', 'email') list_filter = ('username', 'email') admin.site.register(models.UserType) admin.site.register(models.UserInfo,UserInfoAdmin) admin.site.register(models.UserGroup) admin.site.register(models.Asset)
Ajax
ajax需要使用jquery
作用是偷偷的往后台发请求,页面不刷新
$.ajax({ url: '/index/', type: 'POST', data: {'username': 'alex','password': '123'}, success: function(data){ // 当后台return之后,该函数自动执行 // data就是后台返回的数据 } })
具体的例子:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <div> <p>用户名:<input type="text" id="username" /></p> </div> <div> <p>用户名:<input type="password" id="pwd" /></p> </div> <input type="button" value="提交" onclick="SubmitForm();" /> <script src="/static/jquery-1.8.2.min.js"></script> <script> function SubmitForm(){ $.ajax({ url: '/web/ajax_demo/', type: 'POST', data: {'user': $('#username').val(), 'pwd': $('#pwd').val()}, dataType: 'json', success: function (data) { // data = 字符串 {status:xx,message:''} // data对象 //var data_dict = JSON.parse(data); if(data.status){ location.href = "http://www.baidu.com"; }else{ alert(data.message); } } }) } </script> </body> </html>
后台views文件:
def ajax_demo(request): if request.method == 'POST': ret = {'status': False, 'message': ''} user = request.POST.get('user',None) pwd = request.POST.get('pwd',None) if user == '111' and pwd == '222': ret['status'] = True return HttpResponse(json.dumps(ret)) else: ret['message'] = "用户名或密码错误" return HttpResponse(json.dumps(ret)) return render(request, 'ajax_demo.html')
Model
D jango 模型是与数据库相关的,与数据库相关的代码一般写在 models.py 中,Django 支持 sqlite3, MySQL, PostgreSQL等数据库,只需要在settings.py中配置即可,不用更改models.py中的代码,丰富的API极大的方便了使用。
1、数据库的连接方式以及设置:
在Django中默认使用的数据库类型是sqlite3,如果想要使用其他数据库就需要在settings中设置数据库的连接方式:
# Database # https://docs.djangoproject.com/en/1.10/ref/settings/#databases # sqlite3数据库连接方式 # DATABASES = { # 'default': { # 'ENGINE': 'django.db.backends.sqlite3', # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), # } # } # MySQL数据库连接方式 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME':'dbname', 'USER': 'root', 'PASSWORD': 'xxx', 'HOST': '', 'PORT': '', } }
2、创建表
数据需要在models.py文件中创建
class UserInfo(models.Model): # CharField类型不能为空,最少要指定一个长度 user = models.CharField(max_length=32) email = models.EmailField(max_length=32) pwd = models.CharField(max_length=32) user_type = models.ForeignKey('UserType') class UserType(models.Model): nid = models.AutoField(primary_key=True) #默认是有隐藏自增id,加上primary_key=True,去掉默认,用自已定义的自增nid caption = models.CharField(max_length=16)
注:在创建外键的时候直接写上UserType和'UserType'的不加引号和加引号,区别就是python程序从上到下解释的顺序问题,如果把UserType这个类写到下面就会没事了
运行Djando项目程序,执行命令创建数据,会自动加载model文件创建定义的表和字段:
python3 manage.py makemigrations
python3 manage.py migrate
创建表的的参数:
1、models.AutoField 自增列 = int(11) #如果没有的话,默认会生成一个名称为 id 的列,如果要显示的自定义一个自增列,必须将给列设置为主键 primary_key=True。 2、models.CharField #字符串字段 #必须 max_length 参数 3、models.BooleanField #布尔类型=tinyint(1) #不能为空,Blank=True 4、models.ComaSeparatedIntegerField #用逗号分割的数字=varchar 继承CharField,所以必须 max_lenght 参数 5、models.DateField 日期类型 date 对于参数,auto_now = True 则每次更新都会更新这个时间;auto_now_add 则只是第一次创建添加,之后的更新不再改变。 6、models.DateTimeField 日期类型 datetime 同DateField的参数 7、models.Decimal 十进制小数类型 = decimal 必须指定整数位max_digits和小数位decimal_places 8、models.EmailField 字符串类型(正则表达式邮箱) =varchar 对字符串进行正则表达式 9、models.FloatField 浮点类型 = double 10、models.IntegerField 整形 11、models.BigIntegerField 长整形 integer_field_ranges = { 'SmallIntegerField': (-32768, 32767), 'IntegerField': (-2147483648, 2147483647), 'BigIntegerField': (-9223372036854775808, 9223372036854775807), 'PositiveSmallIntegerField': (0, 32767), 'PositiveIntegerField': (0, 2147483647), } 12、models.IPAddressField 字符串类型(ip4正则表达式) 13、models.GenericIPAddressField 字符串类型(ip4和ip6是可选的) 参数protocol可以是:both、ipv4、ipv6 验证时,会根据设置报错 14、models.NullBooleanField 允许为空的布尔类型 15、models.PositiveIntegerFiel 正Integer 16、models.PositiveSmallIntegerField 正smallInteger 17、models.SlugField 减号、下划线、字母、数字 18、models.SmallIntegerField 数字 数据库中的字段有:tinyint、smallint、int、bigint 19、models.TextField 字符串=longtext 20、models.TimeField 时间 HH:MM[:ss[.uuuuuu]] 21、models.URLField 字符串,地址正则表达式 22、models.BinaryField 二进制 23、models.ImageField #只针对admin后台上传图片,默认上传在根目录 24、models.FilePathField 文件 更多字段
1、null=True 数据库中字段是否可以为空 2、blank=True django的 Admin 中添加数据时是否可允许空值 3、primary_key = False 主键,对AutoField设置主键后,就会代替原来的自增 id 列 4、auto_now 和 auto_now_add auto_now 自动创建---无论添加或修改,都是当前操作的时间 auto_now_add 自动创建---永远是创建时的时间 5、choices GENDER_CHOICE = ( (u'M', u'Male'), (u'F', u'Female'), ) gender = models.CharField(max_length=2,choices = GENDER_CHOICE) 6、max_length 7、default 默认值 8、verbose_name Admin中字段的显示名称 9、name|db_column 数据库中的字段名称 10、unique=True 不允许重复 11、db_index = True 数据库索引 12、editable=True 在Admin里是否可编辑 13、error_messages=None 错误提示 14、auto_created=False 自动创建 15、help_text 在Admin中提示帮助信息 16、validators=[] 17、upload-to
执行成功状态:
bogon:django_modes01 zk$ python3 manage.py makemigrations Migrations for 'app01': app01/migrations/0001_initial.py: - Create model UserInfo - Create model UserType - Add field user_type to userinfo bogon:django_modes01 zk$ python3 manage.py migrate Operations to perform: Apply all migrations: admin, app01, auth, contenttypes, sessions Running migrations: Rendering model states... DONE Applying contenttypes.0001_initial... OK Applying auth.0001_initial... OK Applying admin.0001_initial... OK Applying admin.0002_logentry_remove_auto_add... OK Applying app01.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 auth.0007_alter_validators_add_error_messages... OK Applying auth.0008_alter_user_username_max_length... OK Applying sessions.0001_initial... OK
如果已经创建完毕并且已经填充了数据,需要修改字段,或添加字段,再执行
python3 manage.py migrate makemigrations ;可能会报错,这个就需要把字段定义个值,或定义此字段可以为空,
如果提示:No changes detected
需要在settings.py的配置文件检测一下有没有注册app
3、创建数据
创建数据的时候有两种方式:
第一种方式:
obj = models.表名(字段名='***') obj.save()
第二种方式:
models.表名.objects.create(字段名='***')
在views.py中写入数据:
from django.shortcuts import render,HttpResponse from app01 import models # Create your views here. def index(request): # 创建用户类型表 models.UserType.objects.create(caption='管路员') models.UserType.objects.create(caption='普通用户') models.UserType.objects.create(caption='超级管理员') # 创建用户信息表 user_info_dict_1 = {'user': 'ales', 'email': 'alex@qq.com', 'pwd': 123, 'user_type': models.UserType.objects.get(nid=1), } user_info_dict_2 = {'user': 'eric', 'email': 'eric@qq.com', 'pwd': 123, 'user_type_id': 2, } models.UserInfo.objects.create(**user_info_dict_1) models.UserInfo.objects.create(**user_info_dict_2) print('yes') return HttpResponse('ok')
4、连表关系:
- 一对多,models.ForeignKey(ColorDic)
- 一对一,models.OneToOneField(OneModel)
- 多对多,authors = models.ManyToManyField(Author)
应用场景:
- 一对一:在某表中创建一行数据时,有一个单选的下拉框(下拉框中的内容被用过一次就消失了)。
例如:原有含10列数据的一张表保存相关信息,经过一段时间之后,10列无法满足需求,需要为原来的表再添加5列数据。
- 一对多:当一张表中创建一行数据时,有一个单选的下拉框(可以被重复选择)。
例如:创建用户信息时候,需要选择一个用户类型【普通用户】【金牌用户】【铂金用户】等。
- 多对多:在某表中创建一行数据是,有一个可以多选的下拉框。
例如:创建用户信息,需要为用户指定多个爱好。
5、数据库基本操作
# 增 # # models.Tb1.objects.create(c1='xx', c2='oo') 增加一条数据,可以接受字典类型数据 **kwargs # obj = models.Tb1(c1='xx', c2='oo') # obj.save() # 查 # # models.Tb1.objects.get(id=123) # 获取单条数据,不存在则报错(不建议) # models.Tb1.objects.all() # 获取全部 # models.Tb1.objects.filter(name='seven') # 获取指定条件的数据 # 删 # # models.Tb1.objects.filter(name='seven').delete() # 删除指定条件的数据 # 改 # models.Tb1.objects.filter(name='seven').update(gender='0') # 将指定条件的数据更新,均支持 **kwargs # obj = models.Tb1.objects.get(id=1) # obj.c1 = '111' # obj.save() # 修改单条数据 基本操作
双下划线操作
# 获取个数 # # models.Tb1.objects.filter(name='seven').count() # 大于,小于 # # models.Tb1.objects.filter(id__gt=1) # 获取id大于1的值 # models.Tb1.objects.filter(id__lt=10) # 获取id小于10的值 # models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值 # in # # models.Tb1.objects.filter(id__in=[11, 22, 33]) # 获取id等于11、22、33的数据 # models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in # contains # # models.Tb1.objects.filter(name__contains="ven") # models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感 # models.Tb1.objects.exclude(name__icontains="ven") # range # # models.Tb1.objects.filter(id__range=[1, 2]) # 范围bettwen and # 其他类似 # # startswith,istartswith, endswith, iendswith, # order by # # models.Tb1.objects.filter(name='seven').order_by('id') # asc # models.Tb1.objects.filter(name='seven').order_by('-id') # desc # limit 、offset # # models.Tb1.objects.all()[10:20] # group by from django.db.models import Count, Min, Max, Sum # models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num')) # SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id" 进阶操作(双下划线)
单表查询:
# ret = models.UserType.objects.all() # print(ret.query) # ret.query后台返回的是查询的sql语句
输出结果:
SELECT `app01_usertype`.`nid`, `app01_usertype`.`caption` FROM `app01_usertype`
获取查询结果的类型:
ret = models.UserType.objects.all() print(type(ret), ret)
结果:
<class 'django.db.models.query.QuerySet'> <QuerySet [<UserType: UserType object>, <UserType: UserType object>, <UserType: UserType object>]>
可以看到类型是一个QuerySet类型,后面是所有的对象,每一个元素就是一个对象,可以循环拿出每一次的数据:
ret = models.UserType.objects.all() print(type(ret), ret) for item in ret: print(item, item.nid, item.caption)
取出的结果:
UserType object 1 管路员 UserType object 2 普通用户 UserType object 3 超级管理员
查询单个字段:
ret = models.UserType.objects.all().values('nid') print(type(ret), ret)
结果查询出nid字段对应的所有的数据 :
<class 'django.db.models.query.QuerySet'> <QuerySet [{'nid': 1}, {'nid': 2}, {'nid': 3}]>
可以看查询的sql语句,用query方法:
ret = models.UserType.objects.all().values('nid') print(type(ret), ret.query)
查询的结果:
<class 'django.db.models.query.QuerySet'> SELECT `app01_usertype`.`nid` FROM `app01_usertype`
当通过values循环取值的时候,如下:
ret = models.UserType.objects.all().values('nid') print(type(ret), ret.query) for item in ret: print(item, type(item))
结果:
<class 'django.db.models.query.QuerySet'> SELECT `app01_usertype`.`nid` FROM `app01_usertype` {'nid': 1} <class 'dict'> {'nid': 2} <class 'dict'> {'nid': 3} <class 'dict'>
通过结果可以看出,最外部是QuerySet,内部元素封装了一个是封装了这一行所有数据的对象,另外只拿到了某几列的字典!
当通过values_list循环取值的时候,如下:
ret = models.UserType.objects.all().values_list('nid') print(type(ret), ret)
查询结果:
<class 'django.db.models.query.QuerySet'> <QuerySet [(1,), (2,), (3,)]>
连表查询:
连表查询的时候和sqlachemy有多不同,django没有join这个方法:
通过UserInfo做连表查询
ret = models.UserInfo.objects.all() print(type(ret), ret) for item in ret: print(item, item.user_type, item.id, item.email, item.user, item.pwd)
查询结果:
<class 'django.db.models.query.QuerySet'> <QuerySet [<UserInfo: UserInfo object>, <UserInfo: UserInfo object>]> UserInfo object UserType object 1 tom@qq.com tom 123 UserInfo object UserType object 2 jerry@qq.com jerry 123
首先输出的是查找出来的UserInfo用户信息表,封装了用户所有的信息,而UserType就是一个对象,这个对象里封装的就是一行信息对应的字段(nid和caption),取出UserType对应的信息,例如:
ret = models.UserInfo.objects.all() print(type(ret), ret) for item in ret: print(item, item.user_type, item.id, item.email, item.user, item.pwd) print(item.user_type.nid, item.user_type.caption)
结果:
<class 'django.db.models.query.QuerySet'> <QuerySet [<UserInfo: UserInfo object>, <UserInfo: UserInfo object>]> UserInfo object UserType object 1 tom@qq.com tom 123 UserInfo object UserType object 2 jerry@qq.com jerry 123 1 管理员 2 普通用户
如果只想看到数据对应的名称,就需要加映射values:
ret = models.UserInfo.objects.all().values('user', 'user_type__caption') print(ret, ret.query)
结果:
<QuerySet [{'user': 'ales', 'user_type__caption': '管路员'}, {'user': 'eric', 'user_type__caption': '普通用户'}]> SELECT `app01_userinfo`.`user`, `app01_usertype`.`caption` FROM `app01_userinfo` INNER JOIN `app01_usertype` ON (`app01_userinfo`.`user_type_id` = `app01_usertype`.`nid`)
通过结果可以看到user_type__caption可以跨表直接获取相应的结果,再看sql语句中django本身加上了一个join。
如果在models中在加上一个表"P",然后在UserType中增加一条外键指向"平"P",
需求:要查找UserInfo表中的name和UserType表中的caption和P表中的neme的方法就是在找下一个对象的时候继续加双下划线:
增加的表结构:
查询语法:
ret = models.UserInfo.objects.all().values('user', 'user_type__caption', 'user_type__p__name') print(ret, ret.query)
查询的结果:
<QuerySet [{'user_type__p__name': 'allan', 'user_type__caption': '管理员', 'user': 'ales'}, {'user_type__p__name': 'allan', 'user_type__caption': '普通用户', 'user': 'eric'}]> SELECT `app01_userinfo`.`user`, `app01_usertype`.`caption`, `app01_p`.`name` FROM `app01_userinfo` INNER JOIN `app01_usertype` ON (`app01_userinfo`.`user_type_id` = `app01_usertype`.`nid`) INNER JOIN `app01_p` ON (`app01_usertype`.`p_id` = `app01_p`.`id`)
如果要拿用户类型是管理员的所有用户:
ret = models.UserInfo.objects.filter(user_type__caption="管理员").values('user', 'user_type__caption') print(ret)
结果:
<QuerySet [{'user': 'tom', 'user_type__caption': '管理员'}]>
5、下划线外键反向查找
找到管理员相关联的信息:
obj = models.UserType.objects.filter(caption='管理员').first() print(obj.nid, obj.caption)
这里查找的是usertype中的数据,如果通过usertype表查找到userinfo表中的信息就得用***_set:
obj = models.UserType.objects.filter(caption='管理员').first() print(obj.nid, obj.caption) print(obj.userinfo_set.all()) ret = models.UserType.objects.all().values('nid', 'caption', 'userinfo__user') print(ret)
1 管理员 <QuerySet [<UserInfo: UserInfo object>]> <QuerySet [{'caption': '管理员', 'userinfo__user': 'alex', 'nid': 1}, {'caption': '普通用户', 'userinfo__user': 'eric', 'nid': 2}, {'caption': '超级管理员', 'userinfo__user': None, 'nid': 3}]> [27/Aug/2016 15:35:31] "GET /index/ HTTP/1.1" 200 2
如果需要固定字段查找:
obj = models.UserType.objects.all().values('nid', 'userinfo__user') print(obj)
结果:
<QuerySet [{'userinfo__user': 'alex', 'nid': 1}, {'userinfo__user': 'eric', 'nid': 2}, {'userinfo__user': None, 'nid': 3}]>
6、多对多之表创建
多对多创建表的时候直接使用ManyToManyField让django自动创建第三张表或者自己手动创建第三张表
models表结构(自定义的第三张表):
class Host(models.Model): hid = models.AutoField(primary_key=True) hostname = models.CharField(max_length=32) ip = models.CharField(max_length=32) class Group(models.Model): gid = models.AutoField(primary_key=True) name = models.CharField(max_length=16) h2g = models.ManyToManyField('Host', through='HostToGroup') class HostToGroup(models.Model): hgid = models.AutoField(primary_key=True) host_id = models.ForeignKey('Host') group_id = models.ForeignKey('Group') status = models.IntegerField()
views文件中插入数据:
models.Host.objects.create(hostname='c1', ip='1.1.1.1') models.Host.objects.create(hostname='c2', ip='1.1.1.2') models.Host.objects.create(hostname='c3', ip='1.1.1.3') models.Host.objects.create(hostname='c4', ip='1.1.1.4') models.Host.objects.create(hostname='c5', ip='1.1.1.5') models.Group.objects.create(name='技术部') models.Group.objects.create(name='财务部') models.Group.objects.create(name='人事部') models.Group.objects.create(name='公关部') models.Group.objects.create(name='运营部') models.Group.objects.create(name='销售部') models.Group.objects.create(name='客服部')
操作表:
获取财务部的对象:
obj = models.Group.objects.get(gid=2) print(obj.gid, obj.name, obj.h2g.all())
结果:
2 财务部 <QuerySet []>
给财务部添加主机:
# 添加一台主机 obj = models.Group.objects.get(gid=2) # print(obj.gid, obj.name, obj.h2g.all()) h1 = models.Host.objects.get(hid=1) obj.h2g.add(h1)
# 把剩下的全部添加 obj = models.Group.objects.get(gid=2) # print(obj.gid, obj.name, obj.h2g.all()) # h1 = models.Host.objects.get(hid=1) q = models.Host.objects.filter(hid__gt=1) obj.h2g.add(*q)
将一台机器分配给多个组(就得用反向操作了):
h = models.Host.objects.get(hid=1)
h.group_set.add(*models.Group.objects.filter(gid__gt=2))
管理员