2021-08-31

创建 django 项目

  • 创建

    • cmd

    django-admin startproject s28(s28为项目名称)

    • pycharm

    …人家是专业版
    File-》new project-》 左侧选择django-》输入项目的目录-》选择解释器

  • 运行

    cd s28
    python manage.py runserver

  • 换端口

    python manage.py runserver 80

  • 换ip(不要使用被占用的)

    python manage.py runserver 0.0.0.1:80

  • 使用(urls.py)返回字符串

from django.contrib import admin
from django.urls import path
from django.shortcuts import HttpResponse
def index(request):
    #逻辑

    #返回结果
    #导入from django.shortcuts import HttpResponse
    return HttpResponse('index')

urlpatterns = [
    path('admin/', admin.site.urls),
    path('index/',index),#index为函数
]
  • 返回网页

  • 首先创建index.html在模板文件夹templates中
  • 然后再urls.py中
from django.contrib import admin
from django.urls import path
from django.shortcuts import HttpResponse, render


def index(request):
    # 逻辑

    # 返回结果
    # 导入from django.shortcuts import HttpResponse
    return render(request,'index.html')


urlpatterns = [

    path('admin/', admin.site.urls),
    path('index/', index),  # index为函数
]

注意:如果使用命令行创建的文件 ,则需要自行创建一个templates文件夹 ,然后再setting.py 添加templates的路径

TEMPLATES = [
{
‘BACKEND’: ‘django.template.backends.django.DjangoTemplates’,
‘DIRS’: [BASE_DIR / ‘templates’]
,
‘APP_DIRS’: True,
‘OPTIONS’: {
‘context_processors’: [
‘django.template.context_processors.debug’,
‘django.template.context_processors.request’,
‘django.contrib.auth.context_processors.auth’,
‘django.contrib.messages.context_processors.messages’,
],
},
},
]

登录界面设计(使用bootstrap)

静态文件导入

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DKF6yPCf-1630375338784)(pic/静态文件结构.png)]

然后在setting.py文件中添加设置


STATICFILES_DIRS=[
    BASE_DIR / 'static'
]

在官网登录界面中检查->资源->css->复制 得到signin.css,然后加入/static/css文件中
样式导入

<link rel="stylesheet" href="/static/plugins/bootstrap-3.4.1-dist/css/bootstrap.css">
<link rel="stylesheet" href="/static/css/signin.css">

注意:这里的文件夹可以改为任何名字,并不是static ,可以为static1 static2 static3 但是link的时候是/static/… 而不是/static1/… /static2…
在静态文件下,不要重名文件 否则只能按照seeting.py设置的顺序

酷炫登录界面

搜索

jq22.com

然后ctrl+s 复制 得到一个html文件+登录界面files(文件夹存放样式)
然后分别导入进静态文件夹

修改原文件

使用ctrl+r 然后使用正则替换,如
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1vliFzL9-1630375338786)(pic/使用正则替换.png)]

实现登录

form表单注意的点:
1.form标签的属性 action 指定提交的地址(不写默认当前的地址),method请求方式(默认get)
2.input标签要有name属性,有的需要value
3.有一个button按钮 或者是type=“submit”的input

目前提交post请求的必要操作:
在setting.py中需要注释一个中间件:

MIDDLEWARE = [  # 中间件
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
   # 'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

login.html

  <form class="form-signin" action="" method="post">
        <h2 class="form-signin-heading">Please sign in</h2>
        <label for="inputEmail" class="sr-only">Email address</label>
        <input type="email" name="user" id="inputEmail" class="form-control" placeholder="Email address" required="" autofocus="">
        <label for="inputPassword" class="sr-only">Password</label>
        <input type="password" name="pwd" id="inputPassword" class="form-control" placeholder="Password" required="">
        <div class="checkbox">
            <label>
                <input type="checkbox" value="remember-me"> Remember me
            </label>
        </div>
        <button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
    </form>

urls.py

def login(request):
    if request.method=='POST':
        #处理post逻辑
        print(request.POST['user'])
        #获取用户提交的用户名和密码 这里使用get获取键值更好
        user=request.POST.get('user')
        pwd=request.POST.get('pwd')
        #进行校验
        if user=="208633445@qq.com" and pwd=='123':
        #校验成功 告知登录成功
             return HttpResponse("登录成功")
    #校验失败 返回登录页面
    return render(request,'login.html')

request:
request.method 请求方式 GET POST
request.POST form 表单提交post请求的数据
request.GET URL 上窗体参数(查询参数)

重定向

from django.shortcuts import HttpResponse, render,redirect

return   return redirect('/index/') #跳转到index页面

重定向可以更改上面的跳转后浏览器的url不改变的情况

app的创建和注册

  • 创建

cd 项目后

python manage.py startapp app01(app名字)

  • 注册

进入setting.py 中,使用推荐写法

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
   # 'app01', # 直接写app名字
    'app01.apps.App01Config',#推荐写法
]

然后在app01-> views.py 中写函数 在原来的urls.py 中导入views 即可实现函数和列表分离

数据库表结构的创建和ORM的使用

ORM

对应关系:
类 -> 表
对象-> 数据行
属性-> 字段

使用ORM
1.配置setting.py中配置数据库的连接:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}

2.在app下的models.py中写类:

class User(models.Model):
    username=models.CharField(max_length=32) #varchar(32)
    password=models.CharField(max_length=32)

3.执行数据库迁移

#检测所有app中的models.py文件有什么变化 将变更记录制作成迁移文件
python manage.py makemigrations
python manage.py migrate #数据库迁移

添加数据(手动)
点击右边数据库的表 点击id可以看到中间的表,然后点击加号添加

4.查询

from  app01 import  models

def index(request):


    ret=models.User.objects.all()#对象列表
    for i in ret:
        print(i,i.username,i.password)
    #获取对象
    #ret=models.User.objects.get(username='208633445@qq.com',password="666666")
    #ret = models.User.objects.get(password="666666")
    #当获取的字段重复,会获取到一个以上的对象,就会报错
    #获取满足数据的对象
    ret = models.User.objects.filter(password="666666")

    print(ret)

    return render(request, 'index.html')


def login(request):

    if request.method=='POST':
        #处理post逻辑
        print(request.POST['user'])
        #获取用户提交的用户名和密码 这里使用get获取键值更好
        user=request.POST.get('user')#字符串
        pwd=request.POST.get('pwd')  #字符串
        #进行校验
        if models.User.objects.filter(username=user,password=pwd):
        #校验成功 告知登录成功
             #return HttpResponse("登录成功")
             return redirect('/index/') #跳转到index页面
    #校验失败 返回登录页面
    return render(request,'login.html')

查询

#对象列表
ret=models.User.objects.all()
#获取满足数据的对象列表(查询)
ret = models.User.objects.filter(password=“666666”)
#查询一条对象
ret=models.User.objects.get(username=‘208633445@qq.com’,password=“666666”)

mysql

启动遵循菜鸟教程

mysql -uroot -pXiaoming250

密码:Xiaoming250

1.创建数据库
2.然后在seeting.py中配置

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'login',
        'HOST':'127.0.0.1',
        'PORT':3306,
        'USER':'root',
        'PASSWORD':'Xiaoming250'
    }
}

3.使用pymysql连接数据库,在setting.py中插入
习惯写入与项目同名的文件夹下的__init__.py中(二者都可以)

import pymysql
pymysql.install_as_MySQLdb()

4.在app01中写moudles

class User(models.Model):
    username=models.CharField(max_length=32) #varchar(32)
    password=models.CharField(max_length=32)

5.执行数据库迁移命令

python manage.py makemigrations
python manage.py makemigrate

在database中添加可视化

书籍出版社小项目

html 表格

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PPrGZf3w-1630375338787)(pic/pub.png)]

<body>
<table border="1">
    <thead>
        <tr>
            <th>序号</th>
            <th>id</th>
            <th>出版社名称</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>1</td>
            <td>1</td>
            <td>商务印刷</td>
        </tr>
    </tbody>
</table>
</body>

实现返回页面数据
1.后端 返回字典,html的返回数据就是key

def publisher_list(request):
    #逻辑
    #获取出版数据
    all_pusher=models.Publisher.objects.all()
    for i in all_pusher:
        print(i,i.name)
    #返回页面,页面中包含出版信息
    return render(request,'publisher_list.html',{'all_publishers':all_pusher})

2.html
其中 forloop.counter为循环的当前次数

<body>
<table border="1">
    <thead>
        <tr>
            <th>序号</th>
            <th>id</th>
            <th>出版社名称</th>
        </tr>
    </thead>
    <tbody>
    {% for i in all_publishers %}
         <tr>
            <td>{{ forloop.counter }}</td>
            <td>{{ i.id }}</td>
            <td>{{ i.name }}</td>
        </tr>
    {% endfor %}

    </tbody>
</table>
</body>

增加数据

<form action="" method="post">
出版社名称:<input type="text" name="pub_name">
<button type="submit">提交</button>
def publisher_add(request):
    #如果是post请求
    if request.method=='POST':
    #获取提交数据
        pub_name=request.POST.get('pub_name')
    #将数据新增到数据库中
        models.Publisher.objects.create(name=pub_name)
    #返回一个重定向到展示出版社的页面

    #get请求返回一个页面,页面包含form表单
    return render(request,'publisher_add.html')

显示的顺序

all_pusher=models.Publisher.objects.all().order_by(‘id’)#升序
all_pusher=models.Publisher.objects.all().order_by(’-id)#降序

如果是已经存在的出版社

#若果数据库中有重复的名字
        if models.Publisher.objects.filter(name=pub_name):
            return render(request,'publisher_add.html',{'error':'出版社名字已经存在'})

删除

     <td><a href="/publisher_del/?pk={{ i.id }}">删除</a></td>
def publisher_del(request):
    #获取要删除的数据id
    pk=request.GET.get('pk')
    #根据id到数据库进行删除
    models.Publisher.objects.get(pk=pk).delete()#查询到一个对象删除
    #返回重定向到出版社页面
    return redirect('/publisher_list/')

修改

<form action="" method="post">
出版社名称:<input type="text" name="pub_name" value="{{ pub_obj.name }}">
    <span>{{ error }}</span>
<button type="submit">提交</button>
</form>
def publisher_edit(request):

    #get 返回一个页面  页面包含form 表单 input有原始数据
    pk=request.GET.get('pk')
    pub_obj=models.Publisher.objects.get(pk=pk)
    if request.method=='GET':
        return render(request,'publisher_edit.html',{'pub_obj':pub_obj})
    #post
    else:
        #获取用户提交的数据
        pub_name=request.POST.get('pub_name')
    #修改数据库中对应的数据
        pub_obj.name=pub_name

    #将修改操作提交到数据库
        pub_obj.save()
    #返回重定向展示出版社信息
        return  redirect('/publisher_list/')

外键

class Book(models.Model):
    name=models.CharField(max_length=32)
    publisher=models.ForeignKey(Publisher,on_delete=models.CASCADE)#默认是级联删除
    #on_delete = models.CASCADE 级联删除
    #on_delete=models.PROTECT 保护
    #on_delete=models.SET() 删除后设置为某个值
    #on_delete=models.SETDEFAULT ,default=1 删除后设置为一个默认值
    #on_delete=models.SET_NULL 删除后设置为NULL
之后进行两条迁移指令

图书展示

同上

书籍增加

  • option
<form action="" method="post">
    书名:<input type="text" name="book_name">
    出版社:
    <select name="pub" id="">
        {% for pulisher in pulishers %}
          <option value="{{ pulisher.id }}">{{ pulisher.name }}</option>
        {% endfor %}
    </select>
<button >提交</button>
</form>
def book_add(request):
    #post
    if request.method=='POST':
    #获取用户提交数据
        book_name=request.POST.get('book_name')
        pub_id = request.POST.get('pub')
        print(pub_id)
    #将数据插入到数据库中
        models.Book.objects.create(name=book_name,publisher_id=pub_id)
    #定向返回到展示书籍的页面
        return redirect('/book_list/')
    # 获取出版社
    pub = models.Publisher.objects.all()
    return render(request, 'book_add.html', {'pulishers': pub})

书籍删除

<td> <a href="/book_del/?id={{book.pk }}">删除</a></td>
#删除书籍
def book_del(request):
    # 获取用户提交的信息
    pk=request.GET.get('id')
    #获取删除的对象
    models.Book.objects.filter(pk=pk).delete()
    #回复一个重定向的页面
    return redirect('/book_list/')

编辑书籍

<form action="" method="post">
    书名:<input type="text" name="book_name" value="{{ book_obj.name }}">
    出版社:
    <select name="pub" id="">
        {% for pulisher in pulishers %}
            {% if pulisher == book_obj.publisher %}
                <option selected value="{{ pulisher.id }}">{{ pulisher.name }}</option>
            {% else %}
                <option value="{{ pulisher.id }}">{{ pulisher.name }}</option>
            {% endif %}
            <option value="{{ pulisher.id }}">{{ pulisher.name }}</option>
        {% endfor %}
    </select>
    <button>提交</button>
</form>
新增更新方法

models.Book.objects.filter(pk=pk).update(name=book_name, publisher_id=publisher)

def book_edit(request):
    pk = request.GET.get('id')
    book_obj = models.Book.objects.get(pk=pk)
    # post请求
    if request.method == 'POST':
        # 获取要编辑的对象
        book_name = request.POST.get('book_name')
        # 获取用户提交的数据
        publisher = request.POST.get('pub')
        # 编辑的对象的修改
        # 方式一:
        # book_obj.name=book_name
        # book_obj.publisher_id=publisher
        # book_obj.save()
        # 方式二
        models.Book.objects.filter(pk=pk).update(name=book_name, publisher_id=publisher)
        # 重定向到展示页面
        return redirect('/book_list/')
    # get 请求

    # 查询要编辑的id
    all_publishers = models.Publisher.objects.all()
    # 返回一个原始页面
    return render(request, 'book_edit.html', {"book_obj": book_obj, 'pulishers': all_publishers})
    # 根据id编辑对象

创建多对多的表

  • models.ManyToManyField()
class Book(models.Model):
    ....................
class Author(models.Model):
    name=models.CharField(max_length=32)
    books=models.ManyToManyField('Book')#增加第三张表 将book和author关联 这句话可以写在Book里面也一样

书籍列表

<table>
    <thead>
    <tr>
        <th>序号</th>
        <th>id</th>
        <th>姓名</th>
        <th>代表作</th>
        <th>操作</th>
    </tr>
    </thead>
    <tbody>
    {% for i in all_author %}
        <tr>
            <td>{{ forloop.counter }}</td>
            <td>{{ i.id }}</td>
            <td>{{ i.name }}</td>
            <td>
                {% for book in i.books.all %}
                    《{{ book.name }}》
                {% endfor %}

            </td>
            <td><a class="btn btn-danger btn-sm" href="/author_del/?id={{ i.pk }}">删除</a>
                <a class="btn btn-primary btn-sm" href="/author_edit/?id={{ i.pk }}">编辑</a>
            </td>
        </tr>
    {% endfor %}

    </tbody>
</table>

注意: #print(i.books.all())#所关联的列表

#作者列表
def author_list(request):
    # 查询所有的作者
    all_author=models.Author.objects.all()
   # for i in all_author:
      # print(i)
      #print(i.id)
      #print(i.name)
      #print(i.books)#对象关系
      #print(i.books.all())#所关联的列表
      # print('*'*20)
    # 返回一个作者的页面
    return render(request,'author_list.html',{"all_author":all_author})

增加书籍

<form action="" method="post" >
   <p>
       作者姓名:<input type="text" name="author_name">
   </p>
    <p>
        代表作:
        <select name="book_id" id="" multiple>
            {% for all_book in all_books %}
                <option value="{{ all_book.id }}">{{ all_book.name }}</option>
            {% endfor %}

        </select>
    </p>
<button>提交</button>
</form>
def author_add(request):
    #post
    if request.method=='POST':
    #获取数据
        author_name=request.POST.get('author_name')
        book_id=request.POST.getlist('book_id')#获取多个返回数据列表
    #插入
        author_obj=models.Author.objects.create(name=author_name)
        author_obj.books.set(book_id)#设置多对多关系
    #返回重定向到作者页面
        return redirect('/author_list/')
    #get
    #查询所有的书籍
    all_book=models.Book.objects.all()
    #返回一个页面
    return render(request,'author_add.html',{'all_books':all_book})

删除书籍

#删除作者
def author_del(request):
    #获取要删除的对象
    pk=request.GET.get('id')
    #根据id查到对象删除
    models.Author.objects.filter(pk=pk).delete()
    #返回重定向页面展示
    return redirect('/author_list/')

编辑书籍

<form action="" method="post" >
   <p>
       作者姓名:<input type="text" name="author_name" value="{{ all_author.name }}">
   </p>
    <p>
        代表作:
        <select name="book_id" id="" multiple>
            {% for all_book in all_books %}
                {% if all_book in all_author.books.all %}
                    <option selected value="{{ all_book.pk }}">{{ all_book.name }}</option>
                {% else %}
                    <option value="{{ all_book.id }}">{{ all_book.name }}</option>
                {% endif %}

            {% endfor %}

        </select>
    </p>
<button>提交</button>
</form>
  • 修改多对多的关系

author_obj.books.set(book_id)#修改多对多的关系

#编辑
def author_edit(request):
    # 获取要编辑的对象
    pk = request.GET.get('id')
    # 根据id查到对象
    author_obj = models.Author.objects.get(pk=pk)
    #post
    if request.method=='POST':
        author_name=request.POST.get('author_name')
        book_id=request.POST.getlist('book_id')
        #修改作者
        author_obj.name=author_name
        author_obj.save()
        #修改作者代表作
        author_obj.books.set(book_id)#修改多对多的关系
        #返回重定向
        return redirect('/author_list/')
    #get
    #获取所有书籍
    all_book=models.Book.objects.all()
    #返回重定向页面展示
    return  render(request,'author_edit.html',{"all_author":author_obj,"all_books":all_book})

MVC 和 MTV框架

MVC :
1.模型(moudles)操作数据库
2.视图(view)展示html
3.控制器(Controller)逻辑业务
Django借鉴了MVC的思想

MTV:
1.模型 ORM
2.模板(Template)
3.视图(View)负责逻辑

模板中的变量

{{变量名 }}和{% 逻辑 %}
python中可变的数据类型:
元组 数字 字符

<body>
<br>
{{ num }}
<br>
{{ string}}
<br>
{{ name_list.1 }}
<br>
{{ dic.name }}
<br>
{{ tup }}
<br>
{{ alex.name }}
</body>
.属性  .key .索引 .方法

过滤器

语法

{{value|filter_name:参数}}

如果没有传递参数过来可使用过滤器,加上默认值
注意不要空格:左边

{{ laobai|default:‘laobai’ }}

default:
变量为空或者没有数据时使用

{{value|filesizeformat}}

加法:

{{1|add:2}}
{{‘1’|add:’-2’}}
字符串相加
{‘1’|add:‘xxx’}

长度

{{ name_list|length }}
切片
{{ name_list|slice:‘0:2:1’ }}
取第一个元素
{{ value|first }}

拼接
join
截断 取前九个字符进行截断

{{ str|truncatechars:‘9’ }}
截断 按照单词进行截断
{{ str|truncatewords:‘9’ }}


{{ now|date:‘Y-m-d’ }}

日期
import datetime

{{now|date:‘Y-m-d H:i:s’}}

setting.py中修改

USE_I18N = True

USE_L10N = False

USE_TZ = True

DATETIME_FORMAT='Y-m-d H:i:s'
TIME_FORMAT='H:i:s'
DATE_FORMAT='Y-m-d'

safe
防止html进行转义

自定义过滤器

1.在app01下创建python包(templatetags 名字不能错)
2.创建mytags.py
3.在其中写:

from django import template
register=template.Library()

4.写函数+装饰器

@register.filter()
def add_arg(value,args):
    #功能
    return '{}_{}'.format(value,args)

5.使用自定义过滤器

{% load mytags %}
{{ alex.name|add_arg:'asd' }}

if、for、with、cstf_taken 标签

  • for
    forloop.counter 当前循环的序号 从1开始
    forloop.counter0 当前循环的序号 从0开始
    forloop.revcounter 当前循环的序号倒序 到1结束
    forloop.revcounter0 当前循环的序号倒叙 到0结束
    forloop.first 是否是第一次循环
    forloop.last 是否是最后一次次循环
% for foo in kong %}
    {{ foo }}
{% empty %} 
    空空如也
{% endfor %}
  • if 支持过滤器,不支持±*/ 支持and
{% if alex.age < 73 %}
     alexxxxxxx
{% elif alex.age == 73 %}
    alexxxxxxx
{% endif %} 
  • with
    作用:取别名
{% with dic as dic1 %}
{{ dic1 }}
{% endwith %}
  • crsf_taken
    from表单可以通过这里提交而不需要注释掉原来setting.py里的设置
<form action="" method="post">
    {% csrf_token %}
    <input type="text">
    <button>提交</button>
</form>

母版和继承

  • 母板
    需要替换的部分使用block,其余的为模板
{% block main0%}
    ......
{% endblock %}
  • 继承
    相同的block可自由编写,这部分替换原来的block
{% extends 'publisher_list.html' %}
{% block main0%}
    <li ><a href="/publisher_list/">出版社地址</a></li>
                <li class="active"><a href="/book_list/">书籍列表</a></li>
                <li><a href="/author_list/">作者</a></li>
                <li><a href="#">Export</a></li>
{% endblock %}

组件和静态文件

1.把一段公用的html单独写进一个html
2.在需要组件的时候在该组件的模板中写入

{% include ‘nav.html’ %}

静态文件引入:

{%load static %}

<link rel="stylesheet" href="{%static '...子目录'%}">

获取静态文件的前缀 如/static/

{% get_static_prefix%}

simple_tag的定义和使用

解决之前过滤器参数太少的问题,但是不能用于if语句中

@register.simple_tag
def str_join(*args,**kwargs):
    return '{}_{}'.format('_'.join(args),'*'.join(kwargs.values()))
{% str_join 'a' 'b' 'c' k1='d' k2='e' k3='f' %}

include_tag的使用

例子:分页
在mytags.py中写

@register.inclusion_tag('page.html')
def pagination(num):
    return {'num':range(1,num+1)}

然后在将bootstrap中的分页效果加到page.html中

<nav aria-label="Page navigation">
  <ul class="pagination">
    <li>
      <a href="#" aria-label="Previous">
        <span aria-hidden="true">&laquo;</span>
      </a>
    </li>
   {% for li in num %}
       <li><a href="">{{ li }}</a></li>
   {% endfor %}

    <li>
      <a href="#" aria-label="Next">
        <span aria-hidden="true">&raquo;</span>
      </a>
    </li>
  </ul>
</nav>

然后在需要分页的地方引入

  {% load mytags %}
  {% pagination 3 %}

视图

  • CBV 和FBV
    CBV: class based view
    FBV:function based view

CBV视图

from django.views import view
class xxx(view):
    def get(self,request):
        #专门处理get请求
        return response
    def post(self,request):
    #专门处理get请求
    return response
url(r'xx/',xxx.as_view())

如果有公共的部分,那么

class PublisherAdd(View):
    #共用的方法
    def dispatch(self, request, *args, **kwargs):
        #判断get post之前的操作
        ret=super().dispatch(self,request,*args,**kwargs)#执行view中的dispath
        return ret

    def get(self,request):
        print('get')
        print(self.request is request)
        return render(request,'publisher_add.html')

    def post(self,request):
        print('get')
        print(self.request is request)
        return render(request,'publisher_add.html')

给FBV加装饰器

import time
#统计时间的装饰器
def timer(func):
    def inner(*args,**kwargs):
        start=time.time()
        ret=func(*args,**kwargs)
        print('执行时间是{}'.format(time.time()-start))
        return ret
    return inner

@timer
def publisher_list(request):
    ..........
CBV加装饰器

导入包

from django.utils.decorators import method_decorator

  • 方法1:
    加在方法上面
  @method_decorator(timer)
     def get(self,request):
        print('get')
        print(self.request is request)
        return render(request,'publisher_add.html')
  • 方法2:
    加在dispatch上面,相当于get和post上都有
 @method_decorator(timer)
    def dispatch(self, request, *args, **kwargs):
        #判断get post之前的操作
        ret=super().dispatch(self,request,*args,**kwargs)#执行view中的dispath
        return ret
  • 方法3:
    加在类上面
@method_decorator(timer,name='get')
@method_decorator(timer,name='post')
class PublisherAdd(View):
    ......

request 对象

  • 属性
    request.method 请求方法 GET POST
    request.GET url上携带的参数 ?k1=xxx&k2=xxx
    requset.POST post请求提交的数据 编码方式是urlencode
    request.path_info 路径信息 不包含ip和端口也不包含参数
    request.body 返回请求体 byte类型
    request.schema 返回是http 还是https
    request.FILES 上传的文件
    request.META 返回头的信息 小写-》大写 HTTP_开头
    request.session
    request.cookie

  • 方法
    request.get_full_path() 完整的路径信息包含返回后面的参数
    request.is_ajax() 判断是否是ajax请求

response对象

from django.short import render,HttpResponse,rediret
HttpResponse(‘xxx’)实例化一个对象,并且返回字符串
render(request,‘模板文件名’,{‘k1’:k1})函数
redirect(‘地址’)#重定向 响应头的内容 location+地址 301 302 的状态码

JsonResponse

字典转字符串叫做序列化

from django.http.response import JsonResponse
return JsonResponse({‘ka’:‘ka’})
如果是传的列表,那么需要加参数,safe=False

文件上传

<form action="" method="post" enctype="multipart/form-data">
     {% csrf_token %}

    <input type="file" name="f1">
    <button>上传</button>
</form>
class upload(View):
    def get(self,request):
        return render(request,'upload.html')

    def post(self,request):
        file=request.FILES.get('f1')
        with open(file.name,'wb') as f:
             for i in file:
                 f.write(i)
        return HttpResponse('OK')

url使用分组和命名分组

通过re在路由时使用
分组

url(r’^blog/([0-9]{4})/\d(2)/$’,views.blog)
url地址上捕获的参数会按照位置传参 方式传递给视图函数
def blog(request,year)

命名分组

url(r'^blog/(?<year>[0-9]{4})/(?<month>)\d(2)/$',views.blog)
url地址上捕获的参数会按照位置传参 方式传递给视图函数
def blog(request,year)

视图函数的默认参数

def page(request,name=‘xiaohua’)

include路由分发

在每一个app下面新建urls.py文件中
然后在外面的urls中

from django.contrib import admin
from django.urls import path,include
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('app01/',include('app01.urls')),
    path('app02/', include('app02.urls')),
]

url的命名和反向解析
静态路由
命名:

url(r’^blog/$’,views.blog,name=‘blog’) #/app01/blog/ =>blog

反向解析:
模板

{% url ‘blog’ %} ->/app01/blog

在py中:

url=reverse(‘blog’)#可获得路径

动态路由
命名

url(r’^blog/([0-9]{4})/(\d{2})/$’,views.blog,name=‘blog’)
反向解析

{% url ‘blog’ ‘2020’ ‘20’%} # url=app01/blog/2020/20

在py中获取url

url=reverse(‘blogs’,args=(‘2018’,‘08’)) #url=app01/blogs/2018/08

namespace
解决不同app下相同name的问题

urlpatterns = [
    path('admin/', admin.site.urls),
    path('app01/',include('app01.urls',namespace='app01')),
    path('app02/', include('app02.urls',namespace='app02')),
]

py

reverse(‘app01:blogs’,args=(‘2018’,‘08’))

反向解析

{% url ‘app01:blog’ ‘2020’ ‘20’%}

常用数据库字段

class Person(models.Model):
    pid=models.AutoField()#自增
    name=models.CharField(max_length=32)
    age=models.IntegerField()#-2147483648~+2........
    birth=models.DateTimeField(auto_now_add=True)#每新增数据时自动保存当前时间
    #auto_now 每次修改后都保存时间
    
Boolean 布尔型
TextField 文件型
FloatField浮点型

自定义字段

作者太懒了,参考网上

字段参数

null=True #可以为空
db_column字段的名字
unique=True
choice=((True,'男'),(False,'女'))

使用django的admin

1.创建一个超级用户

python manage.py createsuperuser

2.注册moudles
在app下的admin下

from app01 import models
admin.site.register(models.Publisher)

然后在moudles中 返回

class Publisher(models.Model):
    name =models.CharField(max_length=32)

    def __str__(self):
        return self.name

3.登录

后续懒得写了

(https://developer.mozilla.org/zh-CN/docs/Learn/Server-side/Django/Testing)

查询语句

  • 查询所有数据

models.Person.objects.all()

  • 获取唯一的数据

models.Person.objects.get()

  • 获取满足条件的数据

models.Person.objects.filter()

  • 按照条件排序(默认升序)字段前加‘-’为降序

models.Person.objects.all().order_by(‘age’)

  • reverse对已经排序的对象序列反转

models.Person.objects.all().reverse()

  • 获取数据所有的字段和值QuerySet [{ },{ },{ }]

models.Person.onjects.all().values(‘pid’,‘name’)

  • 不指定字段获取所有的值

models.Person.onjects.all().values_list(‘pid’,‘name’)

  • 去重

models.Person.onjects.all().destinct()
models.Person.onjects.values(‘age’).destinct()

  • 计数

models.Person.onjects.all().count()

  • 获取第一个/最后一个数据

models.Person.onjects.all().first()
models.Person.onjects.all().last()

  • 查询是否有结果

models.Person.onjects.filter().exists()

  • 排除

models.Person.onjects.all().exclude(pk=1)

单表的下划线

  • 小于

    models.Person.onjects.filter(pid__lt=6)#小于6

  • 大于

    models.Person.onjects.filter(pid__gt=6)#大于6

  • 小于等于

    models.Person.onjects.filter(pid__lte=6)

  • 大于等于

    models.Person.onjects.filter(pid__gte=6)

  • 范围(左右都包含)

    models.Person.onjects.filter(pid__range=[1,6])

  • 属于范围

    models.Person.onjects.filter(pid__in=[1,5,6,3])

  • 包含

    models.Person.onjects.filter(name__contains=‘alex’)#sql like

  • 包含(忽略大小写)

    models.Person.onjects.filter(name__icontains=‘alex’)#sql like

  • 以什么开头

    models.Person.onjects.filter(name__startwith=‘alex’)

  • 以什么开头(忽略大小写)

    models.Person.onjects.filter(name__startwith=‘alex’)

  • 以什么结尾

    models.Person.onjects.filter(name__endtwith=‘alex’)

  • 以什么结尾(忽略大小写)

    models.Person.onjects.filter(name__iendwith=‘alex’)

  • 查找日期

    models.Person.onjects.filter(birth__year=‘2019’)
    models.Person.onjects.filter(birth__month=‘2019’)
    models.Person.onjects.filter(birth__day=‘2019’)
    models.Person.onjects.filter(birth__contains=‘2019-01-01’)
    models.Person.onjects.filter(birth__contains=’-01-01’)

  • 查找字段为null

    models.Person.onjects.filter(name__isnull=True)

外键操作

  • 正向查询 同上
  • 反向查询

    per=models.Person.onjects.get(pk=1)
    print(per.per_set.all())
    #小写类名_set 或者自定义数据库的时候加上参数 related_name=‘books’

  • 基于字段的查询 pub是外键 name是出版社的字段

    models.Book.objects.filter(pub__name=‘新华出版社’)#也可同上指定related_query_name,pub则也改为相应的数据

多对多

设置多对多关系
set方法
添加多对多的关系

author_obj.books.add(1,2)
author_obj.books.add(*modles.Book.objects.filter(id__in=[3,4]))

移除

author_obj.books.remove(1,2)
author_obj.books.remove(*modles.Book.objects.filter(id__in=[3,4]))

清空多对对关系

author_obj.books.clear()

新建

author_obj.books.create(name=‘倜然’,pid=‘12’)

聚合和分组

  • 导入

from django.db.models import Max, Min,Count,Sum,Avg

  • 使用 aggregate为终止字句

models.Book.objects.all().aggregate(Max(‘price’),min(‘price’))

分组group

按照书分组计数作者
annotate 注释 过程使用了分组

ret=models.book.objects.annotate(Count(‘authors’).values())

统计每一出版社卖的最便宜的书的价格

ret=models.Pulisher.object.annotate(Min(‘book_price’)).values()
按照pub ,pub_name分组
ret=models.book.object.values(‘pub’,‘pub_name’).annotate(Min(‘Price’))

统计不止一个作者的图书

ret=models.Book.objects.annotate(count=Count(‘author’)).filter(count__gt=1)

F和Q

  • 导入

from django.db.modles import F ,Q

modles.book.objects.filter(sale_gt=F('kucun)) #where sale>kucun
modles.book.objects.filter(id__lte=3).update(‘sale’)*3+13)

Q ( )

|

&

~

re=modles.book.objects.filter(Q(id__lt=3),Q(id__gt=5))
re=modles.book.objects.filter(Q(id__lt=3)|Q(id__gt=5))

事务

from django.db import transaction

try:
with transaction.atomic():
    models.Book.objects.all.update(kucun=F('kucun')-10)
    int('sss')
    models.Book.objects.all.update(kucun=F('kucun')-10)
except Exception as e
    print(e)

cookie

保存在浏览器本地的一组组键值对

django中操作cookie

登录时的cookie

  • 导入

    from functools import wraps

  • 写装饰器

    def login_required(func):
      @wraps(func)
      def inner(request,*args,**kwargs):
          # 是否登陆了
          is_login = request.COOKIES.get('is_login')
          # 登录了
          if is_login != '1':
              return redirect('/login/?url={}'.format(request.path_info))
          ret=func(request,*args,**kwargs)
          return ret
      return inner
    
    
  • 然后加装饰器

  • 优化登录(返回登录前的页面)

    def login(request):
      if request.method=='POST':
          user=request.POST.get('user')
          pwd=request.POST.get('pwd')
          if user=='alex' and pwd=='123':
              #登录成功之后保存登录状态到cookie
              #如果有返回的页面(没有登录前)
              url=request.GET.get('url')
              if url:
                   urld=url
                   print(url)
              else:
                  urld='/publisher_list/'
              ret = redirect(urld)
              ret.set_cookie('is_login', '1')
              return ret
          else:
              error=''
      return render(request,'login.html',locals())
    

cookie操作

设置cookie
repponse.set_cookie(key,value)
response.set_signed_cookie(key,value,salt='s28')# 加密
max_age超时时间
path 是cookie生效的页面
secure=False https进行传输
httponly =False 无法被js获取

设置cookie
response.COOKIE()
response.get_signed_Cookie(key,salt='s28',defalut='')#加密

删除cookie 设置cookie为0 超时时间为0
response.delete_cookie(key)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值