灵虚御风
醉饮千觞不知愁,忘川来生空余恨!

导航

 
昨日内容回顾
    主题就是围绕登陆功能
        app的概念
            django其实就是一个专门用来开发app的web框架
            一个空的django的项目就类似于是一所大学
            app就类似于大学里面的各个学院
            比如你的选课系统(学生,老师,管理员)
            在比如你的优酷项目(普通用户,vip用户,管理员)
            大白话:针对不同的功能模块 你就可以开设不同的app去处理实现程序的解耦
            并且更好的实现分组开发

        静态文件配置(******)
            大前提:浏览器之所以能够输入网址访问到对应的资源,是因为后端开设了资源的访问接口(url),
            django在何处可以开设接口???   urls.py路由与视图函数对应关系

            网址所用到的html文件通常都是放在templates文件夹下
            网站所用到的静态资源通常都是放在static文件夹下

            django 配置文件中指定静态文件暴露的接口
            STATIC_URL = '/static/'  # 仅仅是访问静态资源的接口前缀
            STATICFILES_DIRS = [
                os.path.join(BASE_DIR,'static'),  # 一旦你是以接口前缀开头的 那么就会自动拿着接口前缀后面的文件路径去列表中一个个的文件夹中查找文件
                os.path.join(BASE_DIR,'static1'),
                os.path.join(BASE_DIR,'static2'),

            ]
            静态文件路径动态解析
            {% load  static %}
            {% static '文件路径' %}

        form表单提交数据
            action
                1.不写默认朝当前url(http://127.0.0.1:8080/index/?id=1)提交
                2.只写后缀/index/或者/index/?id=1
                3.写全路径(你这个form要往其他网站的url提交数据)
            method
                默认是get请求

            get请求和post请求携带参数的特点
                get请求是直接在url后面?开头以&连接多个条件
                /index/?id=1&username=jason(get请求携带的参数大小是有限制的)

                而post请求数据是放在请求体中的


        request方法初识
            request.method  获取请求方式(get/post)  全大写的字符串形式
            request.GET     获取get请求携带的所有的数据  类似于是一个大字典
            request.POST    获取post请求携带的所有的数据  类似于是一个大字典
                取值分为两种
                    request.POST.get('hobby')  默认取列表最后一个元素
                    request.POST.getlist('hobby')  直接将列表原封不动的取出

        pycharm连接数据库
            侧边栏database连接你想要操作的数据库  pycharm充当数据库的客户端
        django连接MySQL(******)
            django自带一个小型的sqlite数据库,该数据库对日期不是很精确
            1.配置文件中配置(配置键必须是全大写)
            DATABASES = {
            'default': {
                'ENGINE': 'django.db.backends.mysql',
                'NAME': 'day51',
                'HOST':'127.0.0.1',
                'PORT':3306,
                'USER':'root',
                'PASSWORD':'123',
                'CHARSET':'utf8'
            }
}
            2.一定要在init文件中告诉django用pymysql取代mysqldb连接数据库
            import pymysql
            pymysql.install_as_MySQLdb()
        django orm简介
            强调:django orm不会帮你创建库,需要你自己手动创建库,它只能帮你创建表(建议你一个django就新建一个数据库)
            模型类的创建
                取应用下的models.py中书写模型类/class User(models.Model):
                    # id字段可以不写 django orm会自动帮你创建一个主键为id的字段
                    uid = models.AutoField(primary_key = True)
                    username = models.CharField(max_length=32)  # username varchar(32)
                    password = models.IntegerField()  # password int


            数据库迁移命令(******)
                注意:只要你动了models中跟数据库相关的代码 你就必须执行以下两条命令
                    python3 manage.py makemigrations  # 将记录写到migrations文件中 类似于日志 
                    python3 manage.py migrate  # 真正的去数据库中操作
                当你熟练掌握之后 你可以采用简写的方式
                    tools
                        run manage.py task


        表字段的增删改查
            1.当表已经创建出来之后 需要新增字段 该字段需要设置默认值 或者 设置成可以为空
                default='默认值'
                null = True
            2.当你注释了某个字段 再执行数据库迁移命令之后 数据库表中 该字段对应的数据全部删除了 (慎用)
        表记录的增删改查
            操作django orm都是以模型类名作为开头
            from app01 import models
            以用户的增删改查为例

                1.先连接数据库展示所有用户信息
                    1.获取模型表中所有的数据
                        models.User.objects.all()  # 结果也是querySet对象    只要是queryset对象 就可以点query查看内部sql语句
                    2.筛选相应的数据
                        1.直接获取对象的
                            models.User.objects.get(**kwargs)  # 条件不存在  立刻报错  不推荐使用
                        2.获取querySet对象的(
                            1.querySet对象你可以把它看成是一个列表 里面放的是一个个的数据对象
                            2.querySet对象支持索引取值和切片操作 但是不支持负数 也不推荐你使用
                            建议你使用封装好的方法
                            )
                            queryset = models.User.objects.filter(**kwargs)  # 括号内多个参数是and的关系
                            user_obj = querySet.first()  # 没有也不会报错  直接返回None
                2.新增用户
                    1.利用create()方法
                        该方法会将当前创建的数据对象返回出来
                        current_user_obj = models.User.objects.create(**{...})
                    2.利用对象的绑定方法
                        user_obj = models.User(**kwargs)
                        user_obj.save()

                3.修改用户
                    1.利用queryset对象的update批量修改的方法
                        models.User.objects.filter(age = 18).update(**kwargs)  # 会将queryset中所有的数据全部修改

                    2.利用对象修改属性的方法
                        user_obj = models.User.objects.filter(**kwargs).first()
                        user_obj.username = 'jason'
                        user_obj.save()  # 该方法 会将数据库中所有的字段全部重写修改一遍 效率极低 不推荐使用

                4.删除用户(不会真正删除数据  通常都是给数据加一个表示是否删除的字段)
                    1.利用queryset对象delete批量删除
                        models.User.objects.filter(age = 18).delete()  # 会将queryset中所有的数据全部删除
复习
今日内容
    1.django请求生命周期

    2.本周作业  图书管理系统表设计

    3.路由层

    4.视图层








表与表之间建关系
    图书管理系统为例
        书籍表
            书籍和出版社是一对多  外键字段建在书籍表中
            书籍和作者是多对多    需要第三种记录多对多关系




        出版社表


        作者表

        django orm中表与表之间建关系
            一对多  ForeignKey(to='Publish')
                  
            一对一  OneToOneField(to='AuthorDetail')

            多对多  ManyToManyField(to='Author')


            注意:
                前面两个关键字会自动再字段后面加_id
                最后一个关键字 并不会产生实际字段 只是告诉django orm自动创建第三张表


        本周作业 图书管理系统至少书籍表的增删改查




django 请求生命周期 图片


    路由层
        url()方法 第一个参数 其实是一个正则表达式
        一旦前面的正则匹配到了内容 就不会再往下继续匹配 而是直接执行对应的视图函数

        正是由于上面的特性  当你的项目特别庞大的时候  url的前后顺序也是你需要你考虑
        极有可能会出现url错乱的情况


        django在路由的匹配的时候  当你在浏览器中没有敲最后的斜杠
        django会先拿着你没有敲斜杠的结果取匹配 如果都没有匹配上  会让浏览器在末尾加斜杠再发一次请求 再匹配一次 如果还匹配不上才会报错
        如果你想取消该机制 不想做二次匹配可以在settings配置文件中 指定
        APPEND_SLASH = False  # 该参数默认是True
        


    无名分组
        url(r'^test/([0-9]{4})/', views.test)
        路由匹配的时候 会将括号内正则表达式匹配到的内容 当做位置参数传递给视图函数
        test(request,2019)

    有名分组
        url(r'^test/(?P<year>\d+)/', views.test)
        路由匹配的时候 会将括号内正则表达式匹配到的内容 当做关键字参数传递给视图函数
        test(request,year=2019)

    # 无名有名不能混合使用 !!!
    url(r'^test/(\d+)/(?P<year>\d+)/', views.test),

    但是用一种分组下 可以使用多个
        # 无名分组支持多个
        # url(r'^test/(\d+)/(\d+)/', views.test),
        # 有名分组支持多个
        # url(r'^test/(?P<year>\d+)/(?P<xx>\d+)/', views.test),


    反向解析
        本质:其实就是给你返回一个能够返回对应url的地址

        1.先给url和视图函数对应关系起别名
            url(r'^index/$',views.index,name='kkk')

        2.反向解析
            后端反向解析
                后端可以在任意位置通过reverse反向解析出对应的url
                from django.shortcuts import render,HttpResponse,redirect,reverse
                reverse('kkk')

            前端反向解析
                {% url 'kkk' %}

    无名分组反向解析

        url(r'^index/(\d+)/$',views.index,name='kkk')

        后端反向解析
            reverse('kkk',args=(1,))  # 后面的数字通常都是数据的id值
        前端反向解析
            {% url 'kkk' 1%}   # 后面的数字通常都是数据的id值


    有名分组反向解析
        同无名分组反向解析意义的用法

        url(r'^index/(?P<year>\d+)/$',views.index,name='kkk')

        后端方向解析
            print(reverse('kkk',args=(1,)))  # 推荐你使用上面这种  减少你的脑容量消耗
            print(reverse('kkk',kwargs={'year':1}))
        前端反向解析
            <a href="{% url 'kkk' 1 %}">1</a>  # 推荐你使用上面这种  减少你的脑容量消耗
            <a href="{% url 'kkk' year=1 %}">1</a>

    注意:在同一个应用下 别名千万不能重复!!!

    作业(******):
        用反向解析完成用户的编辑和删除
        前后端都要用


    路由分发(******)
        当你的django项目特别庞大的时候 路由与视图函数对应关系特别特别多
        那么你的总路由urls.py代码太过冗长  不易维护

        每一个应用都可以有自己的urls.py,static文件夹,templates文件夹(******)

        正是基于上述条件 可以实现多人分组开发 等多人开发完成之后  我们只需要创建一个空的django项目
        然后将多人开发的app全部注册进来 在总路由实现一个路由分发 而不再做路由匹配(来了之后 我只给你分发到对应的app中)


        当你的应用下的视图函数特别特别多的时候  你可以建一个views文件夹 里面根据功能的细分再建不同的py文件(******)


        urlpatterns = [
            url(r'^admin/', admin.site.urls),
            url(r'^app01/',include('app01.urls')),
            url(r'^app02/',include('app02.urls')),
            url(r'^app03/',include('app03.urls')),
        ]




    名称空间(了解)
        多个app起了相同的别名 这个时候用反向解析 并不会自动识别应用前缀
        如果想避免这种问题的发生
        方式1:

            总路由
                url(r'^app01/',include('app01.urls',namespace='app01'))
                url(r'^app02/',include('app02.urls',namespace='app02'))

            后端解析的时候
                reverse('app01:index')
                reverse('app02:index')
            前端解析的时候
                {% url 'app01:index' %}
                {% url 'app02:index' %}

        方式2:
            起别名的时候不要冲突即可  一般情况下在起别名的时候通常建议以应用名作为前缀
                name = 'app01_index'
                name = 'app02_index'



    伪静态
        静态网页:数据是写死的 万年不变

        伪静态网页的设计是为了增加百度等搜索引擎seo查询力度

        所有的搜索引擎其实都是一个巨大的爬虫程序

        网站优化相关  通过伪静态确实可以提高你的网站被查询出来的概率
        但是再怎么优化也抵不过RMB玩家



    虚拟环境

        一般情况下 我们会给每一个项目 配备该项目所需要的模块 不需要的一概不装
        虚拟环境 就类似于为每个项目量身定做的解释器环境


        如何创建虚拟环境
            每创建一个虚拟环境 就类似于你又下载了一个全新的python解释器


    django版本的区别
        django1.X跟django2.X版本区别
            路由层1.X用的是url
            而2.X用的是path

            2.X中的path第一个参数不再是正则表达式,而是写什么就匹配什么 是精准匹配

            当你使用2.X不习惯的时候  2.X还有一个叫re_path
            2.x中的re_path就是你1.X的url


        虽然2.X中path不支持正则表达式  但是它提供了五种默认的转换器

            1.0版本的url和2.0版本的re_path分组出来的数据都是字符串类型
            默认有五个转换器,感兴趣的自己可以课下去试一下
            str,匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式
            int,匹配正整数,包含0。
            slug,匹配字母、数字以及横杠、下划线组成的字符串。
            uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。
            path,匹配任何非空字符串,包含了路径分隔符(/)(不能用?)



            path('index/<int:id>/',index)  # 会将id匹配到的内容自动转换成整型



        还支持自定义转换器
            class FourDigitYearConverter:
            regex = '[0-9]{4}'
            def to_python(self, value):
                return int(value)
            def to_url(self, value):
                return '%04d' % value  占四位,不够用0填满,超了则就按超了的位数来!
            register_converter(FourDigitYearConverter, 'yyyy')

            urlpatterns = [
                    path('articles/2003/', views.special_case_2003),
                    path('articles/<yyyy:year>/', views.year_archive),
                    ...
                ]


    视图层
        1.小白必会三板斧
            1.HttpResponse
            2.render
            3.redirect
            django视图函数必须要给返回一个HttpResponse对象

        前后端分离
            前端一个人干(前端转成自定义对象)
                JSON.stringify()        json.dumps()
                JSON.parse()            json.loads()
            后端另一个干(python后端用字典)
            只要涉及到数据交互,一般情况下都是用的json格式
            后端只负责产生接口,前端调用该接口能拿到一个大字典
            后端只需要写一个接口文档 里面描述字典的详细信息以及参数的传递
        2.JsonReponse
            from django.http import JsonResponse
            def index(request):
                data = {'name':'jason好帅哦 我好喜欢','password':123}
                l = [1,2,3,4,5,6,7,8]
                # res = json.dumps(data,ensure_ascii=False)
                # return HttpResponse(res)
                # return JsonResponse(data,json_dumps_params={'ensure_ascii':False})
                return JsonResponse(l,safe=False)  # 如果返回的不是字典 只需要修改safe参数为false即可

        3.上传文件
            form表单上传文件需要注意的事项
                1.enctype需要由默认的urlencoded变成formdata
                2.method需要由默认的get变成post
                (目前还需要考虑的是 提交post请求需要将配置文件中的csrf中间件注释)


            如果form表单上传文件 后端需要在request.FILES获取文件数据 而不再是POST里面


            request.method
            request.GET
            request.POST
            request.FILES  获取文件数据
            request.path  # 只回去url后缀 不获取?后面的参数
            request.get_full_path()  # 后缀和参数全部获取



    FBV与CBV(******)
总结
"""
Django settings for untitled1 project.

Generated by 'django-admin startproject' using Django 1.11.

For more information on this file, see
https://docs.djangoproject.com/en/1.11/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.11/ref/settings/
"""

import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'hr5k6-&@=n_=ri1#dt)s#9g1_zdt$(8yfkjk)gw#w-v65)e9lo'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01.apps.App01Config',
    'app02'
]

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',
]

ROOT_URLCONF = 'untitled1.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(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',
            ],
        },
    },
]

WSGI_APPLICATION = 'untitled1.wsgi.application'


# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'day53',
        'USER': 'root',
        'PASSWORD': 'llx20190411',
        'HOST': '127.0.0.1',
        'PORT':3306,
        'CHARSET':'utf8'
    }
}


# Password validation
# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/1.11/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/

STATIC_URL = '/static/'
STATIC_DIRS = [
    os.path.join(BASE_DIR,'static')
]

# 取消django响应机制,大白话
# 127.0.0.1:8000/test 不在自动+ / 变为 127.0.0.1:8000/test/
# APPEND_SLASH = False
settings.py
"""untitled1 URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.11/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.conf.urls import url, include
    2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url,include
from django.contrib import admin
from app01 import views
import json
from django.shortcuts import HttpResponse,redirect,render
from django.http import JsonResponse

def index(request):
    data = {'name': 'jason', 'password': 123}
    l = [1, 2, 3, 4, 5]
    res = json.dumps(data,ensure_ascii=False)
    # return HttpResponse(res)
    # return JsonResponse(data, json_dumps_params={'ensure_ascii':False})
    print(request.path)
    print(request.get_full_path())
    return JsonResponse(l, safe=False)

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^jsonsss/', index),
    # 主页
    url(r'^$', views.home),
    url(r'^test/$', views.test),
    url(r'^testadd/', views.testadd),

    # 无名分组
    url(r'^text/([0-9]{4})', views.text),
    # 无名分组支持多个
    url(r'^texts/(\d+)/(\d+)/', views.texts),

    # 有名分组
    url(r'^textadd/(?P<year>\d+)', views.textadd),
    # 有名分组支持多个
    url(r'^textadds/(?P<year>\d+)/(?P<xx>\d+)', views.textadds),
    # 无名有名不能混合使用
    # url(r'^txt/(\d+)/(?P<year>\d+)',views.txt),

    # 反向解析
    url(r'^index/(?P<year>\d+)$',views.index, name='kkk'), # 给当前视图函数起一个别名
    url(r'^login/$',views.login),
    # url(r'^app01/',include(app01_urls)),
    # url(r'^app02/',include(app02_urls)),
    url(r'app01/',include('app01.urls')),
    url(r'app02/',include('app02.urls')),
# 当所有的路由都没有匹配上的时候 固定走404处理逻辑
#     url(r'',views.error)
]
urls.py
from django.conf.urls import url
from app02 import views
urlpatterns = [
    # url(r'^index/',views.index,name='index'),
    url(r'^index.html',views.index,name='app02_index'),
    url(r'^login/',views.login)
]
app01/urls.py
from django.shortcuts import render,HttpResponse,reverse,redirect

# Create your views here.


def index(request):

    return HttpResponse("app02 index")



def login(request):
    # print(reverse('app02:index'))
    print(reverse('app02_index'))
    return HttpResponse('app02 login')
app01/views.py
from django.conf.urls import url
from app02 import views
urlpatterns = [
    # url(r'^index/',views.index,name='index'),
    url(r'^index.html',views.index,name='app02_index'),
    url(r'^login/',views.login)
]
app02/urls.py
from django.shortcuts import render,HttpResponse,reverse,redirect

# Create your views here.


def index(request):

    return HttpResponse("app02 index")



def login(request):
    # print(reverse('app02:index'))
    print(reverse('app02_index'))
    return HttpResponse('app02 login')
app02/views.py
import pymysql
pymysql.install_as_MySQLdb()
__init__.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    {% load static %}
    <link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}">
    <script src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script>
</head>
<body>
<form action="" method="post" enctype="multipart/form-data">
    <input type="file" name="myfile">
    <input type="submit">
</form>
</body>
</html>
templates/file.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    {% load static %}
    <link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}">
    <script src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script>
</head>
<body>
{#<a href="{% url 'kkk' 1111111%}">1</a>#}
{#<a href="{% url 'kkk' 11111%}">11</a>#}
{#<a href="{% url 'kkk' 11111%}">111</a>#}
{#<a href="{% url 'kkk' 1111%}">1111</a>#}
{#<a href="{% url 'kkk' 111%}">11111</a>#}
{#<a href="{% url 'kkk' 11%}">111111</a>#}

{#<a href="{% url 'app01:index' %}"></a>#}
<a href="{% url 'app01_index' %}">1</a>
</body>
</html>
templates/login.html

 

1.django请求生命周期.png

 


2.创建虚拟环境.png

 


3.虚拟环境标志.png

 


4.png

 

posted on 2022-04-06 13:38  没有如果,只看将来  阅读(37)  评论(0编辑  收藏  举报