Django 高级特性总结 - archering/basic GitHub Wiki

Django 高级特性总结

通过命令创建一个django项目

django-admin startproject 项目名

项目创建后,结构如下:

project_name
  ├──project_name
  │	 ├──__init__.py
  │	 ├──settings.py
  │	 ├──urls.py
  │	 └──wsgi.py
  └──manage.py

__init__.py 这个文件的存在决定了这是一个package

settings.py django项目的配置文件,内部变量均大写,他配置了启动的端口,静态目录,模板目录....

CACHE_BACKEND默认值: 'simple://'
DATABASE_HOST默认值: ''
DATABASE_NAME默认值: '' (空的字符串)
DATABASE_PASSWORD默认值: '' (空的字符串)
DATABASE_PORT默认值: '' (空的字符串)

DEBUG默认值: False
DEFAULT_CHARSET默认值: 'utf-8'
DEFAULT_CONTENT_TYPE默认值: 'text/html'
ENABLE_PSYCO默认值: False    #如果允许 Psyco, 将使用Pscyo优化 Python 代码. 需要 Psyco 模块.
IGNORABLE_404_ENDS默认值: ('mail.pl', 'mailform.pl',  'favicon.ico', '.php')
LANGUAGE_CODE默认值: 'en-us'    #一个 tuple('da', _('Danish')),('de', _('German'))
PREPEND_WWW默认值: False    # 是否为没有 "www." 前缀

SESSION_COOKIE_NAME默认值: 'sessionid'
SESSION_COOKIE_AGE默认值: 1209600 (2周, 以秒计)   # session cookies 的生命周期, 以秒计
SESSION_COOKIE_DOMAIN默认值: None
SITE_ID默认值: Not defined

urls.py 路由的映射关系,最重要的urlpatterns 这个list, 定义映射关系在这里

wsgi.py Web Server Gateway Interface

#回到 manage.py 所在的目录 

python manage.py runserver  # 启动server

django 如何host 静态资源(通过url可以直接访问css,html,js, 图片...)

修改项目中的配置文件 settings.py

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

STATIC_URL = '/statics/'  #  这个目录是存放在项目根目录下的
STATICFILES_DIRS = [ # list 或 tuple, 静态资源的绝对路径根目录
    os.path.join(os.path.dirname(__file__), '../statics/').replace('\\', '/')
]

配置完上面两个信息,重启服务,就可以通过url访问资源了

假设我们在项目根目录简历了一个叫 statics的文件夹,里面建子目录js,css, css目录里面放着bootstrap

statics ├──css │ └──bootstrap3.3.6 │ ├──css │ ├──js └──js

http://localhost:8001/statics/css/bootstrap3.3.6/css/bootstrap.css  # 这样就可以在浏览器输出css内容了

模板中使用静态资源有两种方式

一种是直观的,url地址方式,向上面这个css访问的地址是

http://localhost:8001/statics/css/bootstrap3.3.6/css/bootstrap.css

模板中直接引用或者采用相对地址的方式,单数注意,需要进入父级目录(否则前面会跟着虚拟机名字) ..

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <link rel="stylesheet" href="../statics/css/bootstrap3.3.6/css/bootstrap.css">
</head>

另外一种通过 {% load staticfiles %} href 哪块有个变量 static 不是 statics

{% load staticfiles %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>template render</title>
    <link rel="stylesheet" href="{% static 'css/bootstrap3.3.6/css/bootstrap.min.css' %}">
</head>

block 块中需要再次 load staticfiles 要不然无法使用static 变量

下面例子, base.html 中已经 load static了, block main 中 需要再次 load staticfiles, 否则无法使用 static

{% extends 'base.html' %}

{% block main %}
    {% load staticfiles %}
    <div class="hello max">
        hello world
    </div>
    <button class="btn btn-info max">click me</button>
    <script src="{% static 'angular/angular.min.js' %}"></script>
    <script>
        console.log(angular);
    </script>
{% endblock %}

STATIC_ROOT 是在部署静态文件时(pyhton manage.py collectstatic)所有的静态文静聚合的目录,STATIC_ROOT要写成绝对地址

STATIC_ROOT 是在部署的时候才发挥作用, 而实际情况下,静态文件的一般安放位置有两种:

1.一种就是在每个app里面新建一个static文件夹,将静态文件放到里面,在加载静态文件时,比如要在模板中用到静态文件,django会自动在每个app里面搜索static文件夹(所以,不要把文件夹的名字写错哦, 否则django就找不到你的文件夹了)

2.另一种,就是在所有的app文件外面,建立一个公共的文件夹, 因为有些静态文件不是某个app独有的,那么就可以把它放到一个公共文件夹里面,方便管理(注意,建立一个公共的静态文件的文件夹只是一种易于管理的做法,但是不是必须的,app是可以跨app应用静态文件的,因为最后所有的静态文件都会在STATIC_ROOT里面存在) 那现在的问题是**如何让django知道你把一些静态文件放到app以外的公共文件夹中呢,**那就需要配置STATICFILES_DIRS了

STATICFILES_DIRS告诉django,首先到STATICFILES_DIRS里面寻找静态文件,其次再到各个app的static文件夹里面找(注意, django查找静态文件是惰性查找,查找到第一个,就停止查找了)

STATICFILES_DIRS = [
      os.path.join(os.path.dirname(__file__), '../statics/').replace('\\', '/'),
      os.path.join(os.path.dirname(__file__), '../node_modules/').replace('\\', '/')
]

这个变量设置之后,静态文件的查找就会先在这个列表描述的地址里面进行,然后是个app自己的static文件夹

此时并不能通过 浏览器地址栏直接输入 url的方式 找到这些静态资源

django利用STATIC_URL来让浏览器可以直接访问静态文件

你可以在浏览器中输入 http:// ...../static/jquery/dist/jquery.js

当django服务发现static这个路由时,就会去 STATICFILES_DIRS 列表对应的路径下去搜 jquery/dist/jquery.js

搜到之后就显示出来。

STATIC_URL = '/static/' 是一个映射route, 具体是对应(上面列表里的)node_modules 还是 statics目录完全取决于在哪里找到这个资源。

<script src="{% static 'jquery/dist/jquery.js' %}"></script>   

###django 项目中给静态资源加header 头部信息

from django.views.generic.base import View
from django.http import HttpResponse
from django.shortcuts import render
from . import models
from .help import getURL
class Hello(View):
    def get(self,request):
        lis = models.CharlesList.objects.all()
        print(lis)
        response = render(request,getURL("me_first/templates/db.html"),{"list":lis})
        response["Cache-Control"] = "public;max-age=" + str(60*60*1000)
        response["X-XSS-Protection"] = "1; mode=block"
        response["X-Frame-Options"] = "SAMEORIGIN"
        response["X-Content-Type-Options"] = "nosniff"
        return response

###summary

STATIC_URL = '/static/' 是一个映射route

STATICFILES_DIRS 静态资源搜索列表

STATIC_ROOT 静态资源聚合目录


URLs.py

当从浏览器发来的请求到达Django之后,Django首先去urls.py去找urlpatters列表,这个列表对应着相应的路由和具体解析和处理这个路由的类

views.py

Django 的views 就是其他MVC框架中的controllers

view 默认接收一个request 对象,返回一个response对象

view 可以是一个function 也可以是一个Class-based view

Class-based view 一般继承AE712109-11B3-403D-9E34-7C298238362D自django.views.generic.base.View (已经实现了许多方法,不必从头写起)

view.py 代码具体来说只用来处理request请求,执行各种业务逻辑,展现层面的东西最好交给template

os.path.dirname(__file__)  #指的是 当前文件所在目录,不包括文件名
os.path.abspath(__file__) #指的是 当前文件的绝对路径,包括文件名
os.path.dirname(os.path.dirname(__file__)) #指的是 当前文件所在目录的所在目录,即上一层文件夹。

settings.py 里面要有TEMPLATES.DIRS ,要不然 render_to_response("temp0.html",{date:date.today()}) 不知道去哪里找这个temp0.html

实现从template的直接渲染展现界面的方式有两种,一种 django.shortcuts.render_to_response

另一种是使用django.views.generic.base.TemplateView 继承并override 里面的方法

views.py

views 是个笼统的概念,任何一个*.py都有可能是一个view。

view 可以基于function

from django.shortcuts import render
from django.http.response import HttpResponse 

def index(request):
    return HttpResponse("hello this is from function based view")

urls.py 引入时可以

from . import funView

path("func/",funView.index),

也可以基于class

from django.views.generic.base import  View
from django.http.response import HttpResponse
from django.shortcuts import render_to_response
from datetime import date
class Temp(View):
    def get(self,request):
        return render_to_response("temp0.html",{date:date.today()})

urls.py引入可以这样

from .temp import Temp

path("temp/",Temp.as_view()),

view 里面的template 混合写python 代码应该这样写: 要有一个开始 和 结束的block 。 比如 if --- endif

    <table border="1">
        {% for item in tableList %}
            <tr>
                <td>{{item.a}}</td>
                <td>{{item.b}}</td>
                <td>{{item.c}}</td>
                <td>{{item.d}}</td>
                <td>{{item.e}}</td>
            </tr>
        {% endfor %}
    </table>
    {% if hello %}
    <h1>{{hello}}</h1>
    {% endif %}

django中静态资源的压缩compress和缓存cache

Django其实自带了Hash和Cache静态文件的功能,在默认情况下没有启动而已

启用静态资源缓存,修改settings.py

STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.CachedStaticFilesStorage'

当进行部署时,Debug=True,执行python manage.py collectstatic 就会自动在生成hash命名的静态文件在STATIC_ROOT/CACHE/下面

压缩静态文件

  1. 安装django_compressor
pip install django_compressor

2.设置(setting.py)

INSTALLED_APPS = (
    # other apps
    "compressor",
)
# 增加Finders
STATICFILES_FINDERS = (
    'django.contrib.staticfiles.finders.FileSystemFinder',
    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
    # other finders..
    'compressor.finders.CompressorFinder',
)

# 设置默认参数
COMPRESS_ENABLED = True
COMPRESS_OFFLINE = True
  1. 模板中使用

    # 在模板中使用
    {% load staticfiles compress %}
    
    {% compress css %}
    <link rel="stylesheet" href="/static/css/one.css" type="text/css" charset="utf-8">
    <style type="text/css">p { border:5px solid green;}</style>
    <link rel="stylesheet" href="/static/css/two.css" type="text/css" charset="utf-8">
    {% endcompress %}
    
    {% compress js %}
    <script src="/static/js/one.js" type="text/javascript" charset="utf-8"></script>
    <script type="text/javascript" charset="utf-8">obj.value = "value";</script>
    {% endcompress %}
    

    部署

    首先,确认在setting.py中加入了STATIC_ROOT并修改DEGUB=False 
    然后,执行以下命令:
    
    python manage.py collectstatic  # 执行之后会生成STATIC_ROOT 指定的目录结构,并聚合所有静态文件
    python manage.py compressor
    

models.py

以下事例中,me_first 是创建的项目名字或者应用名

sqllite 数据库可视化工具 SQLitestudio

通常都要继承自 django.db.models, 这个里面定义的class 数据结构类将用来生成数据库(默认sqllite)中相应的表。

django 创建数据库INSTALLED_APPS 里面去

me_first 这个要加到 settings.py 的

python manage.py makemigrations me_first
Migrations for 'me_first':
  me_first\migrations\0001_initial.py
    - Create model Charles
    - Create model CharlesList

同时,项目的目录下会创建一个 migrations的文件夹,这个里面偶有一个 0001_initial.py 保存着表的映射关系

makemigration 命令会创建migrations目录,并记录所有关于models.py的改动,这个改动还没有作用到数据库

python manage.py migrate #将 models.py 的表关系实际生成数据库中的表

EE4949B4-1548-41C6-9220-F1816D6B22D1

当0001_initial.py 文件创建后,可以使用以下命令,查看sql执行命令将怎样创建表结构

python manger.py sqlmigrate me_first 0001

如果你修改了models.py 你需要重新执行上面两个命令刷新数据库的表结构

class Charles(models.Model):
    # fk = models.ForeignKey(CharlesList)
    name = models.CharField(max_length=100)
    gender = models.IntegerField()
    due_date = models.DateTimeField()
    passed = models.BooleanField(default=False)  # 新增
    fk = models.ForeignKey(CharlesList,on_delete=models.CASCADE) #新增

351F2711-9303-44FD-B1E5-E6160E8E5968

如果在执行命令中出现下面问题

(pyone) D:\py\me_first>python manage.py makemigrations me_first
You are trying to add a non-nullable field 'fk' to charles without a default; we can't do that (the database needs something
Please select a fix:
 1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
 2) Quit, and let me add a default in models.py
Select an option: 2

解决办法:

  1. 先修改models.py ,添加一个 default=1

      fk = models.ForeignKey(CharlesList,on_delete=models.CASCADE,default=1)
    

  2. 执行命令

    python manage.py makemigrations me_first
    

  3. 删除default =1 保存

fk = models.ForeignKey(CharlesList,on_delete=models.CASCADE)

  1. 再执行 命令

    python manage.py makemigrations me_first
    
    python manage.py migration
    

创建superuser

python manage.py createsuperuser   # 创建一个 admin  密码是admin123的 超级用户

8284D8C0-2B2F-425C-B922-434314B03DEE

运行程序,进入admin

966DADF6-057C-47E9-A162-1A862138CE50

用你创建的超级用户登录B6586759-4330-4C80-80CC-D13206D14317

⚠️ **GitHub.com Fallback** ⚠️