• 第六章Django


    web应用程序

    server端建立socket,不断地accept,当收到客户端连接信号之后,服务端向客户端发送数据,将html网页打开,read出来,并发送至客户端,这样客户端就可以浏览到网页的内容

    http协议:

    包头里面的数据用 一个“ ”来区分,最后使用两个“ ”来区分数据

    GET协议把数据放在了包头里面,POST协议把数据放在包头的最后面

    GET提交的数据以“?”区分,参数之间以“&”进行连接

    相应格式:

    协议版本 状态码 状态码的原因短语 相应首部字段 主体

    web框架 yuan功能总结

    main.py: 启动文件,封装了socket

    1 urls.py: 路径与视图函数映射关系 ---- url控制器

    2 views.py 视图函数,固定有一个形式参数:environ -----视图函数,

    3 templates文件夹: html文件 -----模板

    4 models: 在项目启动前,在数据库中创建表结构 ----- 与数据库相关



    Django的安装与启动
    创建应用:python manage.py startapp blog

    urlpatterns = [
    re_path(r'^articles/2003/$', views.special_case_2003),
    re_path(r'^articles/([0-9]{4})/$', views.year_archive),
    re_path(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
    re_path(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
    ]

    有名分组:在组前面加上?P<组名> 即可,在传参时的形参必须是“组名”,否则会出错
     


    命名空间:namespace
    app01.urls:
    需要加上
    app_name = "app01"
    urlpatterns=[
    re_path(r'^index/',views.index,name="index"),
    ]

    同理在ap02.urls加上相同的配置

    views.py:
    def index(request):
    return HttpResponse(reverse("app01:index"))
    需要加上反向解析


    注册自定义转换器
    先建一个类
    class FourDigitYearConverter:
    regex = '[0-9]{2}' #正则表达式的公式

    def to_python(self,value):
    return int(value)

    def to_url(self,value):
    return '%04d' % value

    在项目中注册转换器
    # 注册定义的url转换器
    register_converter(FourDigitYearConverter,'mm') #FourDigitYearConverter : 为以上类名

    之后在urls里可以直接path使用
    path('articles/<mm:month>/',views.month_archive)


    模板语法 只有两个
    1.{{}}
    可以在
    return render(request,'index.html',locals()) 这样就把该函数里的全部全局变量都传过去了
    同时在index.html可以通过 . 来过去数据 如一个数组l=【‘123’,‘456’,‘789’】 ,在html可以通过l.2 获取到数据456

    2{%%}
    {%if%}

    {%endif%}

    自定义标签与过滤器
    1.在settings的INSTALLED_APPS加上当前app的名称,不然django无法找到自定义的simple_tag.
    2.在app文件夹里面添加templatetags模块(模块名只能是templatetags)
    3.在templatetags里面创建任意py文件
    4.在该py文件里面引入
    from django import template
    register = template.Library()  # 固定名字
    @register.filter          #加上装饰器,这个为模板过滤器
    def filter_multi(x,y):
    return x*y

    @register.simple_tag #标签过滤器
    def filter_tag(x,y):
    return x*y
    5.在html文件里面读取该过滤器
    {%load py的文件名%}
    6.使用
    {{ 2 | filter_multi:5 }}

    {% filter_tag 5 6 %}

    继承:extends
    在一个base.html 里面把模板写好
    在另一个html里面引入base.html
    {% extends "base.html" %}
    这时候可以在下面继续添加block里面的内容
    {{% block title %}
    <title>第一个</title>
    {% endblock title%}

    模型层ORM
    ORM 对象-关系-映射
    通过编写ORM层,控制pysql转换成db语句,再去控制db数据库。py文件里面通过创建一个类


    生成表模型
    1.创建模型
    from django.db import models
    
    # Create your models here.
    
    class Book(models.Model):
         id = models.AutoField(primary_key=True)
         title=models.CharField(max_length=32)
         state=models.BooleanField()
         pub_date=models.DateField()
         price=models.DecimalField(max_digits=8,decimal_places=2)
         publish=models.CharField(max_length=32)

    创建一个app,然后在app项目文件下的models下创建类

    2.配置链接数据库settings

    在项目文件下的settings文件设置下,设置数据库信息

    DATABASES = {
        'default':{
            'ENGINE':'django.db.backends.mysql',
            'NAME':'bms',                #创建数据库名字
            'USER':'root',         #链接数据库用户名
            'PASSWORD':'',         #链接数据库密码
            "HOST":'127.0.0.1',      #目标数据库地址
            'PORT':3306           #目标数据库端口
        }
    }
    

      

    3.确认信息

    ①在项目app文件下的__init__插入代码:
    import pymysql
    
    pymysql.install_as_MySQLdb()
    
    
    
    

    ②确保配置文件中的INSTALLED_APPS中写入我们创建的app名称

    如在installed_apps 下添加app文件名


    最后,可以进行数据迁移
    python manage.py makemigrations
    python manage.py migrate
    

      


    数据库的建立create:
    方式一:
    book_obj = Book.objects.create(title='第一个数据库',state=True,price=500,pub_date="2012-12-12",publish='人民出版社')    #里面的数据格式需要与建立时的数据格式一致

    方式二:
    book_obj = Book(title='方式二',publish='机械出版社',state=True,pub_date="2010-12-11",price=10.12)
    book_obj.save()                    #需要多一个save
     
    查询表:
    Django 自己生成的一个数据对象:QuerySet: [obj1,obj2,obj3....]
    可以通过语句Book.object ---> 生成QuerySet数据
    Book.object.all() 可以读取所有的数据

    values方法: 返回和调用都是QuerySet
    book_obj = Book.objects.values('price')
    相当于
    list = []
    for obj in QuerySet:
      list.append{'price':obj['price']}
      .... #如果在values后面加值,就继续append

    values_list方法:  
    返回和调用都是QuerySet
    book_obj = Book.objects.values_list('price')


    distinct:去重 从返回结果中剔除重复纪录


    表的查询

    一对多的查询:
    A---B
    如果关联表在A表中:
    A----->B :正向查询
    反过来通过B去查A 则是反向查询,主要看关联表在哪张表里面
    正向查询:看字段
    反向查询:看表名:表名小写__set.all()
    from django.db import models
    
    # Create your models here.
    
    
    class Author(models.Model):
        nid = models.AutoField(primary_key=True)
        name=models.CharField( max_length=32)
        age=models.IntegerField()
    
        # 与AuthorDetail建立一对一的关系, on_delete must add after Django 2.0 when use foreign Key
        authorDetail=models.OneToOneField(to="AuthorDetail",on_delete=models.CASCADE)    
    class AuthorDetail(models.Model):
    
        nid = models.AutoField(primary_key=True)
        birthday=models.DateField()
        telephone=models.BigIntegerField()
        addr=models.CharField( max_length=64)
    
    class Publish(models.Model):
        nid = models.AutoField(primary_key=True)
        name=models.CharField( max_length=32)
        city=models.CharField( max_length=32)
        email=models.EmailField()
    
    
    class Book(models.Model):
    
        nid = models.AutoField(primary_key=True)
        title = models.CharField( max_length=32)
        publishDate=models.DateField()
        price=models.DecimalField(max_digits=5,decimal_places=2)
    
        # 与Publish建立一对多的关系,外键字段建立在多的一方
        publish=models.ForeignKey(to="Publish",to_field="nid",on_delete=models.CASCADE)
        # 与Author表建立多对多的关系,ManyToManyField可以建在两个模型中的任意一个,自动创建第三张表
        authors=models.ManyToManyField(to='Author',)
    
    
    

      



    聚合与分组查询
    关键字:
    annotate

    总结 跨表的分组查询的模型:
    # 每一个后表模型.objects.values("pk").annotate(聚合函数(关联表__统计字段))
     

    AJAX
    特点:
    1.使用JavaScript向服务器发送异步请求
    2.局部刷新

    $(".Ajax").click(function () {
    $.ajax({
    url:"/test_ajax/", //请求地址
    type:"get", //请求的类型poet或者是get
    success:function (data) {
    $(".haha").html(data)
    console.log(data)
    }
    })
    })


    数据之间的传输 通过使用json序列化
    在py里面使用json.dump序列化
    在Ajax里面使用JSON.parse 反序列化进行解析


    利用Form表单进行文件上传

    def file_put(request):
        if request.method=="POST":
            print('123')
            print(request.POST)
            print(request.FILES)
    
            file_obj = request.FILES.get("tou")
    
            with open(file_obj.name,'wb') as f:
                for i in file_obj:
                    f.write(i)
    
            return HttpResponse('OK')
    
        return render(request, "file_put.html")
    批量导入数据库的数据:
    '''
        批量导入数据:
    
        Booklist=[]
        for i in range(100):
            book = Book(user="book_%s"%i,pwd=i*i)
            Booklist.append(book)
        Book.objects.bulk_create(Booklist)
        '''

    分页器:

    book_list = Book.objects.all()
    
        paginator = Paginator(book_list,10)
    
        print("count:", paginator.count)  # 数据总数
        print("num_pages", paginator.num_pages)  # 总页数
        print("page_range", paginator.page_range)  # 页码的列表
    
        page1=paginator.page(4)     #第4页的page对象数据
        for i in page1:             #遍历
            print(i)
    
        print(page1.object_list)    #直接拿出该page的所有对象

      
      #捕捉EmptyPage错误信息时做的处理
      try:
      current_page = int(request.GET.get("page",1))
      page1 = paginator.page(current_page)
      except EmptyPage as e:
      page1 = paginator.page(1)
     
     print(page2.has_next())            #是否有下一页
        print(page2.next_page_number())    #下一页的页码
        print(page2.has_previous())        #是否有上一页
        print(page2.previous_page_number()) #上一页的页码

    form组件

    form.is_valid()   #:返回布尔值
    form.cleaned_data #:{"name":"yuan","email":"123@qq.com"} 返回匹配成功的字典
    form.errors      #返回对应类字段的错误信息 :{"name":[".........."]}
    
    
    from django.forms import widgets
    class UserForm(forms.Form):                              #用于认证用
        name = forms.CharField(max_length=32,label="用户名", widget=widgets.TextInput(attrs={"class":"form-control"}),error_messages={“required”:“该字段不能为空”})   #attr即为修改样式,error_message修改默认的错误信息,必须为required这个键名
        pwd = forms.CharField(min_length=4)
        r_pwd = forms.CharField(min_length=4)
        email = forms.CharField()
        tel = forms.CharField(min_length=4,max_length=32)
    
    
    def form_test(request):
        if request.method == 'POST':
            form = UserForm(request.POST)
            if form.is_valid():             #校验是否验证通过,同时会把错误、正确的信息放在两个字典里面
                print(form.cleaned_data)
            else:
                print(form.cleaned_data)
                print(form.errors)  # ErrorDict : {"校验错误的字段":["错误信息",]}
                print(form.errors.get("name"))  # ErrorList ["错误信息",]
            return HttpResponse("OK")
            form = UserForm()
            return render(request, "form_test.html", locals())
    
        form = UserForm()
    
        return render(request,"form_test.html")

    在html里面想打印错误信息,可以{{form.name.errors}}  这样可以获取name里的错误信息

    利用form表单组件 进行文件上传,使用FormData

    $(".login_btn").click(function () {
            var form_data = new FormData();         //首先实例化一个FormData
            form_data.append("user",$("#id_user").val())    //再往里面添加数据
            form_data.append("pwd",$("#id_pwd").val())
            form_data.append("r_pwd",$("#id_r_pwd").val())
            form_data.append("email",$("#id_email").val())
            form_data.append("img",($("#avater")[0].files[0]))     //该为文件,主要是传它才使用FormData,不然不用这么麻烦
            form_data.append("csrfmiddlewaretoken",$("[name='csrfmiddlewaretoken']").val())
    
            $.ajax({
                url:"",
                type:"post",
                contentType:false,     //必须设置这两个值
                processData:false,
                data:form_data,         //最后把这个对象传给data
                success:function (data) {
                    console.log(data)
                }
            })
        })

    局部钩子

    在规则里面class 添加一个方法"clean_%s"name

     def clean_tel(self):
            val = self.cleaned_data.get('tel')
    
            if len(val) == 11:
                return val
            else:
                raise ValidationError("手机号格式错误")

    form.is_valid--》self.errors-->self.full_clean--》self._clean_fields()
    依次校验每个字段,之后再走钩子去判断里面有没有clean_%s 用户自定义的方法

    if hasattr(self, 'clean_%s' % name):
        value = getattr(self, 'clean_%s' % name)()
        self.cleaned_data[name] = value

    全局钩子

        def clean(self):
            pwd = self.cleaned_data.get('pwd')
            r_pwd = self.cleaned_data.get('r_pwd')
    
            if pwd and r_pwd:
                if pwd == r_pwd:
                    return self.cleaned_data
                else:
                    raise ValidationError('两次密码不一致!')
            else:
                return self.cleaned_data

    视图函数 form_test.html

    <div class="container">
        <form action="" method="post">
            {% csrf_token %}
            <div class="row">
                <div>
                    <p>
                    {{ form.name.label }}{{ form.name }}<span>{{ form.name.errors }}</span><span class="has-error pull-right">{{ errors.0 }}</span>  #errors类 自己写
                    </p>
                </div>
                <div>
                    <p>
                    {{ form.pwd.label }}{{ form.pwd }}<span>{{ form.pwd.errors }}</span>
                    </p>
                </div>
                <div>
                    <p>
                    {{ form.r_pwd.label }}{{ form.r_pwd }}<span>{{ form.r_pwd.errors }}</span><span class="pull-right error">{{ errors.0 }}</span>
                    </p>
                </div>
                <div>
                   <p>
                    {{ form.email.label }}{{ form.email }}<span>{{ form.email.errors }}</span>
                    </p>
                </div>
                <div>
                    <p>
                    {{ form.tel.label }}{{ form.tel }}<span>{{ form.tel.errors }}</span>
                    </p>
                </div>
                <input type="submit" value="提交">

    cookie:具体一个浏览器针对一个服务器存储key-value({})

    获取cookie:

    cookie 信息储存在request.COOKIE

  • 相关阅读:
    Laravel 中查询 where 记录
    eclipse svn重定位(relocate)
    使用git ftp发布我个人的hexo博客内容
    oracle数据库查询常用语句
    telnet关闭tomcat
    XML字符串解析成对象的时候应注意空格
    去除焦点边框线
    如何查看和更改mysql数据库文件存放位置
    设置div,td失去焦点
    (加减乘除)字符串计算机
  • 原文地址:https://www.cnblogs.com/tyh-tesla/p/9411086.html
Copyright © 2020-2023  润新知