Django3.2学习笔记

基本常用命令

django-admin

django-admin startproject myproject:创建一个django工程,其中myproject为工程名;
执行上述命令后,会生成如下目录结构:
myproject/
|------myproject/
|        |------__init__.py
|        |------asgi.py
|        |------settings.py:Django项目配置文件,包括Django模块应用配置、数据库配置、模板配置等
|        |------urls.py:Django路由配置
|        |------wsgi.py:与WSGI兼容的Web服务器,为项目提供服务入口
|------manage.py:命令行工具,支持不同的交互运行方式

manage

  说明:manage.py在Django工程目录下,执行python manage.py命令时,需要先进入工程目录下
  • python manage.py startapp myapp:创建一个App,其中myapp为App名称;
执行上述命令后,会在myproject工程目录下生成如下目录结构:
myproject/
|------myproject/:目录结构参见django-admin命令执行后生成的目录结构
|------manage.py:命令行工具,支持不同的交互运行方式
|------myapp/
|       |------migrations/:用于记录models中数据结构的变更
|       |------__init__.py
|       |------admin.py:Django自带的后台管理
|       |------apps.py:用于应用程序配置
|       |------models.py:Django数据模型,定义应用程序数据结构(对应数据库的相关操作)
|       |------tests.py:Django测试用例相关
|       |------views.py:Django视图模块,控制前面页面显示的内容
  • python manage.py runserver 127.0.0.1:8000:启动Django项目,其中127.0.0.1:8000为项目访问地址及端口
  • python manage.py shell:以终端命令交互的方式启动Django项目
  • python manage.py test:执行Django测试用例,默认为myproject/myapp/tests.py中的用例
  • python manage.py makemigrations:创建数据模型变更记录,当数据模型发生变化时,会在myproject/migrations目录下生成新的形如"0001_initial.py"的文件
  • python manage.py migrate:数据库迁移,当settings中配置好数据库后,执行此命令会在数据库中生成相应的数据表结构

Django架构

MVC & MTV

    0
Model数据模型
数据存取层,定义系统的数据表结构
View视图模块
建立用户与系统的连接页面,用户通过request发送请求给Controller,再由Controller分发到指定的路由,经过Model层的数据存取,最终将数据渲染到指定模板文件,并最终呈现到页面中,由视图和模板组成
Controller控制模块
将用户提交的request分发给View模块的视图函数

MTV

    0
Model数据模型
数据存取层,定义系统的数据表结构、数据的存取,通过View模块联接
View视图模块
业务逻辑层,包括数据模型的存取及调用适当的模板文件的相关逻辑,类型于模型与模板之间的桥梁
Template模板文件
表现层,渲染View层的数据并最终呈现在页面中

运行流程

说明:由于Django的URLConf自动完成,因此C层被弱化,而T层被单独抽出
如上图:
1.用户通过web浏览器向apache服务器发起请求;
2.apache服务器将请求转发给urls模块;
3.urls.py至上而下匹配路由配置,匹配成功后,将请求交给视图模块views对应的视图函数处理;
4.视图函数接收到请求后,将相应的数据请求交给models数据模型;
5.models通过ORM操作数据库;
6.数据库操作完成后,将结果返回给models;
7.models将数据结果返回给views视图函数;
8.views视图函数将数据结果,并通过指定的模板文件进行渲染;
9.将渲染后的模板文件最终呈现给web浏览器

URLconf

  Django通过URLconf模块来维护网址的解析与views视图函数的对应关系。

常用方法:(django.urls模块)

方法
说明
示例
path
指定的地址为确定的地址,不支持正则匹配
path("", views.index)
re_path
指定的地址为不确定的地址,支持正则匹配
re_path("user/(?P\d+)", views.user)
include
 
path("api/", include("allauth.urls"))
reverse
反向生成URL地址,其参数为urls.py中视图函数对应的name参数
reverse('add')
说明:当re_path中使用的正则表达式如(?P<tid>\d+)时,视图函数的参数名必须指定为tid

参数说明

  • name:类似于网址的别名,可用于templates、models、views中得到对应的网址,只要这个名字不变,即使网址发生了变化,也能通过这个名字找到正确的网址;

在模板文件中的应用

View Code
View Code
如果网址发生变化但网址别名未发生变化时,通过别名可正确识别变化后的网址,如将新的路由配置修改为如下
View Code
View Code

在视图函数中的应用

View Code
  • include:路由转发,用于从根路由出发,将app所属url请求转发到子urls.py中,path/re_path中使用;

方法一:只指定urls模块的字符串

View Code

方法二:同时指定urls(模块字符串、app_name)、命名空间(当存在多个app时,指定namespace很有必要)

View Code

api/urls.py

View Code

mblog/urls.py

View Code

在template中使用命名空间

View Code

在views中使用命令空间

View Code
注意:namespace与name在模板文件和视图函数中使用的时候要用冒号分隔,如:"api:host"

Template

配置

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',    # 默认模板引擎
        'DIRS': [],  # 默认为app目录下的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',
            ],
        },
    },
]
View Code
  • BACKEND:模板引擎,可使用指定的模板引擎,如django.template.backends.jinja2.Jinga2
  • DIRS:模板文件目录,默认为app目录下的templates目录,可指定特定的目录,常用方式[os.path.join(BASE_DIR, "templates")]

View中的使用

到底使用哪个模板进行渲染,由views.py的视图函数决定

from django.shortcuts import render

# Create your views here.
def index(request):
    return render(request, "index.html")
View Code
    0
render(request, "index.html", {"username": username})
第一个参数为request,第二个参数为模板文件,第三个为可选参数,接收一个dict类型,在index.html模板文件中需要使用的变量,可通过这个dict参数传入
说明:第三个参数可利用python的locals()函数替换

使用现有模板框架(此处以bootstrap3为例)

目前接触到使用bootstrap3的方法有两种,分别是静态引用和动态加载

  • 静态引用

1.安装bootstrap3

pip install django-bootstrap3

2.在settings.py的INSTALLED_APPS中添加bootstrap3应用

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'myapp',
    'bootstrap3',
]
View Code

3.在模板文件中引用bootstrap3

<head>
    <meta charset="UTF-8">
    {% load bootstrap3 %}
    {% bootstrap_css %}
    {% bootstrap_javascript %}
    <title>MySite</title>
</head>
View Code
  • 动态加载

      直接通过bootstrap官网,找到CDN并复制到<head></head>标签中

# 在https://getbootstrap.com/docs/3.4/getting-started/#download网址中,找到BootstrapCDN,
# 将其复制到模板文件的<head></head>标签中即可
# jQuery框架同样可以采用此种方式加载

<head>
    <meta charset="UTF-8">
    <title>MySite</title>
    <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"
          integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu"
          crossorigin="anonymous">

    <!-- 可选的 Bootstrap 主题文件(一般不用引入) -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap-theme.min.css"
          integrity="sha384-6pzBo3FDv/PJ8r2KRkGHifhEocL+1X2rVCTTkUfGk7/0pbek5mMa1upzvWbrUbOZ"
          crossorigin="anonymous">
    <script src="https://code.jquery.com/jquery-3.6.0.js"
            integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous">
    </script>
    <!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"
            integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd"
            crossorigin="anonymous">
    </script>
</head>
View Code

支持的语法

{%%}{{}}

{% if exp %}
条件控制语法,语法同python,使用{% endif %}结束条件控制,可配合{% else %}、{% elif %}使用形成分支结构
{% if username %}

登出

{% else %}

登录

{% endif %}
{% for %}
循环控制语法,语法同python,使用{% endfor %}结束循环控制
 
{% for user in usersusers %}

{{ user.name }}

{% endfor %}
 
可配合{% empty %}显示特定内容,内部变量:forloop
注意:内部变量forloop只在{% for %}循环内生效,当检测到{% endfor %}时,forloop即失效不可用
 
{% for user in usersusers %}

{{ user.name }}

{% empty %}

There are no athletes. Only computer programmers.

{% endfor %}
 
forloop.counter:表示循环次数,从1开始开始计数
{% for user in users %}

{{ forloop.counter }}: {{ user }}

{% endfor %}
forloop.counter0:也表示循环次数,但是从0开始计数
{% for user in users %}

{{ forloop.counter0 }}: {{ user }}

{% endfor %}
forloop.revcounter:循环中剩余元素数量,初始值为元素总数,最后一次为1
 
forloop.revcounter0:也是循环剩余元素数量,不过初始值为元素总数-1,最后一次为0
 
forloop.first:Bool类型,第一次循环时返回True,否则返回False
{% for object in objects %}
{% if forloop.first %}
 
{% else %}
 
{% endif %}
{{ object }}
 
{% endfor %}
forloop.last:Bool类型,最后一次循环时返回True,否则返回False
 
{% extends %}
html继承语法,base.html为html模板文件,类比于Python的基类
{% extends "base.html" %}
{% include %}
html引用语法,将其他html模板文件导入到该html文件中,一般用于网页的页眉、页脚
{% include "header.html" %}
{% include "footer.html" %}
{% load %}
html加载静态文件/框架
{% load bootstrap3 %}
{% load static %}
{% block %}
用于继承及实现;在base.html模板文件中定义了{% block %}{% endblock %}之后,所有继承base.html文件的模板文件都必须实现{% block %}{% endblock %}修饰的内容
base.html
{% block title %}{% endblock %}
index.html
{% extends "base.html" %}
{% block title %}MySite{% endblock %}

使用静态文件

Django中,使用静态文件的方式,可以一度程序上提高性能。而Django的静态文件默认存储在templates/static中

settings.py中的默认配置

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

STATIC_URL = '/static/'
View Code
当然,我们同样可以通过在settings.py中配置的方式来指定静态文件的存放位置
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.2/howto/static-files/

STATIC_URL = '/static/'
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, "static"),
]
View Code
当配置为上述路径后,静态文件的目录路径则变更为与app同级目录的static目录,对于images、css、js则分别创建相应的目录即可
而在template模板文件中使用静态文件时,则按照如下方式即可正常引用静态文件了
<hr>
{% load static %}    # 加载静态文件
<img src="{% static 'images/logo.png' %}" width=100>
<em>Copyright 2016 a
    <a href="http://www.baidu.com">http://www.baidu.com</a>.
    All rights reserved.
</em>
View Code

常用过滤器

过滤器名称
用法
示例
capfirst
将字符串首字母大写
{{ msg | capfirst }},如果msg内容为"django",则html中显示将变成"Django"
center/ljust/rjust
为字符串加上指定空格后居中、靠左、靠右对齐
{{ msg | center: "15" }}
cut
在字符串中删除指定的子字符串
{{ msg | cut: " " }},如果msg内容为" How are you",则html中显示将变成"Howareyou"
date
设置日期的显示格式
{{ value | date:"D d M Y" }},value为datetime的标准格式。可利用date来设置显示格式
default
如果没有值,就使用默认值
{{ msg | default:"没有信息" }}
first/last
只取出列表数据中的第一个/最后一个元素
{{ values | first }} {{ values | last }},values为列表元素
floatformat
以指定的浮点数格式显示数据
{{ value | floatformat:3 }},如果value为123.45678,则html中显示将变成123.457
linebreaks
将文字内容中的换行符号转换成HTML的

 

{{ msg | linebreaks }}
linebreadsbr
将文字内容中的换行符号转换成HTML的
{{ msg | linebreaksbr }}
linenumber
为显示的文字内容加上行号
{{ msg | linenumber}}
lower/upper
将显示的文字内容转换成小写/大写
{{ msg | lower }} {{ msg | upper }}
random
以随机数将数据内容显示出来
{{ values | random }}
safe
标记字符串为安全的,不需要再处理转义字符
{{ msg | safe }}
striptags
去掉文字内容中的所有HTML标签
{{ msg | striptags }}
truncatechars
把过长的字符串裁切成指定的长度,并将最后3个字符转换成...
{{ msg | truncatchars:12 }}
yesno
按照值的内容True/False/None,显示出有意义的内容
{{ value | yesno:"是,否,可能吧" }}

Models

  Django中,models负责定义数据模型,通过views中的视图函数与Django Models机制的交互,调用相应的驱动程序接口,实现对数据的存取

配置

在默认配置中,Django以SQLite作为数据库管理系统,当然也可以使用其他的数据库管理系统
# Database
# https://docs.djangoproject.com/en/3.2/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}
View Code
配置链接 mySQL 数据库
# mysql
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',  # 数据库驱动
        'NAME': 'event',  # 数据库名称(需要先创建)
        'USER': 'root',  # 数据库用户名
        'PASSWORD': '123456',  # 数据库密码
        'HOST': '',  # 数据库主机,留空默认为localhost
        'PORT': '3306',  # 数据库端口
    }
}
View Code
配置链接PostgreSQL 数据库
# postgresql
DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.postgresql_psycopg2",
        "NAME": "event",
        "USER": "postgres",
        "PASSWORD": "123456",
        "HOST": "localhost",
        "PORT": "5432",
    }
}
View Code

定义模型类

Django提供了完善的模型(model)层来创建和存取数据,它包含你所存储的数据的必要字段和行为以及类型;
  • 每一个模型都是一个python类,并且继承自django.db.models.Model类
  • 该模型的每个属性都表示一个数据库表的字段
  • 每个模型自动生成一个auto_increment的id字段,并作为主键
  • 内部类Meta:用于指定一些特殊属性,如ordering(排序规则)、unique_together(联合外键)  
示例:
from django.db import models

class Poll(models.Model):

    name = models.CharField(max_length=200, null=False)
    create_at = models.DateField(auto_now_add=True)
    enabled = models.BooleanField(default=False)
    
    class Meta:
        ordering = ("-create_at",)     # 定义结果的排序规则,此处按照创建时间进行排序,"-"表示按照倒序排序

    def __str__(self):
        return self.name

class PollItem(models.Model):

    poll = models.ForeignKey(Poll, on_delete=models.CASCADE)  # 指定PollItem表的外键为Poll
    name = models.CharField(max_length=200, null=False)
    image_url = models.CharField(max_length=200, null=True, blank=True)
    vote = models.PositiveIntegerField(default=0)

    def __str__(self):
        return self.name
 
View Code

使用admin后台管理数据模型

Django提供了admin后台管理,对于自定义的数据模型,只需要将数据模型注册到admin后台管理中就可以了
而注册admin后台管理也非常简单,在admin.py中引入数据模型,并调用admin.site.register()方法就可以了
from django.contrib import admin
from mysite.models import Poll


admin.site.register(Poll)
View Code
为了在admin后台管理中能显示更多的字段,可利用django.contrib.admin.ModelAdmin派生出新的类,并在新的类中对想要的属性进行调整
from django.contrib import admin
from mysite.models import Poll, PollItem


class PollAdmin(admin.ModelAdmin):

    list_display = ("name", "create_at", "enabled")
    ordering = ("-create_at",)


class PollItemAdmin(admin.ModelAdmin):

    list_display = ("poll", "name", "vote", "image_url")
    ordering = ("poll", )


admin.site.register(Poll, PollAdmin)
admin.site.register(PollItem, PollItemAdmin)
View Code
django.contrib.admin.ModelAdmin中提供了很多定制化的属性
  • list_display:可迭代对象,其中每个对象对应数据模型中定义的属性,如:list_display = ("name", "create_at", "enabled")
  • search_fields:搜索器,可迭代对象,同上,如:search_fields = ("name", "poll")
  • ordering:同上,如:ordering = ("-create_at")
  • list_filter:过滤器,可迭代对象,如:list_filter = ("enabled")

常用Model属性类型

admin.Model提供的常用属性

AutoField
一个IntegerField类型的自增字段类型
BooleanField
用于存入布尔类型的数据(True/False)
CharField
用于存放字符型的数据,需要指定数据长度,max_length
DateField
日期类型,必须是"YYYY-MM-DD"格式
DateTimeField
日期时间类型,必须是"YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]"
DecimalField
定点数类型,max_digits指定最大值,decimal_places指定小数位数
EmailField
电子邮件类型
FilePathField
文件路径类型
FloatField
浮点数类型
IntegerField
integer类型,数值范围从-2147483648g到2147483647
BigIntegerField
用于存放大的integer类型
GenericIPAddressField
存放IP地址类型,支持IPv4和IPv6的字符串格式
NullBooleanField
类似BooleanField类型,但允许为NULL
PositiveIntegerField
integer类型,范围0~2147483647
TextField
用于存放文本类型的数据
TimeField
时间类型,必须是"HH:MM[:ss[.uuuuuu]]"格式
URLField
用于存放URL地址
BinaryField
存储原始二进制数据的字段
注意:在models数据模型定义中,属性中加上verbose_name可定义属性的中文名

在models.ForeignKey(Poll, on_delete=models.CASCADE)中on_delete参数,支持五种操作:

  • on_delete=models.CASCADE:删除被引用的对象时,此对象也一并被删除
# models.py
from django.db import models

class AClass(models.Model):
    name = models.CharField(max_length=40)

    def __str__(self):
        return self.name

class AListClass(models.Model):
    a_name = models.ForeignKey(AClass, on_delete=models.CASCADE)
    name = models.CharField(max_length=40)

    def __str__(self):
        return self.name
        
# admin.py
from django.contrib import admin
from mysite.models import AClass, AListClass

class AListClassAdmin(admin.ModelAdmin):
    list_display = ("name", "a_name")    # AListClass表显示name字段及外键AClass的name字段

admin.site.register(AClass)
admin.site.register(AListClass, AListClassAdmin)
View Code
AClass表添加A1、A2实例,同时AListClass添加a1、a11两个实例关联A1,a2、a22两个实例关联实例A2
0
当删除AClass表的A1实例时,会将AListClass表中相关联的a1、a11实例都删除
0
确认删除后,查看AListClass表中,已不存在a1、a11的数据
0
  • on_delete=models.PROTECT:禁止删除并抛出异常ProtectdError
# models.py
from django.db import models

class BClass(models.Model):
    name = models.CharField(max_length=40)

    def __str__(self):
        return self.name

class BListClass(models.Model):
    b_name = models.ForeignKey(BClass, on_delete=models.PROTECT)
    name = models.CharField(max_length=40)

    def __str__(self):
        return self.name

# admin.py
from django.contrib import admin
from mysite.models import BClass, BListClass

class BListClassAdmin(admin.ModelAdmin):
    list_display = ("name", "b_name")

admin.site.register(BClass)
admin.site.register(BListClass, BListClassAdmin)
View Code
BClass表添加B1、B2实例,同时BListClass添加b1、b11两个实例关联B1,b2、b22两个实例关联实例B2
0
当删除BClass表的B1实例时,会提示"Cannot delete b class",并提示需要先删除依赖实例B1的实例才能删除B1实例
0
删除BListClass表的b1、b11这两个依赖B1的实例
0
再次尝试去删除BClass表的B1实例,这次就能正常删除B1实例了
0
  • on_delete=models.SET_NULL:当被引用的对象被删除后,依赖它的其他对象的该字段都被设置为NULL;设置此操作时,字段必须设置null=True来允许字段值为NULL
# models.py
from django.db import models

class CClass(models.Model):
    name = models.CharField(max_length=40)

    def __str__(self):
        return self.name

class CListClass(models.Model):
    c_name = models.ForeignKey(CClass, on_delete=models.SET_NULL, null=True)  # 必须指定null=True允许字段值为空
    name = models.CharField(max_length=40)

    def __str__(self):
        return self.name

# admin.py
from django.contrib import admin
from mysite.models import CClass, CListClass

class CListClassAdmin(admin.ModelAdmin):
    list_display = ("name", "c_name")

admin.site.register(CClass)
admin.site.register(CListClass, CListClassAdmin)
View Code
CClass表创建C1、C2实例,CListClass表添加c1、c11两个实例关联实例C1,c2、c22两个实例关联实例C2
0
当删除CClass的C1实例时,与它相关联的CListClass表的c1、c11实例的c_name字段会被设置为NULL
0
  • on_delete=models.SET_DEFAULT:当被引用的对象被删除后,依赖它的其他对象的该字段都被设置为默认值;设置此操作时,字段必须设置default参数
# models.py
from django.db import models

class DClass(models.Model):
    name = models.CharField(max_length=40)

    def __str__(self):
        return self.name

class DListClass(models.Model):
    d_name = models.ForeignKey(DClass, on_delete=models.SET_DEFAULT, default=None, null=True)
    name = models.CharField(max_length=40)

    def __str__(self):
        return self.name
        
# admin.py
from django.contrib import admin
from mysite.models import DClass, DListClass

class DListClassAdmin(admin.ModelAdmin):
    list_display = ("name", "d_name")

admin.site.register(DClass)
admin.site.register(DListClass, DListClassAdmin)
View Code
DClass表创建D1、D2实例,DListClass表创建d1、d11两个实例关联D1实例,创建d2、d22两个实例关联D2实例
0
当删除DClass的D1实例时,与它相关联的DListClass表的d1、d11实例的d_name字段会被设置为默认值,此处为NULL
0
 
  • on_delete=models.DO_NOTHING:什么事儿都不做?如果你的数据库后端强制引用完整性,它将引发一个IntegrityError ,除非你手动添加一个ON DELETE 约束给数据库

 

posted @ 2021-07-14 11:16  Maserati~  阅读(643)  评论(0编辑  收藏  举报