目录
1、Django获取多个数据
在我们的view.py中获取前端form表单发来的一个数据比较简单,比如text、radio、password等
v = request.POST.get("username")
获取多个数据,比如checkbox、select
v = request.POST.getlist("favor")
2、Django文件上传
前端代码
<form action="" method="post" enctype="multipart/form-data">
<input type="file" name="fname" />
<input type="submit" value="提交" />
</form>
view.py
obj = request.FILES.get("fname")
# obj.name 文件名
# obj.size 文件大小
print(obj, type(obj))
f = open(obj.name, "wb") # 当前路径新建一个文件,名叫源文件的名字
for i in obj.chunks(): # 本地下载,chunks生成器迭代器的知识点
f.write(i)
f.close()
3、CBV和FBV
FBV:function base view
就是经常用的,urls.py中请求对应views.py中的函数
urls.py
path('index/', views.index),
views.py
def index(request):
if request.method == "POST":
return render(request, 'index.html')
elif request.method == "GET":
return render(request, 'index.html')
CBV:class base view
urls.py中请求对应views.py中的类,和FBV不同点就是,不需要自己去判断提交方式是哪一种了
提交方式有:[‘get’, ‘post’, ‘put’, ‘patch’, ‘delete’, ‘head’, ‘options’, ‘trace’]
urls.py
path('home/', views.Home.as_view()),
views.py
from django.views import View
class Home(View):
# 请求来了,先调用dispatch,基于反射找到相应的提交方式
#这样重写父类的dispatch可以定制功能
def dispatch(self, request, *args, **kwargs):
#调用父类的dispatch
print('before')
result = super(Home, self).dispatch(request, *args, **kwargs)
print('after')
return result
def get(self, request):
print(request.method)
return render(request, 'home.html')
def post(self, request):
print(request.method)
return render(request, 'home.html')
4、DjangoORM
1.创建基本类型以及生成数据库结构
创建类
1、根据类自动创建数据库表
在app下的models.py
from django.db import models
# Create your models here.
#app01_userinfo
class UserInfo(models.Model):
# 隐含的,自动创建id列,自增,主键
# 用户名列、字符串类型、指定长度
# 字段:字符串、数字、时间、二进制、自增(primary_key)
username = models.CharField(max_length=32)
password = models.CharField(max_length=64)
Django提供了大量的字段,其中大部分字段都是给Django自带的后台管理系统使用的
字段
AutoField(Field)
- int自增列,必须填入参数 primary_key=True
BigAutoField(AutoField)
- bigint自增列,必须填入参数 primary_key=True
注:当model中如果没有自增列,则自动会创建一个列名为id的列
from django.db import models
class UserInfo(models.Model):
# 自动创建一个列名为id的且为自增的整数列
username = models.CharField(max_length=32)
class Group(models.Model):
# 自定义自增列
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
SmallIntegerField(IntegerField):
- 小整数 -32768 ~ 32767
PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
- 正小整数 0 ~ 32767
IntegerField(Field)
- 整数列(有符号的) -2147483648 ~ 2147483647
PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
- 正整数 0 ~ 2147483647
BigIntegerField(IntegerField):
- 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807
自定义无符号整数字段
class UnsignedIntegerField(models.IntegerField):
def db_type(self, connection):
return 'integer UNSIGNED'
PS: 返回值为字段在数据库中的属性,Django字段默认的值为:
'AutoField': 'integer AUTO_INCREMENT',
'BigAutoField': 'bigint AUTO_INCREMENT',
'BinaryField': 'longblob',
'BooleanField': 'bool',
'CharField': 'varchar(%(max_length)s)',
'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
'DateField': 'date',
'DateTimeField': 'datetime',
'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
'DurationField': 'bigint',
'FileField': 'varchar(%(max_length)s)',
'FilePathField': 'varchar(%(max_length)s)',
'FloatField': 'double precision',
'IntegerField': 'integer',
'BigIntegerField': 'bigint',
'IPAddressField': 'char(15)',
'GenericIPAddressField': 'char(39)',
'NullBooleanField': 'bool',
'OneToOneField': 'integer',
'PositiveIntegerField': 'integer UNSIGNED',
'PositiveSmallIntegerField': 'smallint UNSIGNED',
'SlugField': 'varchar(%(max_length)s)',
'SmallIntegerField': 'smallint',
'TextField': 'longtext',
'TimeField': 'time',
'UUIDField': 'char(32)',
BooleanField(Field)
- 布尔值类型
NullBooleanField(Field):
- 可以为空的布尔值
CharField(Field)
- 字符类型
- 必须提供max_length参数, max_length表示字符长度
TextField(Field)
- 文本类型
EmailField(CharField):
- 字符串类型,Django Admin以及ModelForm中提供验证机制
GenericIPAddressField(Field)
- 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6
- 参数:
protocol,用于指定Ipv4或Ipv6, 'both',"ipv4","ipv6"
unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启刺功能,需要protocol="both"
URLField(CharField)
- 字符串类型,Django Admin以及ModelForm中提供验证 URL
SlugField(CharField)
- 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号)
CommaSeparatedIntegerField(CharField)
- 字符串类型,格式必须为逗号分割的数字
UUIDField(Field)
- 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证
FilePathField(Field)
- 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能
- 参数:
path, 文件夹路径
match=None, 正则匹配
recursive=False, 递归下面的文件夹
allow_files=True, 允许文件
allow_folders=False, 允许文件夹
FileField(Field)
- 字符串,路径保存在数据库,文件上传到指定目录
- 参数:
upload_to = "" 上传文件的保存路径
storage = None 存储组件,默认django.core.files.storage.FileSystemStorage
ImageField(FileField)
- 字符串,路径保存在数据库,文件上传到指定目录
- 参数:
upload_to = "" 上传文件的保存路径
storage = None 存储组件,默认django.core.files.storage.FileSystemStorage
width_field=None, 上传图片的高度保存的数据库字段名(字符串)
height_field=None 上传图片的宽度保存的数据库字段名(字符串)
DateTimeField(DateField)
- 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]
DateField(DateTimeCheckMixin, Field)
- 日期格式 YYYY-MM-DD
TimeField(DateTimeCheckMixin, Field)
- 时间格式 HH:MM[:ss[.uuuuuu]]
DurationField(Field)
- 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型
FloatField(Field)
- 浮点型
DecimalField(Field)
- 10进制小数
- 参数:
max_digits,小数总长度
decimal_places,小数位长度
BinaryField(Field)
- 二进制类型
参数
null 数据库中字段是否可以为空
db_column 数据库中字段的列名
db_tablespace
default 数据库中字段的默认值
primary_key 数据库中字段是否为主键
db_index 数据库中字段是否可以建立索引
unique 数据库中字段是否可以建立唯一索引
unique_for_date 数据库中字段【日期】部分是否可以建立唯一索引
unique_for_month 数据库中字段【月】部分是否可以建立唯一索引
unique_for_year 数据库中字段【年】部分是否可以建立唯一索引
auto_now 创建时,自动生成时间
auto_now_add 更新时,自动更新时间
如:
ctime = models.DateTimeField(auto_now_add=True, null=True)
uptime = models.DateTimeField(auto_now=True, null=True)
自动更新时:1更新时间不会发生变化,2有效,所以要用第二种
写法一:
obj = UserGroup.objects.filter(id=1).update(caption="CEO")
写法二:
obj = UserGroup.objects.filter(id=1).first()
obj.caption="CEO"
obj.save()
verbose_name Admin中显示的字段名称
blank Admin中是否允许用户输入为空
editable Admin中是否可以编辑
help_text Admin中该字段的提示信息
choices Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
如:
user_type_choices = (
(1, '超级用户'),
(1, '普通用户'),
(1, '普普通用户'),
)
user_type_id = models.IntegerField(choices=user_type_choices, default=1)
error_messages 自定义错误信息(字典类型),从而定制想要显示的错误信息;
字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date
如:{'null': "不能为空.", 'invalid': '格式错误'}
validators 自定义错误验证(列表类型),从而定制想要的验证规则
from django.core.validators import RegexValidator
from django.core.validators import EmailValidator,URLValidator,DecimalValidator,\
MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator
如:
test = models.CharField(
max_length=32,
error_messages={
'c1': '优先错信息1',
'c2': '优先错信息2',
'c3': '优先错信息3',
},
validators=[
RegexValidator(regex='root_\d+', message='错误了', code='c1'),
RegexValidator(regex='root_112233\d+', message='又错误了', code='c2'),
EmailValidator(message='又错误了', code='c3'), ]
)
写好类之后,查看settings.py中的app是否注册了,如果注册,执行命令,生成数据库表
#django生成表结构、修改表结构
python3 manage.py makemigrations
python3 manage.py migrate
2、根据类对数据库表中的数据进行操作
# 创建
# 1、
models.UserInfo.objects.create(username='root', password='123')
#models.UserGroup.objects.create(caption="dba")
# 2、
dic = {'username': 'test', 'password': '123'}
models.UserInfo.objects.create(**dic)
# 3、
obj = models.UserInfo(username='severen', password="123")
obj.save()
# 查
result = models.UserInfo.objects.all()
result是一个QuerySet类型,这个类型是Django提供的,我们去理解的就话,就当它是一个列表即可,列表内的元素是UserInfo的对象
result = models.UserInfo.objects.filter(username='root')
result = models.UserInfo.objects.filter(username='root', password='123')
for row in result:
print(row.id, row.username, row.password)
obj = models.UserInfo.objects.filter(id=nid).first()
# 取单条数据,如果不存在,就直接报错
# models.UserInfo.objects.get(id=nid)
# 删除
models.UserInfo.objects.all().delete()
models.UserInfo.objects.filter(id=4).delete()
# 更新
models.UserInfo.objects.all().update(password='666')
# gte -> 大于等于;lte -> 小于等于
models.UserInfo.objects.filter(id__gt=1).update(password='666') # id > 1
2.外键操作
# UserInfo表中的user_group字段关联UserGroup表的主键,建立外键关系
# 数据库里面会自动生成字段名user_group_id
user_group = models.ForeignKey("UserGroup", to_field='uid', default=1, on_delete=models.CASCADE) # 如果没有指定to_field字段,默认和关联表的主键关联
在进行操作的时候,可以取到obj.user_group和obj.user_group_id
obj.user_group是一个对象
obj.user_group_id是数值
3.获取单表单数据的三种方式
# way one
v1 = models.Business.objects.all()
# QuerySet, 内部元素是对象
# [obj(id, caption, code), obj, obj...]
# way two
v2 = models.Business.objects.all().values('id', 'caption')
# QuerySet, 内部元素是字典
# [{'id':1, 'caption':'运维部'},{},{}...]
# way three
v3 = models.Business.objects.all().values_list('id', 'caption')
# QuerySet, 内部元素是元组
# [(1, '运维部'),(2, '开发'),()...]
<h1>业务线列表(对象)</h1>
<ul>
{% for row in v1 %}
<li>
{{row.id}}-{{row.caption}}-{{row.code}}
</li>
{% endfor %}
</ul>
<h1>业务线列表(字典)</h1>
<ul>
{% for row in v2 %}
<li>
{{row.id}}-{{row.caption}}
</li>
{% endfor %}
</ul>
<h1>业务线列表(元组)</h1>
<ul>
{% for row in v3 %}
<li>
{{row.0}}-{{row.1}}
</li>
{% endfor %}
</ul>
4.获取一对多数据的的三种方式
# way 1
v1 = models.Host.objects.all()
# 双下划线 way 2
v2 = models.Host.objects.filter(nid__gt=0).values('nid', 'hostname', 'ip', 'port', 'b_id', 'b__caption')
for row in v2:
print(row["nid"],row["hostname"],row["ip"],row["port"],row["b_id"],row["b__caption"])
# way 3
v3 = models.Host.objects.filter(nid__gt=0).values_list('nid', 'hostname', 'ip', 'port', 'b_id', 'b__caption')
<h1>主机列表(对象)</h1>
<div>
<input id='add_host' type='button' value='添加' />
</div>
<table border='1'>
<thead>
<tr>
<th>序号</th>
<th>主机名</th>
<th>IP</th>
<th>端口</th>
<th>业务线名称</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for row in v1 %}
<tr hid='{{row.nid}}' bid='{{row.b_id}}'>
<td>{{forloop.counter}}</td> <!--forloop.counter: for循环的计数器,从1开始,循环一次记+1,counter0:从0开始, revcounter, revcounter0:反转, last, first:是否是最后一个,第一个-->
<td>{{row.hostname}}</td>
<td>{{row.ip}}</td>
<td>{{row.port}}</td>
<td>{{row.b.caption}}</td>
<td>
<a class='edit'>编辑</a>|<a class='delete'>删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<h1>主机列表(字典)</h1>
<table border='1'>
<thead>
<tr>
<th>主机名</th>
<th>IP</th>
<th>端口</th>
<th>业务线名称</th>
</tr>
</thead>
<tbody>
{% for row in v2 %}
<tr hid='{{row.nid}}' bid='{{row.b_id}}'>
<td>{{row.hostname}}</td>
<td>{{row.ip}}</td>
<td>{{row.port}}</td>
<td>{{row.b__caption}}</td>
</tr>
{% endfor %}
</tbody>
</table>
<h1>主机列表(元组)</h1>
<table border='1'>
<thead>
<tr>
<th>主机名</th>
<th>IP</th>
<th>端口</th>
<th>业务线名称</th>
</tr>
</thead>
<tbody>
{% for row in v3 %}
<tr hid='{{row.0}}' bid='{{row.4}}'>
<td>{{row.1}}</td>
<td>{{row.2}}</td>
<td>{{row.3}}</td>
<td>{{row.5}}</td>
</tr>
{% endfor %}
</tbody>
</table>
5.多对多关系
创建多对多
way1:自定义关系表
优点:想生成多少列数据就多少列
缺点:需要自己写第三张表
class Host(models.Model):
nid = models.AutoField(primary_key=True)
hostname = models.CharField(max_length=32, db_index=True) # db_index: 索引
ip = models.GenericIPAddressField(protocol="both", db_index=True) # protocol: 支持ipv4还是ipv6
port = models.IntegerField()
b = models.ForeignKey("Business", to_field="id", on_delete=models.CASCADE)
class Application(models.Model):
name = models.CharField(max_length=32)
class HostToApp(models.Model):
hobj = models.ForeignKey(to="Host", to_field="nid", on_delete=models.CASCADE)
aobj = models.ForeignKey(to='Application', to_field='id', on_delete=models.CASCADE)
way2:自动创建关系表
优点:不要自己写第三张表,自动生成
缺点:最多生成三列数据类型
class Host(models.Model):
nid = models.AutoField(primary_key=True)
hostname = models.CharField(max_length=32, db_index=True) # db_index: 索引
ip = models.GenericIPAddressField(protocol="both", db_index=True) # protocol: 支持ipv4还是ipv6
port = models.IntegerField()
b = models.ForeignKey("Business", to_field="id", on_delete=models.CASCADE)
class Application(models.Model):
name = models.CharField(max_length=32)
r = models.ManyToManyField("Host") # django将自动帮助创建关联表
对第三张表的数据操作
way1
# 通过类来操作数据库
obj = models.HostToApp.objects.create(hobj=1, aobj=2)
way2
obj = models.Application.objects.get(id=1)
obj.name
# 添加
obj.r.add(1)
obj.r.add(2)
obj.r.add(3,4,5)
obj.r.add(*[1,2,3,4])
# 删除
obj.r.remove(1)
obj.r.remove(2,3)
obj.r.remove(*[1,2,3])
# 清空
obj.r.clear()
# 更新
obj.r.set([3,4,5]) # 清空之前的所有,变成我现在设置的这个
# 获取值
obj.r.all() # 所有相关的主机对象"列表" QuerySet
项目地址:
https://github.com/Stark-Xue/test2
https://github.com/Stark-Xue/test3