Django——model(建表,增删改查,外键,多对多)
数据库操作
- dbfirst:数据库优先
- codefirst(ORM):代码优先,sqlalchemy和DJango都是用的这种
创建表
a.在app下的models.py中,创建类
from django.db import models class UserInfo(models.Model): #django会默认为我们生成一个自增且是主键的id列 uid = models.AutoField(primary_key=True) #当然也可以自己写,必须要这样写 username = models.CharField(max_length=32) # 用户名列,字符串类型,指定长度 password = models.CharField(max_length=64)
b.注册app(在settings下的INSTALLED_APPS中将app的名字添加进路径)
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01', ]
c.执行命令
python manage.py makemigrations python manage.py migrate
Django连接mysql
Django默认使用MySQLdb模块链接MySQL但MySQLdb只支持到python2.7,所以要进行以下操作
settings.py DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME':'dbname', 'USER': 'root', 'PASSWORD': 'xxx', 'HOST': '', 'PORT': '', } } 如下设置放置的与project同名的配置的__init__.py文件中 import pymysql pymysql.install_as_MySQLdb()
字段
- 字符串类型
- 数字类型
- 时间类型
- 二进制类型
字段的参数
a.数据库部分
null 数据库中字段是否可以为空 email = models.CharField(max_length=60,null=True) db_column 数据库中字段的列名 email = models.CharField(max_length=60,db_column='e-mail') default 数据库中字段的默认值 email = models.CharField(max_length=60,default='alex3714@163.com') primary_key 数据库中字段是否为主键 uid = models.AutoField(primary_key=True) #AutoField 自增
db_index 数据库中字段是否可以建立索引 unique 数据库中字段是否可以建立唯一索引 unique_for_date 数据库中字段【日期】部分是否可以建立唯一索引 unique_for_month 数据库中字段【月】部分是否可以建立唯一索引 unique_for_year 数据库中字段【年】部分是否可以建立唯一索引
auto_now 创建时自动生成当前时间 uptime = models.DateTimeField(auto_now=True, null=True) auto_now_add 更新时,自动更新为当前时间 ctime = models.DateTimeField(auto_now_add=True, null=True) obj = UserGroup.objects.filter(id=1).update(caption='CEO') #使用这种方式更新时不能记录 obj = UserGroup.objects.filter(id=1).first() obj.caption = "CEO" obj.save()
b.admin/modelform部分
verbose_name Admin中显示的字段名称 blank Admin中是否允许用户输入为空 editable Admin中是否可以编辑 help_text Admin中该字段的提示信息 choices Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作 如:gf = models.IntegerField(choices=[(0, '何穗'),(1, '大表姐'),],default=1) error_messages 先pass,自定义错误信息(字典类型),从而定制想要显示的错误信息; 字典键:null, blank, invalid, invalid_choice, unique, and unique_for_date 如:{'null': "不能为空.", 'invalid': '格式错误'} validators pass
#小tips:数据库中的EmailField,URLFiled等是给admin用的
1 from django.db import models 2 3 # Create your models here. 4 5 class UserInfo(models.Model): 6 username = models.CharField(max_length=32, verbose_name='用户名') # 用户名列,字符串类型,指定长度 7 password = models.CharField(max_length=60, help_text='pwd') 8 email = models.CharField(max_length=60,null=True,blank=True) 9 test = models.EmailField(max_length=19, null=True) 10 text = models.CharField(max_length=20,null=True,editable=False)
2、根据类对数据库表中的数据进行各种操作
对数据库的增、删、改、查
views.py from cmdb import models def orm(request): #增,建议用前两种 models.UserInfo.objects.create(username='root',password='123') dic={'username':'alex','password':'321'} models.UserInfo.objects.create(**dic) obj = models.UserInfo(username='x54256',password='666') obj.save() #查,filter<==>where查询条件 result = models.UserInfo.objects.all() #拿到所有的 #Query[obj1(uid,username,password),obj2(uid,username,password),obj3(uid,username,password)] for i in result: print(i.uid,i.username,i.password) result = models.UserInfo.objects.filter(username='root') for item in result: print(item.uid,item.username,item.password)
#小tips:result.query==>查看当前sql语句
result = models.UserInfo.objects.filter(username='root',password='123').first() #直接取得就是Query对象
print(result.uid,...)
#删 models.UserInfo.objects.filter(username='root').delete() #改 models.UserInfo.objects.filter(id=3).update(password=147) return HttpResponse('abc')
5种查询方法(元组,字典方法)
v1 = models.Host.objects.all() # QuerySet[obj(id,hostname),obj,...],内部元素都是对象 v2 = models.Host.objects.all().values('hostname','ip','port','b_id','b__caption') #b连接的外键 在元组和字典格式里跨表查询时要用"__" # QuerySet[{'hostname':c1,'ip':1.1.1.1,'port':80,'b_id':2,'b__caption':abc},{},...],内部元素都是字典 v3 = models.Host.objects.all().values_list('hostname', 'ip', 'port', 'b__caption') # QuerySet[(c1,1.1.1.1,80,2,abc),(),...],内部元素都是元组 models.Business.objects.get(id=1) # 获取到的一个对象,如果不存在就报错 获取到一个对象或者None : models.Business.objects.filter(id=1).first() #***建议用这种 return render(request,'host.html',{'v1':v1,'v2':v2,'v3':v3,'b_list':b_list})
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 <h1>业务线列表(对象)</h1> 9 <ul> 10 {% for i in v1 %} 11 <li>{{ i.id }}-{{ i.caption }}-{{ i.code }}</li> 12 {% endfor %} 13 </ul> 14 <h1>业务线列表(字典)</h1> 15 <ul> 16 {% for i in v2 %} 17 <li>{{ i.id }}-{{ i.caption }}</li> 18 {% endfor %} 19 </ul> 20 <h1>业务线列表(元组)</h1> 21 <ul> 22 {% for i in v3 %} 23 <li>{{ i.0 }}-{{ i.1 }}</li> 24 {% endfor %} 25 </ul> 26 27 28 </body> 29 </html>
一对多(绑外键)
from django.db import models # Create your models here. class UserInfo(models.Model): uid = models.AutoField(primary_key=True) username = models.CharField(max_length=32, verbose_name='用户名') # 用户名列,字符串类型,指定长度 password = models.CharField(max_length=60, help_text='pwd') email = models.CharField(max_length=60,null=True) user_group = models.ForeignKey("UserGroup", to_field='id') #绑定UserGroup的id列(绑定的列必须每一行都是唯一的,不写to_field的默认绑主键) class UserGroup(models.Model): caption = models.CharField(max_length=32) ctime = models.DateTimeField(auto_now_add=True, null=True) uptime = models.DateTimeField(auto_now=True, null=True) user_type_choices = ( # 内存中存放 (1, '超级用户'), (2, '普通用户'), (3, '普普通用户'), ) user_type_id = models.IntegerField(choices=user_type_choices,default=1) #默认值是1
Django默认为我们生成了一个user_group_id代表着外键连接的表的id
def orm(request): result = models.UserInfo.objects.all() # 拿到所有的 # Query[obj1(uid,username,password,email,user_group_id),obj2(...),obj3(...)] for i in result: #i.user_group_id==>所绑的id #i.user_group==>是绑定的那个飚的对象,so可以用i.user_group.另一个表的内容 print(i.id,i.user_group_id,i.user_group.caption)
小Tips:
数据库中的EmailField,URLFiled等是给admin用的
result.query==>查看当前sql语句(result是Query对象)
default=1 ==> #默认值是1
多对多
方式一:自定义关系表(直接创建第3张表,想有多长就有多长)***
class Host(models.Model): nid = models.AutoField(primary_key=True) hostname = models.CharField(max_length=32,db_index=True) ip = models.GenericIPAddressField(protocol="ipv4",db_index=True) port = models.IntegerField() b = models.ForeignKey(to="Business", to_field='id') class Application(models.Model): name = models.CharField(max_length=32) class HostToApp(models.Model): hobj = models.ForeignKey(to='Host',to_field='nid') aobj = models.ForeignKey(to='Application',to_field='id') #可以直接对第三张表进行操作 #增 HostToApp.objects.create(hobj_id=1,aobj_id=2)
方式二:自动创建关系表
class Host(models.Model): nid = models.AutoField(primary_key=True) hostname = models.CharField(max_length=32,db_index=True) ip = models.GenericIPAddressField(protocol="ipv4",db_index=True) port = models.IntegerField() b = models.ForeignKey(to="Business", to_field='id') class Application(models.Model): name = models.CharField(max_length=32) r = models.ManyToManyField("Host") #无法直接对第三张表进行操作 #但我们可以间接操作第三张表呀 obj = Application.objects.get(id=1) obj.name obj.r.add(2) #在id=1下添加id=2 obj.r.add(*[1,2,3,4]) #在id=1下添加id=1,2,3,4 obj.r.remove(2) #删除id=1下的id=2 obj.r.remove(*[1,2,3]) #添加删除列表 要加* obj.r.clear() #删除所有id=1的 obj.r.set([3,5,7]) #删除所有id=1的,添加1 3,1 5,1 7 而且不加* obj.r.all() # 所有相关的主机对象QuerySet"列表" ,(一开始我也是不信的)
1 def cla_stu_add(request): 2 3 class_name = request.POST.get('class_name') 4 student_list = request.POST.getlist('student_list') 5 6 obj = models.classes.objects.create(name=class_name) 7 obj.r.add(*student_list) 8 9 return redirect('/cmdb/classes') 10 11 12 def cla_stu_edit(request): 13 14 pass
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 <style> 7 .hide{ 8 display: none; 9 } 10 .shade{ 11 position: fixed; 12 top: 0; 13 right: 0; 14 left: 0; 15 bottom: 0; 16 background: black; 17 opacity: 0.6; 18 z-index: 100; 19 } 20 .add-modal,.delete{ 21 position: fixed; 22 height: 300px; 23 width: 400px; 24 top:100px; 25 left: 50%; 26 z-index: 101; 27 border: 1px solid red; 28 background: white; 29 margin-left: -200px; 30 } 31 </style> 32 </head> 33 <body> 34 <div class="shade hide"></div> 35 <div class="add-modal hide"> 36 <form class="form_edit" method="post" action="/cmdb/cla_stu_edit/"> 37 <p><input type="text" id="stu_name" name="stu_name" placeholder="学生姓名" /><span style="color: red">*</span></p> 38 39 <p><select name="cla_stu_edit" id="cla_stu_edit" multiple > 40 {% for i in student_list %} 41 <option value="{{ i.sid }}">{{ i.stu_name }}</option> 42 {% endfor %}</select></p> 43 <input id="i2" type="submit" value="确认" /> 44 </form> 45 </div> 46 47 48 <form action="/cmdb/cla_stu_add/" method="post"> 49 <input type="text" placeholder="课程名" name="class_name" /> 50 <select name="student_list" multiple> 51 {% for i in student_list %} 52 <option value="{{ i.sid }}">{{ i.stu_name }}</option> 53 {% endfor %} 54 </select> 55 <input type="submit" value="添加"/> 56 57 </form> 58 59 <table border="1"> 60 <thead> 61 <tr> 62 <th>课程名</th><th>学生列表</th> 63 </tr> 64 </thead> 65 <tbody> 66 {% for row in classes_list %} 67 <tr> 68 <td rid="{{ row.id }}">{{ row.name }}</td> 69 <td> 70 {% for i in row.r.all %} 71 <span sid="{{ i.sid }}">{{ i.stu_name }}</span> 72 {% endfor %} 73 </td> 74 <td><a class="edit">编辑</a>|<a>删除</a></td> 75 </tr> 76 {% endfor %} 77 </tbody> 78 </table> 79 <script src="/static/jquery-1.12.4.js"></script> 80 <script> 81 $(".edit").click(function () { 82 var sid_list = []; 83 $(this).parent().prev().each(function () { 84 var sid = $(this).attr('sid'); 85 sid_list.push(sid) 86 }); 87 $('#cla_stu_edit').val(sid_list); 88 89 $('.hide').removeClass('hide') 90 91 }) 92 </script> 93 </body> 94 </html>