• Django


                    前戏

    一.http协议

    1.url:协议://域名(IP)+端口(80)/路径?参数(a=1&b=2)

    2.基于请求响应

    3.基于TCP协议

    4.请求协议格式

      请求首行  请求方式 url(路径?get请求参数) 协议/版本号

      请求头   key:value

      请求体   数据(只有post请求才会有请求体)

      User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36

    二.Django的下载安装

    1.django:pip3 install django == 2.1.1

    2.创建Django项目:django-admin.py startproject 项目名称

    3.创建应用:python manage.py startapp app名称

    4.启动项目:python manage.py runserver IP:PORT

    项目名称

      --manage.py   #启动文件   与项目交互命令

      --项目名称

        ----settings.py:配置信息

        ----urls:路径与视图函数的映射

        ----wsgi:封装socket

      app01

        ----models:存放与该app相关的表结构

        ----view:存放与该app相关的视图函数

                    正戏

    一.url控制器

      urls.py:请求路径与视图函数的映射关系

      (1)简单使用:通过正则分组获取url中的动态参数

      (2)有名分组:给分组起一个名字,实现关键字传参

      (3)分  发:把每一个app自己的url分发各自的路由文件

      (4)反向解析:不要硬编码url,通过别名解析url

    二.视图函数

      request(请求对象)

        request.method 请求方式

        request.path 请求路径

        request.POST POST的请求数据,字典格式

        request.GET GET的请求数据,字典格式

        request.META 请求头

        request.get_full_path()

        request.is_ajax()

      request(响应对象)

         三种形式:

          1.HttpResponse("字符串")

          2.render("页面")

            ---读取文件字符串

            ---渲染变量

          3.redirect() #重定向

    三.模板语法

    服务器发送请求:

      1.地址栏输入url  默认get方式

      2.form表单发请求  可以设置get或post

      3.a标签发请求  

    四.ORM(object relation mapping)

        类----------表

    类属性-----表字段

    类对象-----表记录

     数据库的迁移:django会把setting中的INSTALLED_APPS中每一个应用中models对应类创建成数据库中的表

    python manage.py makemigrations   同步

    python manage.py migrate

    新的数据类型:QuerySet  [obj1,obj2....]

    1.添加记录

    #方式1:

    book=Book(title="python",price=123,pub_date="2012-12-12",publish="人民出版社")
    book.save()
    

    #方式2:

    book=Book.objects.create(title="python",price=123,pub_date="2012-12-12",publish="人民出版社")
    

    2.查询记录

    (1)all(): 调用者:objects管理器   返回queryset

    (2)filter(): 调用者:objects管理器  返回queryset

    (3)get():  调用者:objects管理器  返回查询到model对象(注意,查询结果有且只有一个才会执行,否则报错)

    (4)first(),last()方法: 调用者:queryset  返回model对象

    (5)exclude(): 调用者:objects管理器  返回queryset

    (6)order_by(): 由queryset对象调用,返回值是queryset

    (7)count: 数数: 由queryset对象调用返回int

    (8)reverse(): 由queryset对象调用,返回值是queryset

    (9)exists(): 由queryset对象调用,返回布尔值

    (10)values()方法: 由queryset对象调用,返回值是queryset

    (11)values_list(): 由queryset对象调用,返回值是queryset

    (12)distinct(): 由queryset对象调用,返回值是queryset

    模糊查询(双下划线)

    Book.objects.filter(price__in=[100,200,300])
    Book.objects.filter(price__gt=100)
    Book.objects.filter(price__lt=100)
    Book.objects.filter(price__range=[100,200])
    Book.objects.filter(title__contains="python")
    Book.objects.filter(title__icontains="python")
    Book.objects.filter(title__startswith="py")
    Book.objects.filter(pub_date__year=2012)

    3.删除记录

    Book.objects.filter(price=100).delete()
    

    4.修改记录

    Book.objects.filter(id=edit_book_id).update(price=111)
    
    Book.objects.filter(price=111).update(publish="南京出版社")
    

    五.ORM的多表操作

    1.操作记录

    一对多:

      方式1

    publish_obj=Publish.objects.get(nid=1)
    book_obj=Book.objects.create(title="追风筝的人",publishDate="2012-12-21",price=100,publish=publish_obj)
    

      方式2:

    book_obj=Book.objects.create(title="追风筝的人",publishDate="2012-12-21",price=100,publish_id=1) 
    book_obj.publish:与这本书关联出版社对象

    多对多操作:

      核心:第三张关系表添加记录

    app01_book_author
                id    book_id    author_id
                1         1          1
                2         1          2
                3         2          2
    autor
                id      name
                1          liu
                2          wu
    

      book_obj.author.add(1,2)

      book_obj.author.remove(1)

      book_obj.author.clear()

      book_obj.author.set(3) 清空后设置id

      book_obj.author.all()  查询与这本书关联的所有queryset的集合

    2.基于对象的跨表查询(基于子查询)

    正向查询

      一对多:

              正向查询按字段:book.publish
    Book----------------------------------->Publish
          <-------------------------------------
        反向查询表名小写_set.all():pub_obj,book_set.all()
    

      多对多:

                正向查询字段book.author.all()
    Book------------------------------------->Author
          <----------------------------------------
      反向查询按表名小写_set.all():liu.book_set.all()
    

      一对一:

                    正向查询字段 liu.info
    Author------------------------------>AuthorInfo
            <---------------------------------
            反向查询按表名小写  info.author    
    

      总结:正向查询按字段;反向查询得到一个对象,按表名小写,可能得到多个对象,按表名小写_set().all()

    3.基于双下划线的跨表查询(基于join实现的)

    创建表结构

    from django.db import models
     
     
    class Book(models.Model):
        title=models.CharField(max_length=32)
        publishDate=models.DateField()
        price=models.DecimalField(max_digits=5,decimal_places=2)
     
        # 出版社可以发布多部书(一对多)
        publish=models.ForeignKey('Publish')
     
     
        # 一个人可以写多本书,一本书也可以由多个人撰写(多对多)
        authorList=models.ManyToManyField('Author')
     
    class Author(models.Model):
        name=models.CharField(max_length=32)
        age=models.IntegerField()
        addr=models.CharField(max_length=32)
        tel=models.CharField(max_length=13)
     
    class Publish(models.Model):
        name=models.CharField(max_length=32)
        addr=models.CharField(max_length=32)
    

    编写views代码,查询实现

    def index(request):
        bookobj = models.Book.objects.all()
        # 练习1:  查询人民出版社出版过的所有书籍的名字与价格(一对多)
        # ret = models.Book.objects.filter(publish__name='山西出版社').values_list('title')
        # ret = models.Publish.objects.filter(name='山西出版社').values_list('book__title','book__authorList__name')
        # ret = models.Author.objects.filter(book__publish__name='山西出版社').values_list('book__title')
        # 练习2: 查询egon出过的所有书籍的名字(多对多)
        # ret = models.Book.objects.filter(authorList__name='alex').values_list('title')
        # ret =models.Author.objects.filter(name='alex').values_list('book__title')
        # 练习3: 查询人民出版社出版过的所有书籍的名字以及作者的姓名
        # ret = models.Publish.objects.filter(name='机械先驱出版社').values_list('book__title','book__authorList__name')
        # ret = models.Book.objects.filter(publish__name='机械先驱出版社').values_list('title','authorList__name')
        # ret = models.Author.objects.filter(book__publish__name='机械先驱出版社').values_list('book__title','name')
        # 练习4: 手机号以151开头的作者出版过的所有书籍名称以及出版社名称
        # ret = models.Author.objects.filter(tel__startswith='158').values_list('book__title','book__publish__name')
        # ret =models.Publish.objects.filter(book__authorList__tel__startswith='158').values_list('book__title','name')
        # ret = models.Book.objects.filter(authorList__tel__startswith='158').values_list('publish__name','title')
        # print(ret)
        return HttpResponse('OK')

    六.Ajax

    浏览器向服务端发送请求的形式:

    1.地址栏输入url 默认get方式

    2.form表单的提交按钮 默认get方式

    3.a标签 默认get

    4.Ajax特点:

      1.异步

      2.局部刷新

    $.ajax({
                url:"/cal/",
                type:"post",
                data:{
                    num1:num1,
                    num2:num2,
                    csrfmiddlewaretoken:$("[name='csrfmiddlewaretoken']").val()
                },
                success:function(response){
                    console.log(reponse);
                    $("#ret").val(reponse)
                }
            })
    View Code

     json数据

    -------------------------------------
    | Python         |Json               |
    =====================
    | dict              |object          |
    =====================
    | list,tuple       |array            |
    =====================
    | str                |string         |
    =====================
    | int,float         |number          |
    =====================
    | True              |true            |
    =====================
    | False             |false           |
    =====================
    | None             |null             |
    --------------------------------------
    

    ContentType

      request.POST

      request.GET

      request.body

                         http协议请求格式
                post    url      http
                                      user_agent:.....
                                      accept:...........
                                      ContentType:json
                                user=liu&pwd=123   #封装数据格式:application/x-www-form-urlencoded
                                {"user":"liu","pwd":123} #json格式
    浏览器------------------------------------>服务器
            <------------------------------------
                         http协议响应格式
    发送接送数据给服务器:
           发送者Ajax:
                           $.ajax({
                                url:"/cal/",
                                type:"post",
                                contentType:"json",
                                data:JSON.stringfy({
                                        num1:num1,
                                        num2:num2,
                                        csrfmiddlewaretoken:$("[name='csrfmiddlewaretoken']").val()
                        }),
                                success:function(response){
                                            console.log(response);
                                            $("#ret").val(response)
                      }
                 })        
    

      Django服务器:

          视图函数:json_dict=json.lodas(request.body.decode("utf8"))

      注意:

          Django解析:

    if contentType:"urlencoded":
                  request.POST=data
    elif contentType=="formdata":
                  request.FILES=data
    else:
                   request.POST={}
    

     七.分页器

    假如我们有100本数的数据,想要将其分页,一页展示8条数据

    创建数据:
    book_list[]
    for i in range(100):
          book=Book(title="book_%s"%i,price=i*i)
          book_list.append(book)
    Book.objects.bulk_create(list)
    分页器的使用:
    paginator=Paginator(book_list,8)
    print(paginator.count)    #100
    print(paginator.num_pages)  #分页数:13
    print(paginator.page_range) #range(1,14)
    
    page=paginator.page(5)
    for i in page:
        print(i)
    
    print(page.has_next())
    print(page.has_previous())
    print(page.next_page_number())
    print(page.previous_page_number())
    

      自定义分页

    保存搜索条件 保存copy出的数据
    QueryDict
        #request.GET["xxx"]=123
        print(type(request.GET))
        from django.http.request import QueryDict
        print(request.GET)
    ================================================= import copy params=copy.deepcopy(request.GET) params["xxx"]=123 print("params",params) print(params.urlencode()) #"a=1&b=2&xxx=123"

      

     八.cookie与session

    cookie:针对每一个服务器都会保存一个key-value结构,类似于{ }

    obj=HttpResponse("OK")
    obj=render("")
    obj=redirect("")
    #设置cokkie
    obj.set_cookie("key","value","max_age=")
    #获取cookie
    request.COOKIES.get()
    #删除
    obj.delete_cookie("cookie_key",path="/",domain=name)

     session

    #设置session
    request.session["username"]="user"
    #取出session
    request.session.get("username")
    #删除session
    del request.session["username"]
    request.session.flush()
    

     用户认证组件

    使用django自带的用户表 auth_user
    插入记录的命令:python manage.py createsuperuser
    1.auth.authenticate(username=user,password=pwd)
    2.auth.login(request,user_obj)
        request.session["user_id"]=user.pk
    request.user:全局变量,模板,视图直接可以使用
    3.auth.logout(request)
    4.User.objects.create_user(username=user,password=pwd)
    5.#重置密码
       user=User.objects.get(username=request.user.username)
       user.set_password("666")
       user.save()
    

     九.ModleForm

    1.model:

    class UserInfo(AbstractUser):
            tel=models.CharField(max_lenght=32)
            gender=models.IntegerField(choices((1,"男"),(2,"女")),default=1)
    liu=UserInfo.objects.get(pk=1)
    liu.get_gender_display()
    

    2.modelform使用

    model.pclass Book(models.Model):

          nid=models.AutoField(primary_key=True)
          title=models.CharField(max_length=32)
          price=models.DecimalField(maax_digits=8,decimal_places=2)
          pub_date=models.DateTimeField()
          publish=models.ForeignKey(to="Publish",on_delete=models.CASCADE)
          authors=models.ManyToManyField(to="Author")
          def __str__(self):
                 return self.title

     

    form.py:

    #构建modelform
    class BookModelForm(forms.ModelForm):
            class Meta:
                model=Book
                fields="__all__"
    

     BookModelForm等同于:

    class BookForm(forms.Form):
            title=forms.CharField(max_length=32)
            price=forms.IntegerField()
         pub_date=forms.DateField(widget=widgets.TextInput(attrs={"type":"date"}))
    	#publish=forms.ChoiceField(choices=[(1,"AAA"),(2,"BBB")])
    	publish=forms.ModelChoiceField(queryset=Publish.objects.all())
    	authors=forms.ModelMultipleChoiceField(queryset=Author.objects.all()) 

    添加书籍逻辑:

    def add(request):
        if method=="GET":
            form=BookModelForm()
            return render(request,"add.html",{"form":form})
        else:
            form=BookModelForm(request.POST)
            if form.is_valid():
                form.save()   #Book.objects.create(**clean_data)
                return redirect("/")
            else:
                return render(request,,"add.html",{"form":form}) 

     编辑书籍逻辑:

    def edit(request,id):
        edit_obj=Book.objects.get(pk=id)
        if method=="GET":
            form=BookModelForm(instance=edit_obj)
            return render(request,{"form":form})
        else:
            form=BookModelForm(request.POST,instance=edit_obj)
            if form.is_valid():
                form.save()     #edit_obj.update(clean_data)
                return redirect("/")
            else:
                return render(request,{"form":form})
    

     十.视图函数

    FBV---------function based view

    CBV---------class based view

    path('index/',Views.index),
    path('login/',Views.LoginView.as_view()),
    path('login/',View.as_view.view)
    #用户访问get请求/login/-------view(request)
    

    十一.自定义过滤器和标签

    1.在setting中的INSTALLED_APPS配置当前app,不然django无法找到自定义的simple_tag.

    2.在app中创建templatetages模块(模块名只能是templatetags)

    3.创建任意 .py文件,如:my_tags.py

    from django import template
    from django.utils.safestring import mark_safe
    register = template.Library()    #register的名字是固定的,不可变的
    
    @register.filter
    def filter_multi(v1,v2):
            return v1*v2
    

    4.在使用自定义simple_tag和filter的html文件导入之前创建的 my_tags.py

    {% load my_tags %}
    

    5.使用模板中:

    #num = 12
    {% load my_tags%}
    {{ num|filter_multi:2 }}  #24
    

    总结:

      1.修改表结构:在权限表中加入is_menu和icon两个字段用来表示该权限是否是菜单权限

      2.登录成功后:注入该用户的权限列表和菜单权限列表注入session中

        permission_menu_list = [{},{}]

      3.在菜单区域中(side_bar):渲染出菜单链接标签:

    {% for item in request.session.permission_menu_list %}
      <p><a href="{{ item.url }}">{{ item.title }}</a></p>
    {% enfor %}
    

      4.点击标签加入active样式:

        解决思路1:每一个返回模板的视图函数中:

    permission_menu_list = request.session.get("permission_menu_list")
    for item in permission_menu_list:
            if re.search("^{}$".format(item["url"]),request.path):
                item["class"] = "active"
    

        解决思路2:引入inclusion_tag方法:

    @register.inclusion_tag("rbac/menu.html")
            def get_menu_styles(request):
                permission_menu_list = request.session.get("permission_menu_list")
                for item in permission_menu_list:
                    if re.search("^{}$".format(item["url"]),request.path)
                        item["class"] = "active"
                return {"permission_menu_list":permission_menu_list}
    

      在layout.html中:

    <div calss="menu-body">
             {% load web %}
             {% get_menu_styles request %}
    </div>
            
    

    十二.rbac(Role-Based Access Control)的应用

    (1)先将 rbac 组件移植到新的项目中

    (2)将settings中install_app 中加入"rbac"

    (3)将新项目的用户表与rbac的User表一对一关联

    (4)数据迁移

    (5)在登录成功后引入rbac下的initial_session方法,在登录用户的权限信息存储(注意user对象)

    (6)在settings中引入rbac下的权限校验中间件

    (7)在项目中的base模板中引入菜单样式,渲染显示

  • 相关阅读:
    DataTableToJSON
    css hack
    把网络数据流转换成图片类
    递归(转)
    SQL 锁
    观察者
    yield
    开闭原则(转)
    迪米特法则(最少知道原则)(转)
    sql 游标
  • 原文地址:https://www.cnblogs.com/liuqingyang/p/9488592.html
Copyright © 2020-2023  润新知