一.from的基本功能应用
1.1.保存用户输入
建立form对象时.把POST对象传进去.则可以用户输入验证错误返回页面时.保存用户以前的输入,提高用户体验.
1 2 3 | def login(request): obj = LoginForm(request.POST) #如果是第一次加载页面.则Post为空.也不会报错 return render(request, 'account/login.html', {'obj': obj}) |
1.2.from验证错误信息原始对象格式
from验证错误时.通过obj.errors能拿到错误的信息.它有3种格式
obj.errors------------->原始的对象,一般是from请求时用.在静态的模板中应用.
1 2 3 4 5 6 7 8 9 | <class 'django.forms.utils.ErrorDict'> <ul class="errorlist"> <li> username <ul class="errorlist"> <li>This field is required.</li> </ul> </li> </ul> |
在模板中获取错误信息,不能通过括号,只能能过点
1 | <span>{{ errors.username }}</span> |
前台输出的是ul,不是纯文本.
1 | <span class="html-tag"><ul <span class="html-attribute-name">class</span>="<span class="html-attribute-value">errorlist</span>"></span><span class="html-tag"><li></span>This field is required.<span class="html-tag"></li></span><span class="html-tag"></ul></span> |
类为他是个django的错误列表,在后台页面获取方式使用[]
1 2 | <class 'django.forms.utils.ErrorList'> print errors['username'][0] #输出为:This field is required. |
输出纯文本,需要自定义simple-tag来处理
A.建立
D:\python\day19\cmdb\templatetags 包
B.新建tag的文件
1 2 3 4 5 6 7 8 9 10 11 12 13 | #!/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 msg_error(error_list): if error_list: return error_list[0]
return '' |
C.模板页面引用
1 2 3 | {% load login_tag %}
<span>{% msg_error errors.username %}</span> #使用tag标签来处理 |
1.3.from验证错误信息json格式
obj.errors.as_json------------>json对象.一般是ajxa请求时用.因为ajax请求时.不能返回对象.需要变成字符串.
错误类型如下:
1 2 3 4 5 6 | { "username": [{"message": "This field is required.", "code": "required"}], "password": [{"message": "This field is required.", "code": "required"}] } |
1.4.form表单生成select标签
from类中先定义
1 2 3 | host_type = forms.IntegerField( widget=forms.Select() ) |
因为是类的静态字段.上述的定义会存在取数据不会实时更新问题.所以可以在类的构造函数中.进行初始化.这样,每次加载页面.都可以去数据库中取取数据
1 2 3 4 | def __init__(self, *args, **kwargs): super(LoginForm, self).__init__(*args, **kwargs) #执行下父类的构造函数 host_data = models.UserInfo.objects.all().values_list("id", "username") #取数据 self.fields['host_type'].widget.choices = host_data #赋值 |
二.model操作进阶
2.1.关系对象映射(Object Relational Mapping,简称ORM)
model类代表数据库的表
model对象代表数据库表的一行记录
对象.value------------>每行里面具体的数据
2.2.model常用的字段
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 1、models.AutoField 自增列 = int(11) #如果没有的话,默认会生成一个名称为 id 的列,如果要显示的自定义一个自增列,必须将给列设置为主键 primary_key=True。 2、models.DateField 日期类型 date 参数:auto_now = True 则每次更新都会更新这个时间; auto_now_add 则只是第一次创建添加,之后的更新不再改变 #测试后发现只在admin修改中用效 3、models.Decimal 十进制小数类型 = decimal 必须指定数位max_digits和小数位decimal_places 4、models.EmailField 字符串类型(正则表达式邮箱) =varchar 对字符串进行正则表达式 5、models.FloatField 浮点类型 = double10、models.IntegerField 整形 6、models.BigIntegerField 长整形 integer_field_ranges = { 'SmallIntegerField': (-32768, 32767), 'IntegerField': (-2147483648, 2147483647), 'BigIntegerField': (-9223372036854775808, 9223372036854775807), 'PositiveSmallIntegerField': (0, 32767), 'PositiveIntegerField': (0, 2147483647), } 7、models.GenericIPAddressField 字符串类型(ip4和ip6是可选的) 参数protocol可以是:both、ipv4、ipv6 验证时,会根据设置报错 8、models.ImageField 图片 upload参数,设置保存路径 9、models.FilePathField 文件 |
注:以上大部份参数,主要是admin后台页面使用.
2.3.字段参数
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 | 1、<span style="color: #ff0000;">null=True</span> 数据库中字段是否可以为空 2、blank=True django的 Admin 中添加数据时是否可允许空值 3、<span style="color: #ff0000;">primary_key</span> = False 主键,对AutoField设置主键后,就会代替原来的自增 id 列 4、auto_now 和 auto_now_add auto_now 自动创建---无论添加或修改,都是当前操作的时间 auto_now_add 自动创建---永远是创建时的时间 5、<span style="color: #ff0000;">choices</span> GENDER_CHOICE = ( (u'M', u'Male'), (u'F', u'Female'), ) gender = models.CharField(max_length=2,choices = GENDER_CHOICE) 6、<span style="color: #ff0000;">max_length</span> #char类型必段要写,不写会报错 7、<span style="color: #ff0000;">default</span> 默认值 8、verbose_name Admin中字段的显示名称 9、name|db_column 数据库中的字段名称 10、<span style="color: #ff0000;">unique=True</span> 不允许重复 11、<span style="color: #ff0000;">db_index = True</span> 数据库索引 12、editable=True 在Admin里是否可编辑 13、error_messages=None 错误提示 14、help_text 在Admin中提示帮助信息 15、<span style="color: #ff0000;">validators=[] #使用验证函数,与forms中类似</span> 16、upload-to #设置上传到那个路径 |
2.4.各种models的字段和form的字段区别
models的字段作用:为了后台/admin,添加数据时.进行验证.因为admin后台录入数据,没有经过类似前以的from表达验证.防止出现脏数据.
from的字段:前台form输入时.进行验证.
所以才有了2套规则.规则非常相似!!
2.5.form文件上传实例
1 2 3 4 | <form method="post" action="/cmdb/login/" enctype="multipart/form-data"> <input type="file" name="f1"> <input type="submit" value="提交"> </form> |
view处理函数
1 2 3 4 5 6 7 | inp_files = request.FILES #获取 所有的文件对象 file_obj1 = inp_files.get("f1") #获取上传文件的内存对象 f = open(file_obj1.name, "wb") #打开写入的文件
for line in file_obj1.chunks(): #分片读取文件内容,写入到服务器 f.write(line) f.close() |
二.数据库Model操作建表
2.1.数据库建表一对多(外键)
一对多.指表的一个字段的值,对应另外个表的字段的多个值.
1 2 3 4 5 6 | class Bussines(models.Model): dep_name = models.CharField(max_length=64)
class Host(models.Model): host_name = models.CharField(max_length=32) dep = models.ForeignKey('Bussines') #外键 |
2.2.数据库建表多对多
1 2 3 4 5 6 7 8 | class User_Group(models.Model): group_name = models.CharField(max_length=32)
class User(models.Model): name = models.CharField(max_length=32) password = models.CharField(max_length=32) email = models.CharField(max_length=32) user_group = models.ManyToManyField("User_Group") #会创建第3张表.进行多对多 |
2.3.建表之一对一
A表中的数据只能在B表中出现一次
1 2 3 4 5 6 7 8 | class AAdmin(models.Model): name = models.CharField(max_length=32) password = models.CharField(max_length=32)
class User2(models.Model): user_name = models.CharField(max_length=32) email = models.CharField(max_length=32) user_info = models.OneToOneField("AAdmin") #一对一的关系 |
三.数据库单表的基本操作
3.1.增加数据:
1 2 3 4 | 法一: models.Tb1.objects.create(c1='xx', c2='oo') 增加一条数据,可以接受字典类型数据 **kwargs 法二: obj = models.Tb1(c1='xx', c2='oo') obj.save() 法三:models.Tb1.objects.create(**dic) 接受个字典 |
3.2.查数据:
1 2 3 4 5 | 法一:models.Tb1.objects.get(id=123) # 获取单条数据,不存在则报错(不推荐使用) 法二:models.Tb1.objects.all() # 获取整张表的数据 法三:models.Tb1.objects.filter(name='seven', gender="0") # 获取指定条件的数据 法四:models.Tb1.objects.filter(**dic) #也可以传字典来判断 法五:models.Tb1.objects.all().first() #取第一条数据 |
3.3.查询数据得到的结果类型
1 2 | <class 'django.db.models.query.QuerySet'> #是django的自定义的查询的结果集 [<User: User object>] #all方法返回一个结果集列表 |
查询指定的列法一:
1 2 3 | user_model_obj = models.User.objects.all().values("name", 'email') print type(user_model_obj) print user_model_obj |
返回的结果是字典列表
1 2 | <class 'django.db.models.query.QuerySet'> [{'name': u'alex', 'email': u'abc@126.com'}] |
查询指定的列法二:
1 | user_model_obj = models.User.objects.all().values_list("name", 'email') |
返加的结果是元组列表
1 | [(u'alex', u'abc@126.com')] |
3.4.删除数据
1 2 | 法一:models.Tb1.objects.filter(name='seven').delete() # 删除指定条件的数据 法二:models.Tb1.objects.filter(**did).delete() #也可以传字典进去 |
3.5.修改数据
1 2 3 4 | 法一: models.Tb1.objects.filter(name='seven').update(gender='0') #将指定条件的数据更新,均支持 **kwargs 法二:obj = models.Tb1.objects.get(id=1) obj.c1 = '111' obj.save() #修改单条数据 |
四.数据库单表进阶操作
4.1.获取数据个数
1 | user_count = models.User.objects.all().filter(name="alex").count() |
4.2.查询条件中使用大于,小于,等于
1 2 3 4 5 | user_model_obj = models.User.objects.all().filter(id__gt=2) #大于 user_model_obj = models.User.objects.all().filter(id__lt=2) #小于 user_model_obj = models.User.objects.all().filter(id=2) #等于
user_model_obj = models.User.objects.all().filter(id__gt=1, id_lt=10) #大于1, 小于10 |
结果
1 2 3 | [<User: 3>, <User: 4>] [<User: 1>] [<User: 2>] |
4.3.查询条件使用in 和 not in
1 2 | user_model_obj = models.User.objects.all().filter(id__in=[1, 2]) user_model_obj = models.User.objects.all().exclude(id__in=[1, 2]) |
结果
1 2 | [<User: 1>, <User: 2>] [<User: 3>, <User: 4>] |
4.4.查询条件使用like(包含每些字符)
1 2 3 | models.Tb1.objects.filter(name__contains="ven") models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感 models.Tb1.objects.exclude(name__icontains="ven") #不包含ven |
4.5.查询条件使用bettwen and
1 | user_model_obj = models.User.objects.filter(id__range=[1, 3]) |
获取结果
1 | [<User: 1>, <User: 2>, <User: 3>] |
4.6.查询条件以什么开头
1 | startswith,istartswith, endswith, iendswith, |
4.7.升序,降序排列
1 2 | user_model_obj = models.User.objects.filter(id__range=[1, 3]).order_by('id') user_model_obj = models.User.objects.filter(id__range=[1, 3]).order_by('-id') |
返回结果
1 2 | [<User: 1>, <User: 2>, <User: 3>] [<User: 3>, <User: 2>, <User: 1>] |
4.8. 从什么开始取几个l
1 | user_model_obj = models.User.objects.all()[1:4] #从第一条开始取,取到第四条,不包括第1条 |
1 | [<User: 2>, <User: 3>, <User: 4>] |
4.9.分组groupby.聚合函数使用
1 2 3 4 5 6 | from django.db.models import Count, Min, Max, Sum
models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num')) #根椐ID进行分组,然后对num进行求和,得到一个新列c
SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id" |
五.表一对多的操作
5.1. 2张表外键约束,添加数据操作
法一.外键列的值使用对象(稍显复杂)
1 2 3 4 5 6 7 8 | group_obj = models.User_Group.objects.get(id=all_data['user_group_id'])
models.User.objects.create( name=all_data['username'], password=all_data['password'], email=all_data['email'], user_group = group_obj ) |
法二.直接使用外键的表字段
POST的传递过来的数据.直接用
1 | user_group_id = all_data['user_group_id'] #此方法更简便 |
外键建表时models中的定义
1 | user_group = models.ForeignKey("User_Group") #<span style="color: #ff0000;">user_group 代表的是一个对象</span> |
5.2.联表操作获取数据
views层,取得数据
1 2 | user_list = models.User.objects.all() return render(request, 'account/login.html', {'obj': obj, "user_list": user_list}) |
模板中渲染
1 2 3 4 5 6 7 | {% for item in user_list %} <tr> <td>{{ item.id }}</td> <td>{{ item.name }}</td> <td>{{ item.user_group.group_name }}</td> #外键在Model层定义时代表的是一个对象.可以直接调用其字段 </tr> {% endfor %} |
view层.通过外键对应的值获取数据(使用了不起的双划线来处理___),跨表时
1 2 | val =request.GET['user_group'] user_list = models.User.objects.filter(user_group<span style="color: #ff0000;">__group_name</span>= val ) #外键名__关联表的字段名 |
总结:
1.model中定义的外键代指一个对象
2.添加数据时.可以使用外键的字段如(user_group_id)
3.查询数据时.可以使用 . 来获取
4.view中跨表查数据,过滤使用__来查
5.多张表中,可以连续使用__来实现 (user_group__group_name__aa)
6.以上规则,同样适用一对一的表