django入门基础
Posted 向前跑,带着冷眼与嘲笑
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了django入门基础相关的知识,希望对你有一定的参考价值。
首先要说的是django与其他的框架不同,django是一个封装的及其完善的框架,我们使用django也不会像之前写学生系统那样,django操作数据库使用自带的ORM来进行操作,Torando与Flask的数据库使用就很自由(当然也可以使用我们之前的SQL helper),并且Flask的模板都不是自带的而是使用的第三方插件。
首先创建一个工程:
django-admin startproject mysite
创建一个应用:
python manage.py starapp app01
每一个新建的app下都有几个文件:
migrations文件夹,存放数据库的相关信息;
admin.py文件,Django自带后台管理相关配置;
modals.py,ORM的相关操作;
tests.py,单元测试;
views文件夹或者文件,业务处理。
路由系统
之前的学生系统传递nid都是通过url进行传递,这样导致链接的seo权重比较低,所以我们可以进行简单的优化。
动态路由:当一条url被路由url(r\'^edit/(\\w+)/\', views.edit)匹配到,那么在视图函数中定义的函数就要传入额外的参数来盛放被正则匹配到的值。
#url url(r\'^edit/(\\w+)/(\\w+)/\', views.edit) #视图函数 def edit(request,a1,a2): print(a1) print(a2) return HttpResponse(\'...\')
上面的例子是顺序传参,当然也可以指定传参,
#指定传参 url(r\'^edit/(?P<a2>\\w+)/(?P<a1>\\w+)/\', views.edit)
#视图函数
def edit(request,a2,a1):
print(a1)
print(a2)
return HttpResponse(\'...\')
注:这两种传参方式不可以混着用,与函数传参不同的是此处的传参不可以用*args和**kwargs接收。
伪静态:
终止符: ^edit$ 伪静态: url(r\'^edit/(\\w+).html$\', views.edit),
路由分发
为了防止不同业务线(app)的开发过程中出现的名称重复,所以才有了路由分发的必要性。
from django.conf.urls import url,include urlpatterns = [ url(r\'^app01/\', include(\'app01.urls\')),]
这样路由进来就被分发到app01里面的urls进行进一步路由匹配。
别名与反向生成url
url(r\'^edit/(\\w+)/(\\w+)/\', views.edit,name=\'n2\') #name就是别名 #在视图函数中: from django.urls import reverse v = reverse(\'n2\',args=(1111,)) #url要是指定传参,reverse里就要用kwargs存放字典指定返回值。
反生成url可应用在html页面中,
#url(r\'^login/\', views.login,name=\'m1\'), # def login(request): # return render(request,\'login.html\') #login.html <form method="POST" action="{% url "m1" %}"> <input />
这里的{% url "m1" %}会被渲染成能被^login/匹配的地址。
url(r\'^edit/(\\w+)/\', views.edit,name=\'n2\'),
{% url "n2" i %}与/edit/{{ i }}/一样,这里n2先被替换成正则前半部分,后面匹配的部分由i传参进去。
ORM框架
ORM一般用来做原生数据库语句转换,使我们开发更为高效。ORM不仅可以进行数据行的增删改查操作,还可以创建,修改,删除数据表(所以功能很强大,可以完成大部分的数据库操作)。
注:python没有办法创建数据库,只能是连接数据库。
ORM利用pymysql等第三方工具连接数据库(不能直接链接数据库,并且默认不是连接MySQL而是SQLlite)。而且默认链接MySQL的是MySQLDB模块。python3默认没装MySQLDB模块,所以最方便就是更改它默认连接MySQL的配置。
#默认 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\': \'\', } }
最后,我们还需要更改project下面的init,
import pymysql pymysql.install_as_MySQLdb()
这样我们就可以使用ORM操作pymysql连接MySQL数据库了。
models文件中创建数据表的各项属性:
from django.db import models class UserInfo(models.Model):#必须继承 """ 员工 """ nid = models.BigAutoField(primary_key=True)#自增可不写 user = models.CharField(max_length=32) password = models.CharField(max_length=64)#位数也很重要 age = models.IntegerField(default=1)
接着要在INSTALLED_APPS[]里加入我们注册的app名。
INSTALLED_APPS = [ \'django.contrib.admin\', \'django.contrib.auth\', \'django.contrib.contenttypes\', \'django.contrib.sessions\', \'django.contrib.messages\', \'django.contrib.staticfiles\', \'mysite\', ]
最后一步,在终端输入
python manage.py makemigrations
python manage.py migrate
再去查看数据库就会增加很多表,其中app01_userinfo才是我们刚才创建的那张表。
这两行操作就是在app下migrations生成配置文件相关操作,migrate拿着配置信息去数据库进行相关操作。
以后我们要是修改表的名字就直接修改类,然后再次在终端执行这两条命令即可,当然比如要增加一行数据(例如UserInfo表里的最后一行age),如果之前有数据,之前的数据可没有age参数,那该怎么办呢,要么把这行数据设置为null允许为空,要么就设置默认值。
外键创建
class UserGroup(models.Model): """ 部门 """ title = models.CharField(max_length=32) class UserInfo(models.Model): """ 员工 """ nid = models.BigAutoField(primary_key=True) user = models.CharField(max_length=32) password = models.CharField(max_length=64) age = models.IntegerField(default=1) # ug_id ug = models.ForeignKey("UserGroup",null=True)
ug = models.ForeignKey("UserGroup",null=True)默认在数据库中多出来的数据是ug_id。
ORM的增删改查
增
models.UserGroup.objects.create(title=\'销售部\')
查
group_list = models.UserGroup.objects.all()#所有 group_list = models.UserGroup.objects.filter(id=1)#过滤 group_list = models.UserGroup.objects.filter(id__gt=1)#神奇的双下划线
删
models.UserGroup.objects.filter(id=2).delete()
更新
models.UserGroup.objects.filter(id=2).update(title=\'公关部\')
# 数据库相关操作 def index(request): # 增删改查 from app01 import models # 新增 # models.UserGroup.objects.create(title=\'销售部\') # models.UserInfo.objects.create(user=\'root\',password=\'pwd\',age=18,ug_id=1) # 查找 # group_list = models.UserGroup.objects.all() # group_list = models.UserGroup.objects.filter(id=1) # group_list = models.UserGroup.objects.filter(id__gt=1) # group_list = models.UserGroup.objects.filter(id__lt=1) # 删除 # models.UserGroup.objects.filter(id=2).delete() # 更新 models.UserGroup.objects.filter(id=2).update(title=\'公关部\') # group_list QuerySet类型(列表) # QuerySet类型[obj,obj,obj] # print(group_list) # for row in group_list: # print(row.id,row.title) # models.UserInfo.objects.all() group_list = models.UserGroup.objects.all() return render(request,\'newindex.html\',{"group_list": group_list})
这里我们查找的group_list是形似列表的QuerySet类型。QuerySet类型可以理解为[obj,obj,obj]。
for row in group_list: print(row.id,row.title)
同理在前端一样适用
{% for row in group_list %} <li>{{ row.id }} === {{ row.title }}</li> {% endfor %}
ORM之连表操作
我们之前的两张表,通过外键连接,其中ut直接连接UserType,ut代指了usertype的一行数据,我们可以直接使用ut.title直接跨表查询。
from django.db import models class UserType(models.Model): """ 用户类型 """ title = models.CharField(max_length=32) class UserInfo(models.Model):#必须继承 """ 员工 """ id = models.BigAutoField(primary_key=True)#自增可不写 name = models.CharField(max_length=32) age = models.IntegerField(default=1) # ug_id ut = models.ForeignKey("UserType",null=True)#外键操作 #创建用户数据 from app01 import models def test(request): # 创建数据 # models.UserType.objects.create(title=\'普通用户\') # models.UserType.objects.create(title=\'二逼用户\') # models.UserType.objects.create(title=\'牛逼用户\') #不要重复添加 # models.UserInfo.objects.create(name=\'方\',age=18,ut_id=1) # models.UserInfo.objects.create(name=\'由\',age=18,ut_id=2) # models.UserInfo.objects.create(name=\'刘\',age=18,ut_id=2) # models.UserInfo.objects.create(name=\'陈\',age=18,ut_id=3) # models.UserInfo.objects.create(name=\'王\',age=18,ut_id=3) # models.UserInfo.objects.create(name=\'杨\',age=18,ut_id=1) return HttpResponse(\'...\')
# 获取 # result取到的是QuerySet[obj,obj,obj] result = models.UserInfo.objects.all() for obj in result: print(obj.name,obj.age,obj.ut_id,obj.ut.title)#直接就连表取到值
# UserInfo,ut是FK字段 - 正向操作 PS: 一个用户只有一个用户类型 obj = models.UserInfo.objects.all().first()#取出第一个queryset数据 print(obj.name,obj.age,obj.ut.title)#因为obj只是一个数据只能对应一种用户
# UserType, 表名小写_set.all() - 反向操作 PS: 一个用户类型下可以有很多用户 obj = models.UserType.objects.all().first() print(\'用户类型\',obj.id,obj.title) for row in obj.userinfo_set.all():#obj.userinfo_set里是userinfo的query对象,.all()取出所有数据 print(row.name,row.age)
#反向取出每一行的queryset result = models.UserType.objects.all() for item in result:#相当于取出每一行用户类型对应的用户的queryset for i in item.userinfo_set.all(): print(i.name) #过滤每一行 result = models.UserType.objects.all().filter(id= 1 )#<QuerySet [<UserType: UserType object>]> for item in result: print(item.userinfo_set.filter(id =1))#<QuerySet [<UserInfo: UserInfo object>]>
result = models.UserInfo.objects.all().values(\'id\',\'name\')#只取两列 # 并且每列的QuerySet[{\'id\':\'xx\',\'name\':\'xx\'} ]都是这样的字典 for row in result: print(row) result2 = models.UserInfo.objects.all().first() print(result2)#UserInfo object
result = models.UserInfo.objects.all().values_list(\'id\',\'name\') # QuerySet[(1,\'f\'), ] for row in result: print(row)
当取出的queryset里面是obj对象的时候,可以直接在for循环里跨表,但是当取出的queryset里是字典或者元祖对象的时候,那么在for循环里就不可以跨表了,这时候就要使用神奇的双下划线 models.UserInfo.objects.filter(id__gt=1).values(\'id\',\'name\')#可以取到id>1的queryset对象。 # [{id:1,name:fd},{id:1,name:fd},{id:1,name:fd},] # models.UserInfo.objects.all().values(\'id\',\'name\') # models.UserInfo.objects.filter(id__gt=1).values(\'id\',\'name\') # 无法跨表 # result = models.UserInfo.objects.all().values(\'id\',\'name\') # for item in result: # print(item[\'id\'],item[\'name\']) # 夸表 __ # result = models.UserInfo.objects.all().values(\'id\',\'name\',"ut__title") # for item in result: # print(item[\'id\'],item[\'name\'],item[\'ut__title\']) # [(1,df),(2,\'df\')] # models.UserInfo.objects.all().values_list(\'id\',\'name\') # models.UserInfo.objects.filter(id__gt=1).values_list(\'id\',\'name\') # 无法跨表 # result = models.UserInfo.objects.all().values_list(\'id\',\'name\') # for item in result: # print(item[0],item[1]) # 夸表 __ # result = models.UserInfo.objects.all().values_list(\'id\',\'name\',"ut__title") # for item in result: # print(item[0],item[1],item[2])
v = models.UserInfo.objects.values(\'id\',\'name\') # 6 v = models.UserInfo.objects.values(\'id\',\'name\',\'ut__title\') # 6 # select * from userinfo left join usertype v1 = models.UserType.objects.values(\'id\',\'title\') print(v1) # 4 v2 = models.UserType.objects.values(\'id\',\'title\',\'userinfo__name\') print(v2) #7 # select * from usertype left join userinfo #正向跨表与反向跨表与left join类似,谁在前面就是查他的所有,没有匹配到的那一行值为none填充 正: 1. q = UserInfo.objects.all().first() q.ug.title 2. UserInfo.objects.values(\'nid\',\'ug_id\') UserInfo.objects.values(\'nid\',\'ug_id\',\'ug__title\') 3. UserInfo.objects.values_list(\'nid\',\'ug_id\',\'ug__title\') 反: 1. 小写的表名_set obj = UserGroup.objects.all().first() result = obj.userinfo_set.all() [userinfo对象,userinfo对象,] 2. 小写的表名 v = UserGroup.objects.values(\'id\',\'title\') v = UserGroup.objects.values(\'id\',\'title\',\'小写的表名称\') v = UserGroup.objects.values(\'id\',\'title\',\'小写的表名称__age\') 3. 小写的表名 v = UserGroup.objects.values_list(\'id\',\'title\') v = UserGroup.objects.values_list(\'id\',\'title\',\'小写的表名称\') v = UserGroup.objects.values_list(\'id\',\'title\',\'小写的表名称__age\')
正向:
xxxx.filter(ut__title=\'超级用户\').values(\'id\',\'name\',\'ut__title\')
反向:
xxxx.filter(表名称__title=\'超级用户\').values(\'id\',\'name\',\'表名称__title\')
# 1.增删改查 # 2. 一般: # models.UserInfo.objects.filter(id__gt=1) # models.UserInfo.objects.filter(id__lt=1) # models.UserInfo.objects.filter(id__lte=1) # models.UserInfo.objects.filter(id__gte=1) # models.UserInfo.objects.filter(id__in=[1,2,3]) # models.UserInfo.objects.filter(id__range=[1,2]) # models.UserInfo.objects.filter(name__startswith=\'xxxx\') # models.UserInfo.objects.filter(name__contains=\'xxxx\') # models.UserInfo.objects.exclude(id=1) # 3. 排序 user_list = models.UserInfo.objects.all().order_by(\'-id\',\'name\') # 4. 分组 from django.db.models import Count,Sum,Max,Min # v =models.UserInfo.objects.values(\'ut_id\').annotate(xxxx=Count(\'id\')) # print(v.query) # v =models.UserInfo.objects.values(\'ut_id\').annotate(xxxx=Count(\'id\')).filter(xxxx__gt=2) # print(v.query)having # v =models.UserInfo.objects.filter(id__gt=2).values(\'ut_id\').annotate(xxxx=Count(\'id\')).filter(xxxx__gt=2) # print(v.query)where # 5. F,更新时用于获取原来的值 # from django.db.models import F,Q # models.UserInfo.objects.all().update(age=F("age")+1) # 6. Q,用于构造复杂查询条件 # 应用一: # models.UserInfo.objects.filter(Q(id__gt=1)) # models.UserInfo.objects.filter(Q(id=8) | Q(id=2)) # models.UserInfo.objects.filter(Q(id=8) & Q(id=2)) # 应用二: # q1 = Q() # q1.connector = \'OR\' # q1.children.append((\'id__gt\', 1)) # q1.children.append((\'id\', 10)) # q1.children.append((\'id\', 9)) # # # q2 = Q() # q2.connector = \'OR\' # q2.children.append((\'c1\', 1)) # q2.children.append((\'c1\', 10)) # q2.children.append((\'c1\', 9)) # # q3 = Q() # q3.connector = \'AND\' # q3.children.append((\'id\', 1)) # q3.children.append((\'id\', 2)) # q2.add(q3,\'OR\') # # con = Q() # con.add(q1, \'AND\') # con.add(q2, \'AND\') # (id=1 or id = 10 or id=9 or (id=1 and id=2)) and (c1=1 or c1=10 or c1=9) # models.UserInfo.objects.filter(con) # condition_dict = { # \'k1\':[1,2,3,4], # \'k2\':[1,], # } # con = Q() # for k,v in condition_dict.items(): # q = Q() # q.connector = \'OR\' # for i in v: # q.children.append((\'id\', i)) # con.add(q,\'AND\') # models.UserInfo.objects.filter(con) # 7. extra, 额外查询条件以及相关表,排序 models.UserInfo.objects.filter(id__gt=1) models.UserInfo.objects.all() # id name age ut_id models.UserInfo.objects.extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None) # a. 映射 # select # select_params=None # select 此处 from 表 # b. 条件 # where=None # params=None, # select * from 表 where 此处 # c. 表 # tables # select * from 表,此处 # c. 排序 # order_by=None # select * from 表 order by 此处 models.UserInfo.objects.extra( select={\'newid\':\'select count(1) from app01_usertype where id>%s\'}, select_params=[1,], where = [\'age>%s\'], params=[18,], order_by=[\'-age\'], tables=[\'app01_usertype\'] ) """ select app01_userinfo.id, (select count(1) from app01_usertype where id>1) as newid from app01_userinfo,app01_usertype where app01_userinfo.age > 18 order by app01_userinfo.age desc """ result = models.UserInfo.objects.filter(id__gt=1).extra( where=[\'app01_userinfo.id < %s\'], params=[100,], tables=[\'app01_usertype\'], order_by=[\'-app01_userinfo.id\'], select={\'uid\':1,\'sw\':"select count(1) from app01_userinfo"} ) print(result.query) # SELECT (1) AS "uid", (select count(1) from app01_userinfo) AS "sw", "app01_userinfo"."id", "app01_userinfo"."name", "app01_userinfo"."age", "app01_userinfo"."ut_id" FROM "app01_userinfo" , "app01_usertype" WHERE ("app01_userinfo"."id" > 1 AND (app01_userinfo.id < 100)) ORDER BY ("app01_userinfo".id) DESC # 8. 原生SQL语句 from django.db import connection, connections cursor = connection.cursor() # connection=default数据 cursor = connections[\'db2\'].cursor() cursor.execute("""Django基础之model操作数据库model基础入门推荐