首页 > 技术文章 > Python Day 58 Django框架、路由系统、视图函数、Django框架ORM框架(单表操作、一对多表、正反查询、双下划线方法)

liangzhenghong 2019-07-16 19:53 原文

  ##Django框架路由系统

1、伪静态
    cnblogs:网站中的地址:
          https://www.cnblogs.c om/linhaifeng/articles/7133167.html
    自己项目中的访问地址:
        http://127.0.0.1:8000/up_studnet/?id=12
    
    如何实现?
        路由分发
#2、路由分发
    url:
        url(r'^index/(\w+)/(\w+)/', index),
        url(r'^test/(?P<id>\w+)/(?P<name>\w+)/', test),
    对应函数:
    def index(request, name, id):
            print(id , name)
            return HttpResponse('index')
    def test(request, name, id):
            print(id , name)
            return HttpResponse('test')
    
    出现问题:
        1、index函数:在web端访问:
            http://127.0.0.1:8000/index/18/icon
            http://127.0.0.1:8000/index/icon/18
            会导致后台接收的id和name参数会随之变化
    解决方案:
        1、test函数:使用正则,然后起别名方式可以解决该问题
#3、路由正则
    url(r'^test2/$', test2)   
    思路:使用正则,当出现访问的地址不存在时,返回浏览器自定义的not fund错误
    url(r'^', notfound)  需要写到最下面
#4、反向路由:
优点:
      设置反向路由以后,只需要修改后台连接地址就可以,无需要动前端代码
后台url:
url(r'^logindjsajdbjsabdsabdbsabdhsabdhbsahbdsaasa/$', login, name='xxx')  
    xxx为自定义

前台:
<form action="{% url 'xxx' %}">
     <input type="text">
</form>

反向解析(带参数的)
  url(r'^indexxasdaskkdjlksajdlksaj/(\d+)/', index,name='index'),
  有名无名均按照下面方式使用即可:
    前端:{% url 'index' 1 %}
  后端:reverse('index',args=(1,))  #5、django创建app python3 manage.py startapp 自定义app名称 在settings.py配置文件中添加app02使其生效 INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', ‘app02’, ] app02参数介绍: admin.py : 写和django-admin相关的配置 apps: 对app的配置 models: 数据表模型 (********) tests: 测试 views: 视图函数 (*******#6、路由分组 浏览器访问:127.0.0.1:8000/app02/teachers 总:项目中urls.py; 先导入include from django.conf.urls import url,include 在路由分发中添加 url(r'^app02/', include('app02.urls')), url(r'^app03/', include('app03.urls')), 分:app02中urls.py: from app03 import views urlpatterns = [ url(r'^students/', views.studnets) ] 建议 大家使用:
  创建一个app, 然后在app的views.py中写自己的业务逻辑函数, urls.py 路由匹配, 只是进行分发

   ##Django框架视图函数


  我们之前写过的都是基于函数的view,就叫FBV。还可以把view写成基于类的。


  就拿我们之前写过的添加班级为例:


#
1、FBV:函数视图 function based view
  # FBV版添加班级
  def add_class(request):
      if request.method == "POST":
          class_name = request.POST.get("class_name")
          models.Classes.objects.create(name=class_name)
          return redirect("/class_list/")
      return render(request, "add_class.html")
#2、CBV:类视图 class based view 总:项目中urls urlpatterns = [ url(r'^app03/',include('app03.urls')), ] 分:app03中urls from app03 import views urlpatterns = [ url(r'^login/',views.Login.as_view()), ] 分:app03中视图函数views from django.views import View class Login(View): def get(self,request): return render(request,'login.html') def post(self,request): uname = request.POST.get('username') print(uname) return HttpResponse('ok') 分:templates目录下login.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/app03/login/" method="post"> <input type="text" name="username"> <input type="submit" value="tijiao"> </form> </body> </html> 浏览器:http://127.0.0.1:8000/app03/login/ get请求找类中get方法 post请求找类中post方法

  注意:

  使用CBV时,urls.py中也做对应的修改:
  # urls.py中
  url(r'^add_class/$', views.AddClass.as_view()),

#3、给视图加装饰器
  FBV本身就是一个函数,所以和给普通的函数加装饰器无差:
  
类中的方法与独立函数不完全相同,因此不能直接将函数装饰器应用于类中的方法 ,我们需要先将其转换为方法装饰器。
  Django中提供了method_decorator装饰器用于将函数装饰器转换为方法装饰器。
  如:
    # CBV版添加班级
    from django.views import View
    from django.utils.decorators import method_decorator

    class AddClass(View):

        @method_decorator(wrapper)
        def get(self, request):
            return render(request, "add_class.html")

        def post(self, request):
            class_name = request.POST.get("class_name")
            models.Classes.objects.create(name=class_name)
            return redirect("/class_list/") 
#4、参数介绍
    'get': 请求数据
    'post':提交数据
    'delete': 删除数据
    'put': 更新数据
    'patch': 更新部分数据

    ps:
        form表单提交 只支持get、post  
        ajax支持多个
    
    核心:
            def dispatch(self, request, *args, **kwargs):
                super(Login, self).dispatch(request, *args, **kwargs)
    dispatch方法:自定制的预处理操作:如权限管理,对登录时可以做一些预处理操作

   ##Django框架ORM

#ORM配置
"""
1、创建数据库
2、配置mysql的数据库链接
    setting文件里的DATABASES设置为
    DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 's8day61',    ## 数据库名称
        'USER': 'root',
        'PASSWORD': '123',    ## 安装 mysql 数据库时,输入的 root 用户的密码
        'HOST': '127.0.0.1',
    }
3、注册app
    也是在settings文件中的INSTALLED_APPS
    把你的app文件名加进去
4、需要把mysqldb设置为pymysql链接
    python3中用的是pymysql
    python2中使用的是mysqldb
    
    为了兼容,都改成pymysql
    app下的__init__文件
        import pymysql
        pymysql.install_as_MySQLdb()
5、创建表(2个命令)
    
    python manage.py makemigrations  ## 生成migrations文件
    
    python manage.py migrate  ### 根据生成的migrations文件生成表

"""

 

#案例:在app03中models.py建立模型表
from django.db import models

# Create your models here.
class Department(models.Model):
    # 主键id  在django中会帮我们创建,所以可以省略id字段
    title = models.CharField(max_length=32,null=True)

class Userinfo(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32,null=True)
    age = models.CharField(max_length=32,null=True)
    email = models.CharField(max_length=32,default="")
    # 默认会创建外键字段,字段名ud_id 回家一个_id
    ud = models.ForeignKey("Department",null=True)


#注意
模型表中的字段增删改查都需要刷新上述两个命令
python3  manage.py makemigrations
python3 manage.py migrate

 

#单表的增删改查

# 先导入models文件
from class_app import models
 ### 增加
# models.Department.objects.create(title="保安部")
# models.Department.objects.create(title="开发部")

### 查询
### 查询所有 ==> 列表里套对象
# res = models.Department.objects.all()
### <QuerySet [<Department: Department object>, <Department: Department object>]>
# for row in res:
#     print(row.id, row.title)

### 指定字段查询 values ==> 列表里套字典
### select title from department ;
# res = models.Department.objects.values("title").all()
# ### <QuerySet [{'title': '保安部'}, {'title': '开发部'}, {'title': '开发部'}]>
# for row in res:
#     print(row['title'])

### 指定字段查询 value_list==> 列表里套元组
# res = models.Department.objects.values_list("title").all()
# ### <QuerySet [('保安部',), ('开发部',), ('开发部',)]>
# print(res)

### select * from xxx where title = "开发部"  过滤
# res = models.Department.objects.filter(title='开发部').all()
#
# print(res)
# res = models.Department.objects.filter(id__lt = 3)   ### less then 小于
# res = models.Department.objects.filter(id__gt = 3)  ###  greater then 大于
## 取第一条数据
# res = models.Department.objects.all().first()
# print(res)
#
models.Classes.objects.filter(name="xxx").delete()

#
models.Classes.objects.filter(name="xxx").update(name="ooo")
# 如果需要改的值很多,并且在一个字典里,也可以用**打散
models.Classes.objects.filter(name="xxx").update(**dic)

 

#一对多表 
   ### 增加
    # models.UserInfo.objects.create(uname = "icon", age=15, email="dddd@qq.com", ud_id=2)
    # models.UserInfo.objects.create(uname = "创彬", age=16, email="gggg@qq.com", ud_id=2)
    # models.UserInfo.objects.create(uname = "owen", age=18, email="hhhh@qq.com", ud_id=1)

    # info = {"uname":'zekai2', 'age':13, "email":'123@qq.com', "ud_id":2}
    # models.UserInfo.objects.create(**info)


    ### 查询
    ### 正向查询
    # res = models.UserInfo.objects.all()
    # for row in res:
    #     print(row.id, row.uname, row.age, row.ud.title)

    ### 反向查询
    ### 写法: 小写的表名_set.all()
    # res = models.Department.objects.all()
    # for row in  res:
    #     print(row.title, row.userinfo_set.all())


    ### 神奇的双下画线
    res = models.UserInfo.objects.values('id', 'uname', "ud__title").all()
    print(res)

    res = models.UserInfo.objects.values_list('id', 'uname', "ud__title").all()
    print(res)

  

 

#django中orm的表的正查与反差

# 如果一张表和其他的表建有外键关系,那么从这张表查另一张表称为正查,反之称为反差
# 先建立两个外键关系的表
class Classes(models.Model):    # 如果我们不设置一张表的id时,django会自动帮我创建一个自增的主键id
    name = models.CharField(max_length=32,null=True)

class Students(models.Model):
    name = models.CharField(max_length=32,null=True)
    cid = models.ForeignKey("Classes",null=True)    # 会自动帮我们和另一张表的主键建立外键关系

# 正查
for obj in students:
    print(obj.cid.name)     # 可以直接通过对象点里面的属性就可以点出另一个类的对象,可以继续取值

# 反查
obj.student_set.all()       # 就是查出所有的对象

# 还可以通过下划线直接取到另一张表的值
# values是取出括号里对应的值,通过列表里套字典的形式
# values_list 是取出括号里对应的值, 通过列表里套元组的形式
models.Classes.objects.values("id","name","cid__name").all()

 

#双下划线
# 查询时通过外键名__另一张表的名字  可以查到关联表的值
# eg:
models.Classes.objects.values("id","name","cid__name").all()    #这个cid__name可以查询到关联表对应的name
# 查询时可以在filter中加入限制条件  __lt 代表小于  __gt代表大于
# eg:
models.Classes.objects.filter(id__lt = 3).all()     # id < 3
models.Classes.objects.filter(id__gte = 3).all()    # id >= 3

 

  

推荐阅读