python框架03 -- Django综述

简介

主要内容: Django运用、序列化、前后端分离、数据库连接、token头、数据交互

更新: 不定期更新,遇到相关问题则会添加到其中,若有问题请留言或者右下角直接联系

虚拟环境安装

安装

  • 安装python虚拟环境

    $ pip install virtualenv
    $ pip install virtualenvwrapper

    $ pip install virtualenvwrapper-win (windows系列)

    $ export WORKON_HOME=~/Envs
    $ mkdir -p $WORKON_HOME
    $ source /usr/local/bin/virtualenvwrapper.sh

    虚拟环境位置文档位置

    https://virtualenvwrapper.readthedocs.io/en/latest/

    • 注意点 virtualenv是初级的工具 只能用在你当前文件夹的目录下面去新建
    • wrapper所带的 mkvirtualenv 和 workon命令可以让你在任何地方管理虚拟环境 不用考虑文件夹位置
  • 新建一个虚拟环境 激活虚拟环境 并且安装django 查看安装的django版本

    virtualenv ruimi_django -p python3.6
    source ruimi_django/bin/activate
    pip install django==1.11
    python -m django --version
  • pycharm安装django环境

    1. 在pycharm中选择newproject django

    2. 选择虚拟环境(你在本地建好的虚拟环境)

    3. 点击create,新建成功

  • 命令行安装django

    1. 使用命令行创建django 效果等同于pycharm 其实pycharm的原理就是去帮你执行这些命令而已

    2. 我们需要先切换到有django的虚拟环境才行

      $ django-admin startproject test

通过django创建第一个app

  • 通过django 创建第一个app

    django-admin startapp movies

    有两个djano_mvc_ppt 第一个是总目录 第二个djano_mvc_ppt是项目的配置目录 settings urls 路由就在里面。他是定义整个项目的配置路由等。

    我们刚才新建的是app目录是单独的功能目录,比如用户信息就可以新建一个目录来表示。在app目录里面我们去定义视图,模型等等。这个在后面章节会讲到。

  • 启动django

    1. 命令行来启动django

      1. python必须是我们的django环境里面的python程序

      2. manage.py是我们django项目目录下面的manage.py

      3. runserver是启动django 后台服务的命令 后面跟上ip和端口即可

        python manage.py runserver 0.0.0.0:8000
    2. pycharm 启动django项目

      1. debug模式, 使用debug模式启动django,我们可以打断点,程序过来以后,就能截取到值

      2. run 模式,那么程序只会执行,不会有断点查看功能

      3. 最后 我们可以在下方 看到运行的状态

        1. 启动完成后我们就可以查看启动是否成功了

为什么使用1.11版本

  1. 2.0版本的lts(long time serve)目前还没有出来,到2019年我们就可以顺利使用django 2.0啦

apps详解

apps和整体配置文件内部结构

  • 最外部的manage.py

    一个命令行工具,实现django各种功能的文件,比如数据库迁移,静态文件收集,启动django服务等等

  • 首先我们来查看一下 djano_mvc_ppt的结构

    1. \__init__.py 它告诉Python这个目录应该被看做一个Python包
    2. settings.py 项目的整体配置文件,包含项目启动哪些app,中间件设置,第三方包配置等等都在里面
    3. urls.py 总路由配置文件
    4. wsgi.py 网关协议入口程序
  • apps的结构

    migrations 文件夹,数据库迁移记录文件

    init.py apps 初始化文件 一般为空即

    admin.py 自定义admin后台管理的地方

    apps.py app的在项目注册的名称,默认就行了

    models.py 定义数据模型

    tests.py 单元测试地址

    views.py 视图

第一个简单页面

  • movies/views.py

    from django.http import HttpResponse
    def test1(request):
    return HttpResponse("Hello, world!")
  • djano_mvc_ppt/urls.py

    	

    from movies.views import test1

    urlpatterns = [

    url(r'^test1$',test1)
    ]
  • 访问 http://127.0.0.1:8000/test1

    解释

  1. views 是我们视图函数 他们负责给用户返回什么样的信息
  2. url 是路由,试想一个网站有不同的页面,怎么样来走到不同的页面,就是通过这的路由分发来做的。我们把test1的网站转发到我们的views.py里面的test1函数
  3. 终上所述,我们在访问页面的时候,就得到了第一个页面

第二个页面

  1. 我们知道,百度等网页是复杂的html构成的,所以我们需要前端人员的html网页支持,django可以渲染出前端的html网页,使用render

    movies/views.py

    def test2(request):

    return render(request,'movies/index.html')

    djano_mvc_ppt/urls.py

    	

    from movies.views import test2

    urlpatterns = [

    url(r'^test2$',test2)
    ]

    templates/movies/index.html

    	
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Title</title>
    </head>
    <body>
    <h1>hello html</h1>
    </body>
    </html>

解释

django可以通过一定的方式,把html网页送给浏览器,这时候就不需要我们去直接回复一个字符串

第三个页面

  • movies/models.py

    from django.db import models

    # Create your models here.

    class Test(models.Model):
    name = models.CharField(max_length=11)
  • djano_mvc_ppt/settings.py

    	
    INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'movies'
    ]
    $ python manage.py makemigrations
    $ python manage.py migrate

    movies/views.py

    def test3(request):
    from movies.models import Test
    user = Test.objects.all()[0]

    return render(request,'movies/index2.html',context={'name':user.name})

    templates/movies/index2.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <h1>hello {{ name }}</h1>
    </body>
    </html>

解释

  1. model可以直接操控数据库,我们不用去写sql语句了,使用对象实例化就可以获取到语句

  2. views可以把数据库传递给html,我们称为模板渲染,因为不是html语法,他需要python去加工一下(渲染)

mtv模式

解释

我们上述的模式就是mtv模式

  1. views专门负责取出数据来,怎么取,取多少数据都在views里面
  2. model专门负责数据库控制,数据库字段怎么定义,这些字段代表什么就是model.py做的事情
  3. html文件负责页面的展现,css js等都写在里面,他就专门负责页面怎么美观就行了

综述

以上就是我们框架的基本模式,主要的思想就是各司其职,分层

函数视图

基础视图分析

  • request 里面有所有的信息,他的信息是我们的wsgi解析之后的报文,回想一下http协议,他所有的信息都在报文里面,是一个很长的字符串,但是我们看到的request里面是dict和object,说明django框架已经帮我们解析好了报文里面的信息

  • HttpResponse是django帮我们封装响应报文,返回我们想给浏览器返回的信息,当然也有其他的返回值,他们都是django帮我们封装好的

    Http404
    HttpResponseForbidden
    ...

    movies/views.py

    def test1(request):
        return HttpResponse("Hello, world!")

快捷函数

  • 我们来写一个能够渲染模板的函数,那么他需要使用HttpResponse来给用户返回信息

    movies/views.py

    def test5(request):
    from django.template import loader
    t = loader.get_template('movies/index.html')
    return HttpResponse(t.render({},request))
  • 如果我们觉得这样写很麻烦,那么我们可以使用快捷函数 render来帮我们做这个事情,凡是在 from django.shortcuts 中定义的函数,都是帮我们快捷的完成一些功能的函数

    movies/views.py

    	
    def test2(request):
    return render(request,'movies/index.html')
  • 查看一下render的源码,我们发现 其实就是我们刚才的原始函数,不过他帮我们做了一层封装

    def render(request, template_name, context=None, 
    content_type=None, status=None, using=None):
    """
    Returns a HttpResponse whose content is filled with the
    result of calling
    django.template.loader.render_to_string() with the passed
    arguments.
    """
    content = loader.render_to_string(template_name, context,
    request, using=using)
    return HttpResponse(content, content_type, status)
  • 其他快捷函数

    1. redirec 重定向,在访问一个网页的时候,帮助我们重定向

      def test6(request):
      return redirect('https://www.baidu.com')
    2. get_object_or_404 帮助我们查找数据,如果没有数据则返回404的错误

      def test7(request):
      obj = get_object_or_404(Test,pk=1)
      return HttpResponse(obj.name)

装饰器

  • 使用装饰器去控制函数视图的行为
from django.views.decorators.http import
                        require_http_methods
    @require_http_methods(['GET'])
    def test8(request):
        return HttpResponse('hello')


1. require_http_methods 控制行为,list传递
2. require_GET get行为
3. require_POST() post行为

类视图

>lietview
>
>deleteview

CSRF

CSRF概念

  1. 全称: CSRF跨站点请求伪造(Cross—Site Request Forgery)
  2. 解释: 攻击者盗用了你的身份,以你的名义发送恶意请求,对服务器来说这个请求是完全合法的,但是却完成了攻击者所期望的一个操作,比如以你的名义发送邮件、发消息,盗取你的账号,添加系统管理员,甚至于购买商品、虚拟货币转账等。 如下:其中Web A为存在CSRF漏洞的网站,Web B为攻击者构建的恶意网站,User C为Web A网站的合法用户。

CSRF攻击攻击原理及过程

  1. 用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A;

  2. 在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发送请求到网站A;

  3. 用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B;

  4. 网站B接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第三方站点A;

  1. 浏览器在接收到这些攻击性代码后,根据网站B的请求,在用户不知情的情况下携带Cookie信息,向网站A发出请求。网站A并不知道该请求其实是由B发起的,所以会根据用户C的Cookie信息以C的权限处理该请求,导致来自网站B的恶意代码被执行。

CSRF攻击实例

  • 攻击

    受害者 Bob 在银行有一笔存款,通过对银行的网站发送请求 http://bank.example/withdraw?account=bob&amount=1000000&for=bob2 可以使 Bob 把 1000000 的存款转到 bob2 的账号下。通常情况下,该请求发送到网站后,服务器会先验证该请求是否来自一个合法的 session,并且该 session 的用户 Bob 已经成功登陆。

    黑客 Mallory 自己在该银行也有账户,他知道上文中的 URL 可以把钱进行转帐操作。Mallory 可以自己发送一个请求给银行:http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory。但是这个请求来自 Mallory 而非 Bob,他不能通过安全认证,因此该请求不会起作用。

    这时,Mallory 想到使用 CSRF 的攻击方式,他先自己做一个网站,在网站中放入如下代码: src=”http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory ”,并且通过广告等诱使 Bob 来访问他的网站。当 Bob 访问该网站时,上述 url 就会从 Bob 的浏览器发向银行,而这个请求会附带 Bob 浏览器中的 cookie 一起发向银行服务器。大多数情况下,该请求会失败,因为他要求 Bob 的认证信息。但是,如果 Bob 当时恰巧刚访问他的银行后不久,他的浏览器与银行网站之间的 session 尚未过期,浏览器的 cookie 之中含有 Bob 的认证信息。这时,悲剧发生了,这个 url 请求就会得到响应,钱将从 Bob 的账号转移到 Mallory 的账号,而 Bob 当时毫不知情。等以后 Bob 发现账户钱少了,即使他去银行查询日志,他也只能发现确实有一个来自于他本人的合法请求转移了资金,没有任何被攻击的痕迹。而 Mallory 则可以拿到钱后逍遥法外。

防御CSRF攻击

  • 目前防御 CSRF 攻击主要有三种策略:验证 HTTP Referer 字段;在请求地址中添加 token 并验证;在 HTTP 头中自定义属性并验证。

  • (1)验证 HTTP Referer 字段

    根据 HTTP 协议,在 HTTP 头中有一个字段叫 Referer,它记录了该 HTTP 请求的来源地址。在通常情况下,访问一个安全受限页面的请求来自于同一个网站,比如需要访问 http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory,用户必须先登陆 bank.example,然后通过点击页面上的按钮来触发转账事件。这时,该转帐请求的 Referer 值就会是转账按钮所在的页面的 URL,通常是以 bank.example 域名开头的地址。而如果黑客要对银行网站实施 CSRF 攻击,他只能在他自己的网站构造请求,当用户通过黑客的网站发送请求到银行时,该请求的 Referer 是指向黑客自己的网站。因此,要防御 CSRF 攻击,银行网站只需要对于每一个转账请求验证其 Referer 值,如果是以 bank.example 开头的域名,则说明该请求是来自银行网站自己的请求,是合法的。如果 Referer 是其他网站的话,则有可能是黑客的 CSRF 攻击,拒绝该请求。

    这种方法的显而易见的好处就是简单易行,网站的普通开发人员不需要操心 CSRF 的漏洞,只需要在最后给所有安全敏感的请求统一增加一个拦截器来检查 Referer 的值就可以。特别是对于当前现有的系统,不需要改变当前系统的任何已有代码和逻辑,没有风险,非常便捷。

    然而,这种方法并非万无一失。Referer 的值是由浏览器提供的,虽然 HTTP 协议上有明确的要求,但是每个浏览器对于 Referer 的具体实现可能有差别,并不能保证浏览器自身没有安全漏洞。使用验证 Referer 值的方法,就是把安全性都依赖于第三方(即浏览器)来保障,从理论上来讲,这样并不安全。事实上,对于某些浏览器,比如 IE6 或 FF2,目前已经有一些方法可以篡改 Referer 值。如果 bank.example 网站支持 IE6 浏览器,黑客完全可以把用户浏览器的 Referer 值设为以 bank.example 域名开头的地址,这样就可以通过验证,从而进行 CSRF 攻击。

    即便是使用最新的浏览器,黑客无法篡改 Referer 值,这种方法仍然有问题。因为 Referer 值会记录下用户的访问来源,有些用户认为这样会侵犯到他们自己的隐私权,特别是有些组织担心 Referer 值会把组织内网中的某些信息泄露到外网中。因此,用户自己可以设置浏览器使其在发送请求时不再提供 Referer。当他们正常访问银行网站时,网站会因为请求没有 Referer 值而认为是 CSRF 攻击,拒绝合法用户的访问。

  • (2)在请求地址中添加 token 并验证

    CSRF 攻击之所以能够成功,是因为黑客可以完全伪造用户的请求,该请求中所有的用户验证信息都是存在于 cookie 中,因此黑客可以在不知道这些验证信息的情况下直接利用用户自己的 cookie 来通过安全验证。要抵御 CSRF,关键在于在请求中放入黑客所不能伪造的信息,并且该信息不存在于 cookie 之中。可以在 HTTP 请求中以参数的形式加入一个随机产生的 token,并在服务器端建立一个拦截器来验证这个 token,如果请求中没有 token 或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求。

    这种方法要比检查 Referer 要安全一些,token 可以在用户登陆后产生并放于 session 之中,然后在每次请求时把 token 从 session 中拿出,与请求中的 token 进行比对,但这种方法的难点在于如何把 token 以参数的形式加入请求。对于 GET 请求,token 将附在请求地址之后,这样 URL 就变成 http://url?csrftoken=tokenvalue。 而对于 POST 请求来说,要在 form 的最后加上 ,这样就把 token 以参数的形式加入请求了。但是,在一个网站中,可以接受请求的地方非常多,要对于每一个请求都加上 token 是很麻烦的,并且很容易漏掉,通常使用的方法就是在每次页面加载时,使用 javascript 遍历整个 dom 树,对于 dom 中所有的 a 和 form 标签后加入 token。这样可以解决大部分的请求,但是对于在页面加载之后动态生成的 html 代码,这种方法就没有作用,还需要程序员在编码时手动添加 token。

    该方法还有一个缺点是难以保证 token 本身的安全。特别是在一些论坛之类支持用户自己发表内容的网站,黑客可以在上面发布自己个人网站的地址。由于系统也会在这个地址后面加上 token,黑客可以在自己的网站上得到这个 token,并马上就可以发动 CSRF 攻击。为了避免这一点,系统可以在添加 token 的时候增加一个判断,如果这个链接是链到自己本站的,就在后面添加 token,如果是通向外网则不加。不过,即使这个 csrftoken 不以参数的形式附加在请求之中,黑客的网站也同样可以通过 Referer 来得到这个 token 值以发动 CSRF 攻击。这也是一些用户喜欢手动关闭浏览器 Referer 功能的原因。

  • (3)在 HTTP 头中自定义属性并验证

    这种方法也是使用 token 并进行验证,和上一种方法不同的是,这里并不是把 token 以参数的形式置于 HTTP 请求之中,而是把它放到 HTTP 头中自定义的属性里。通过 XMLHttpRequest 这个类,可以一次性给所有该类请求加上 csrftoken 这个 HTTP 头属性,并把 token 值放入其中。这样解决了上种方法在请求中加入 token 的不便,同时,通过 XMLHttpRequest 请求的地址不会被记录到浏览器的地址栏,也不用担心 token 会透过 Referer 泄露到其他网站中去。

    然而这种方法的局限性非常大。XMLHttpRequest 请求通常用于 Ajax 方法中对于页面局部的异步刷新,并非所有的请求都适合用这个类来发起,而且通过该类请求得到的页面不能被浏览器所记录下,从而进行前进,后退,刷新,收藏等操作,给用户带来不便。另外,对于没有进行 CSRF 防护的遗留系统来说,要采用这种方法来进行防护,要把所有请求都改为 XMLHttpRequest 请求,这样几乎是要重写整个网站,这代价无疑是不能接受的。

Form表单

作用

django的form有两个功能,第一个是帮助我们生成表单,在html里面,第二个功能是帮我们验证表单

生成表单

  • 首先我们会在一个外部的forms.py文件里面建立我们的表单类,在这个类的定义的字段会直接显示在html里面,我们不用在html里面去写input标签

    test1/forms.py

    from django import forms

    class LoginForm(forms.Form):
    zhanghu = forms.CharField(max_length=10)
    mima = forms.CharField(max_length=20)
  • 在views里面去实例化表单类,注意,我们是去实例化forms.py里面的LoginForm 然后把实例化的对象login_form 传递给模板 login_test.html 传递的值是 form

    test1/views.py

    def test5(request):

    from movies.forms import LoginForm
    method = request.method

    if method == "GET":
    login_form = LoginForm()
    return render(request,'test1/login_test.html',{'form':login_form})
    elif method == "POST":
    account = request.POST['account']
    password = request.POST['password']
    return HttpResponse('POST')
  • 在html里面去调用form,以为接受值,因为我们在views.py里面定义就是form,当然我们也可以定义其他的值

    return render(request,'test1/login_test.html'
    ,{'form':login_form})

    templates/movies/login_test.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Title</title>
    </head>
    <body>
    <h1>hi Login!</h1>

    <form action="http://127.0.0.1:18001/login/"
    method="post">{{ form }}

    </form>
    </body>
    </html>

项目整体

安装

创建项目

  • pycharm中可直接创建; 或者命令行:django-admin startproject priject_name

  • 运行Django:python3 manage.py runserver 浏览器打开有小火箭即成功

  • 创建app:python3 manage.py startapp app_name

  • pycharm: debug运行 :edit可设置ip和端口

Django配置

  • 配置目录

与Django一样名字的目录为配置目录

urls:各种链接,功能的实现,路由URL

1.path(‘地址栏取名’,相关函数)

例如:path(‘hello/‘, views.hello_world)

2.需要使用import调用函数所在文件 调用的为views中的函数

例如:from app1 import views

settings:

1.allowed_hosts(允许访问的IP)bug:同一局域网里IP可随意访问

2.templates:模版 ‘dirs’:确认html放置的文件夹

例如:’DIRS’: [os.path.join(BASE_DIR, ‘templates’)]
base_dir:该项目的路径

  • app操作

自己建立的app包中:

views:创建函数

1.httpresponse函数:创建报文内容 用于return HttpResponse(‘html语句’) 需要使用import导入该函数

2.requests参数:创建函数时必须加上该参数,用于接收数据等便于使用

3.render(re参数,html位置—>直接html名,参数dict) :将其发送给浏览器

文件发送

  • html:

    • 创建放置html文件夹
    • 确认文件夹位置:settings 2 templates中
    • 书写html
    • 编写调用函数 views 3
    • urls增加该网页 urls 1,2
  • css/js/images(静态文件访问):

    • 在编写的html中增加

      		<head>中加:
      激活:
      {% load static %}
      自动生成静态文件链接:
      <link rel="stylesheet" href='{% static "css.css" %}'
      >html中的{{}}<li>{{ age }}</li>
      编写views中的函数内容时可以将{{}}中的参数以dict的形
      式发送过来并替换其中的字段
      ```

      * 创建css js文件夹
      * settings添加:
      >1.设置访问url的路径(网址名):STATIC_URL = '/static/'
      >2.确认位置:STATICFILES_DIRS = [os.path.join(BASE_DIR, “html存放路径”),]


      * 配置urls:

      ```python
      from django.conf import settings 调用上面的设置
      from django.conf.urls.static import static 调用该函数
      urlpatterns = [
      ]+static(settings.STATIC_URL)
    • 书写css js images

    • 浏览器访问:/static/css.css

    • 浏览器访问对应html便可以

数据库连接

  • 与settings在相同文件夹下创建:my.cnf普通文件

    # my.cnf
    [client]
    database = NAME
    user = USER
    password = PASSWORD
    default-character-set = utf8mb4
  • settings设置:databases 中将本身数据库配置替换成mysql的配置代码

    # settings.py
    DATABASES = {
    'default': {
    'ENGINE': 'django.db.backends.mysql',
    'OPTIONS': {
    'read_default_file': os.path.join(base_dir,‘django_s’,’my.cnf’),
    },
    }
    }
  • 安装pymysql :

    pip install pymsql 

    // pycharm/preferences/project.django_s/
  • Django使用mysql:settings同级的init中增加代码:

    (1).__init__中代码:
    import pymysql
    pymysql.version_info(2,0,0)
    <—版本报错问题解决 无可不修改
    pymysql.install_as_MySQLdb()

    (2).在external library//site-packages/django/db/backends/
    mysql/operations

    中将与下面5 1对应修改146
    可以先运行会自定跳到该错误这里修改即可

    last_executed_query中query.decode改成encode

数据库操作

  • 命令行:在manage.py同级目录下执行

    python3 manage.py migrate —>在mysql中直接创建django内置的表

    (1).出现’decode’:在 external library/python 3.7/site-packages/django/db/ backends/mysql/operationslast_executed_query中query.decode改成encode (直接vim修改)

  • orm:通过对象操作数据库

    • 在views同级的models.py中编写定义自己的数据库表:即class创建

      例如:创建一个文章发布的数据库
      score = models.FloatField(default = 0,verbose_name=‘电影评分’)
      class Article(models.Model):
      title = models.CharField(max_length=255) #文章标题
      punish_time = models.DateTimeField() #文章发布时间
      author = models.CharField(max_length=20) #文章作者
      text = models.CharField(max_length=2000) #文章内容

      def __str__(self):
      return self.title
      (admin中直接以title字段显示)
    • 在settings:

      installed_apps=[‘添加自己创建的app,即views所在文件夹名’
      例:’app1’]
    • 生成数据库表:命令行执行:

      1.python3 manage.py makemigrations   
      (会在migrations文件夹下生成一个数据库迁移文件)
      2.python3 manage.py migrate
      (根据(3)生成的建表文件在数据库中建表)

      注意:1执行成功的迁移文件会在数据库中django_migrations表中也创建一个该记录必须同时存在才行 不然会一直报错:table

      解决:(1)删除migrations中的相关文件 再删除数据库表中的对应的记录 重新执行上述两个命令

    • 数据库表数据读取并在html中显示出来:

      1.创建html相关网页

      2.views:创建函数提取:引入models中的相关class 即2(1)中创建的相关表的类名from app1.models import Article

      编写发送函数:
      def article(requests):
      #相当于select * from article where id = 1
      语句(并未执行):
      data = Article.objects.filter(id=1)
      #切片执行该语句:
      res = data[0]
      return render(requests,’article.html’,
      {html中{{}}}的对应值dict})
  • 配置urls :与上面urls配置一样 先导入再添加

admin用户创建

  • 命令行:

    python3 manage.py createsuperuser (本次设置user:wangqi password:wang1995)

  • 添加数据库到admin

    • admin文件中添加代码

       导入models中创建的数据库类名:
      from app1.models import Article
      添加到admin中:
      @admin.register(Article)
      class ArticleAdmin(admin.ModelAdmin):
      pass
    • 浏览器中进入admin即有自己创建的数据库,可以进行相关插入等操作

外部app(或者html)

在django文件夹下:

python3 manage.py startapp ‘名字’ 创建新的app

先运行 python3 manage.py rumserver 确定Django开启成功

将其外部的网页代码放入django 项目下

  • 配置路径

    settings installed_apps添加该app名 templates:添加html存放路径
    在最后添加存放静态文件(html中的css/js)的代码以及媒体文件的media路径(见下)

  • 配置urls 先连接index.html看是否成功

  • 设置css/js/images

    1) python中 提供 win+r 可以查询+替换修改代码中的相关代码

    2) 在使用正则表达式时需要勾选Regex

    3) 查询:(css/.*\.css) 加括号表示一个整体\ 转译

    4) 替换:

  • 建立数据库:

    1)modele:建表 + 命令行操作数据库链接

    2)admin建立后台

    3)settings设置路径 databases添加数据库my.cnf文件位置

    4)views添加查询和插入函数将切片转到html代码中去:

    html中循环:`{% for %}循环代码{% endear %}`				
    例如
    views:
    def index_movie(requests):
    data = Movie.objects.all()
    return render(requests, 'index.html'
    {‘data’:data}
    html:
    {% for movie in data %}
    <li><p class='title'>{{ movie.title }}</p></li>
    {% endfor %}
    模版中切片:
    {% for movie in data |slice:"0:5"%}取前5

    url建立连接

图片处理

  • models:添加字段:

    img = models.ImageField(upload_to=’images’,verbose_name=’电影图片’)再执行数据库操作2(3)

    注意 :进行3第一步时会跳出选择:

    1.后续更改 先创建 2.退出,先添加 选择1 然后随便添加内容回车html中修改图片的链接

html中使用自定义函数

  • 函数模版:

    在app中建立一个目录:名字固定:templatetags 其中包含init文件

    创建一个功能名.py文件

    在该.py中自定义函数编写:

    模版:
    from django import template
    register = template.Library()
    import math

    @register.filter(name = ‘count_star’)
    #计算星星数量
    def count_star(value):
    return range(math.floor(value))

    在需要该函数的html中装载:{% load 功能名 %}

媒体文件访问

  • 图片以及视频与静态文件分开:

    (1)创建图片视频等存放文件夹

    (2)settings :

    templates添加:

    django.template.context_processors.media
    最后添加:#代表媒体文件的存储路径
    MEDIA_ROOT = os.path.join(BASE_DIR,'media')
    #指定后 其媒体文件根目录为media
    MEDIA_URL = '/media/'

    (3)urls:

    调用re_path 使用正则表达式

    from django.urls import path,re_path
    from django.views.static import serve
    from p1904_django2.settings import MEDIA_ROOT,MEDIA_URL

    urlpatterns添加:
    re_path(r'^media/(?P<path>.*)$', serve,
    {'document_root':MEDIA_ROOT}),

    (4)html:

    装载:{% load movie_extras %} 

    替换所有img:{% static movie.img.url %}
    \{ % static '(images/.*\.jpg)' %\}

    替换成: {{ MEDIA_URL }}images/m15.jpg
    \{ MEDIA_URL }}$1以及:{{ movie.img.url }}

    (5)models:

    修改img的存储结构(路径格式)其媒体跟目录为media 只需要在这个跟目录下创建images文件用来存放媒体文件即可

登陆 注册 退出

  • django 自带用户表 auth_user :password pbkdf2_sha256$150000$ 使用sha256加密了150000次使用该表并使用orm继承并扩展

  • 建立一个用户单独的app python3 manage.py startalp users (django官网:documentation 查询user有步骤)

  • 用户models 中

    from django.contrib.auth.models import AbstractUser #在用户app中继承用户模型

    class UserInfo(Abstract..)

  • 添加app到 settings:确认其修改

    INS.._APP添加:users

    AUTH_USER_MODEL = ‘users.UserInfo’

  • 命令行执行:数据库迁移

    执行时会出问题:用户表在数据库中存在,删除不了

    解决办法:在Django之前就创建好上诉继承代码 若已经创建 直接删除所有表然后再python3 manage两步 再创建命令行超级用户

  • 注册功能:

    	views:导入数据库models中创建表类名

    def register(requests):pass

    UserInfo.objects.create_user(username=
    requ.POST[‘username’],password=..)
    creat_user:可在生成名字时就会生成密码
    return HttpResponse(‘hello’) #检测链接

    出现CSRF验证:settings中middleware中注销掉Csrf

    urls:添加该函数到path网页中找到注册表单—html中找到相应位置
    修改action http://ip/register函数所有表单信息便传到该函
    数的requests中
    ```

    * 登陆功能:

    ```python
    views:
    def login(re..):
    username = re…POST[‘username’]
    password = re…POST[‘ps’]
    user = UserInfo.objects.filter(username=username)[0]
    #数据库查询语句 查询用户表中username密码
    check_password 函数(需要导入): 检测密码
    return

    注意:表单形式的验证前后端需要同时做:
    例如:密码验证需要前后端都同时做
    前端:html:min_length = ‘4
    (这里设置后,如果后端没改,前端网页里的限制条件仍然可以改,
    因其html保存在本地的,在elements中可以修改,相当于漏洞)

    后端:if leng(‘username’) < 4:
    return HttpResponse(‘用户名长度必须大于4’)
    ```

    * 7.登陆注册只用后端做的方法

    ```python
    forms模块(表单渲染 生成表单和验证表单 生成表单属于index中的
    解决6中注意)

    class LoginForm(forms.Form)
    charfield:数据库中为varchar()
    html:type元素 app中创建forms.py文件

    导入forms模块 :
    与创建module一样创建相关class,比如登陆表单的input字段等
    密码字段定义:
    password = forms.CharField(min_length =8, widget
    =forms.PasswordInput)
    将type中改成password邮箱字段:EmailField
    网址字段:urlfiled
    views:添加该相关函数的值到html调用函数中进行实例化,
    f = LoginForm() 表示在html中生成表单

    html:在form表单中直接使用该字段

    验证表单:
    users app中
    导入表单
    f = LoginForm(requests.POST)
    print(f.is_valid()) :ture false
    表示该表单符合创建表单其中的字段限制
    username = f.cleaned_data[‘username’]
    从cleaned中取html中验证成功的相关字段(与form表单中的字
    段名需要一致)用户不存在:try

    ModelForm模块(与数据库相连,比上面更好,可以以数据库中字段创建表):
    forms.py:
    from django.contrib.auth import get_user_model
    #获取user的数据库信息 类

    User = get_user_model()
    class UserForm(forms.ModelForm): #
    class Meta:
    model = User #创建用户模版
    fields = (“username”, “password”)
    #需要验证的字段
    #选择需要修改的字段
    widgets = {
    ‘password’: forms.PasswordInput(
    attrs={“min_length”:8}),
    #设置最小长度 (数据库中该字段只有max_length)
    ‘username’: forms.TextInput(attrs={“
    min_length”:4,‘class’: text})
    #启动class字段 }
    html/views:
    users/views:
    登陆注意:is_valid()函数会验证在数据库中是否存在,
    需要在上述中将该方法在上面类下重写方法
    def validate_unique(self):pass
  • 保持登陆: Django中的login方法

    引用:
    from django.contrib.auth import login as user_login
    在登陆函数中
    users/views/login:check_password
    正确后:
    user_login(requests, user)
    将该user加到报文中,并在html中保存为session以及数据库中保存在
    登陆页面(index.html):
    加入判断语句:
    {% if not requests.user.is_authenticated %}
    判断是否登陆,以此返回不同的标签 {% else %}{% endif %}
    以此保持登陆

    退出:
    loginout模块
    user/views:
    def logout:user_logout(requests)
    return HttpResponse(‘logout success’)

    --urls--中配置
    html中加入到相关href中
    urls:可以设置别名:name=‘’
    相应href 中可以使用{% -url- ‘别名’ %}
    可以把固定地址换成与后台同步

    跳转页面
    from django.shortcuts import redirect
    from django.urls
    return redirect(‘http// …’)
    return redirect(‘别名’)
  • 评分:

    	新建评分app
    settings:添加app
    新建model:导入models Movie get_user_model 模块
    User = get_user_model
    class Score(models.Model):
    tags = ((1, ‘aa’),(2,’bb’),)
    movie_score = models.Int..(choices=tags)
    选择分数
    movie = models.ForieginKey(‘movie.Movie’,
    on_delete=models.CASCADE)
    删除的方式
    user = models.for…key(‘users.UserInfo, ..’)

    class Meta:
    unique_together = (‘movie’, ‘user’) 唯一

    注意:字段不能与相关联表的字段重合

    命令行创建数据库表

    修改之前自定义打星函数:
  • 部署:将本地代码放到云服务器以便所有人都可以访问

1.服务器
2.登陆部署电脑:ssh rimi@10.2.0.26
3.本地上传代码到 git 再在部署电脑上拷贝下来
4. 部署机:安装django, 注意版本号
5.输出本地关于oython3的所有包版本号:pip3 freeze > requirements.txt
6.服务器:pip3 install -r requirements.txt
7. 启动 0.0.0.0:8000 所有人都可以访问(测试用)gunicorn(上线)
8.gunicorn: 安装 线程数量:cpu*2 +1 进程 = 线程/2
9.启动:wigs: scoket 接收http协议 需要将python的socket替换成wigs
10.访问日志/报错
11.图片美化 分类搜索 活动 后台分类(分级)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值