Django学习之初识

================================

参考

https://www.cnblogs.com/wupeiqi

https://www.bilibili.com/video/BV1NL41157ph?p=1

安装 django

1
pip  install django
1
2
3
4
5
6
$ /home/conda/bin/conda env list  
# conda environments:
#
base * /home/conda
django /home/conda/envs/django

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ source /home/conda/bin/activate django 

(django) $ pip list
Package Version
----------------- ---------
asgiref 3.4.1
certifi 2021.10.8
cffi 1.15.0
cryptography 36.0.0
Django 3.2.7
mysqlclient 2.0.3
pip 21.2.2
pycparser 2.21
PyMySQL 1.0.2
pytz 2021.3
setuptools 58.0.4
sqlparse 0.4.2
typing_extensions 4.0.1
wheel 0.37.0
(django) $
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

(django) $ pip3 list
Package Version
----------------- ---------
asgiref 3.4.1
certifi 2021.10.8
cffi 1.15.0
cryptography 36.0.0
Django 3.2.7
mysqlclient 2.0.3
pip 21.2.2
pycparser 2.21
PyMySQL 1.0.2
pytz 2021.3
setuptools 58.0.4
sqlparse 0.4.2
typing_extensions 4.0.1
wheel 0.37.0

创建django项目

django-admin

使用 django-admin 命令创建项目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

(django) $ django-admin --help

Type 'django-admin help <subcommand>' for help on a specific subcommand.

Available subcommands:

[django]
check
compilemessages
createcachetable
dbshell
diffsettings
dumpdata
flush
inspectdb
loaddata
makemessages
makemigrations
migrate
runserver
sendtestemail
shell
showmigrations
sqlflush
sqlmigrate
sqlsequencereset
squashmigrations
startapp
startproject
test
testserver
Note that only Django core commands are listed as settings are not properly configured (error: Requested setting INSTALLED_APPS, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.).
(django) $

django-admin startproject

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

(django) $ django-admin startproject --help
usage: django-admin startproject [-h] [--template TEMPLATE]
[--extension EXTENSIONS] [--name FILES]
[--version] [-v {0,1,2,3}]
[--settings SETTINGS]
[--pythonpath PYTHONPATH] [--traceback]
[--no-color] [--force-color]
name [directory]

Creates a Django project directory structure for the given project name in the
current directory or optionally in the given directory.

positional arguments:
name Name of the application or project.
directory Optional destination directory

optional arguments:
-h, --help show this help message and exit
--template TEMPLATE The path or URL to load the template from.
--extension EXTENSIONS, -e EXTENSIONS
The file extension(s) to render (default: "py").
Separate multiple extensions with commas, or use -e
multiple times.
--name FILES, -n FILES
The file name(s) to render. Separate multiple file
names with commas, or use -n multiple times.
--version show program's version number and exit
-v {0,1,2,3}, --verbosity {0,1,2,3}
Verbosity level; 0=minimal output, 1=normal output,
2=verbose output, 3=very verbose output
--settings SETTINGS The Python path to a settings module, e.g.
"myproject.settings.main". If this isn't provided, the
DJANGO_SETTINGS_MODULE environment variable will be
used.
--pythonpath PYTHONPATH
A directory to add to the Python path, e.g.
"/home/djangoprojects/myproject".
--traceback Raise on CommandError exceptions
--no-color Don't colorize the command output.
--force-color Force colorization of the command output.

创建一个项目swprojmgr

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
(django) $ django-admin startproject swprojmgr # 执行命令创建一个项目,项目名是swprojmgr

(django) $ tree
.
└── swprojmgr
├── manage.py 很重要,项目管理脚本,创建app,启动项目等使用,不需要修改
└── swprojmgr # 和项目同名的一个目录,
├── asgi.py
├── __init__.py
├── settings.py # 项目的配置文件,例如配置数据库,注册app等。
├── urls.py # url 和 python 函数对应,一一对应
└── wsgi.py # 接收网络请求的,内部使用的,不需要动

2 directories, 6 files

django-admin startapp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
(django) $ django-admin startapp --help 
usage: django-admin startapp [-h] [--template TEMPLATE]
[--extension EXTENSIONS] [--name FILES]
[--version] [-v {0,1,2,3}] [--settings SETTINGS]
[--pythonpath PYTHONPATH] [--traceback]
[--no-color] [--force-color]
name [directory]

Creates a Django app directory structure for the given app name in the current
directory or optionally in the given directory.

positional arguments:
name Name of the application or project.
directory Optional destination directory

optional arguments:
-h, --help show this help message and exit
--template TEMPLATE The path or URL to load the template from.
--extension EXTENSIONS, -e EXTENSIONS
The file extension(s) to render (default: "py").
Separate multiple extensions with commas, or use -e
multiple times.
--name FILES, -n FILES
The file name(s) to render. Separate multiple file
names with commas, or use -n multiple times.
--version show program's version number and exit
-v {0,1,2,3}, --verbosity {0,1,2,3}
Verbosity level; 0=minimal output, 1=normal output,
2=verbose output, 3=very verbose output
--settings SETTINGS The Python path to a settings module, e.g.
"myproject.settings.main". If this isn't provided, the
DJANGO_SETTINGS_MODULE environment variable will be
used.
--pythonpath PYTHONPATH
A directory to add to the Python path, e.g.
"/home/djangoprojects/myproject".
--traceback Raise on CommandError exceptions
--no-color Don't colorize the command output.
--force-color Force colorization of the command output.
(django) $

创建app

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
(django) $ django-admin startapp myapp01  # 创建一个 myapp01


(django) $ tree
.
├── manage.py
├── myapp01
│ ├── admin.py 固定不用动 默认提供了admin后台管理
│ ├── apps.py 固定不用动
│ ├── __init__.py
│ ├── migrations # 固定不用动 数据库变更记录,每次执行 python manage.py makemigrations 命令,这个目录下面会生成个新的文件,很类似 git 提交 历史那样
│ │ └── __init__.py
│ ├── models.py # 数据库
│ ├── tests.py # 单元测试用的
│ └── views.py # 视图, 函数,之前那个 urls.py 就和 这里的函数对应,路由映射
└── swprojmgr
├── asgi.py
├── __init__.py
├── __pycache__
│ ├── __init__.cpython-37.pyc
│ └── settings.cpython-37.pyc
├── settings.py
├── urls.py
└── wsgi.py


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
$ tree  
.
├── api 这是我们新建的 app
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py
│   ├── tests.py
│   └── views.py
├── autoserver 这是我们新建的 project
│   ├── asgi.py
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-37.pyc
│   │   └── settings.cpython-37.pyc
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── manage.py
└── web 这是我们新建的 app
├── admin.py
├── apps.py
├── __init__.py
├── migrations
│   └── __init__.py
├── models.py
├── tests.py
└── views.py

6 directories, 22 files

注册app

在 settings.py 文件中 INSTALLED_APPS 添加注册

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15


INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',

'myapp01.apps.Myapp01Config'

]


编写url和函数映射

路由url

在 urls.py 文件中

1
2
3
4
5
6
7
8
9
from myapp01  import views  # 需要导入

urlpatterns = [
path('index/', views.index), # 只要用户 访问 index/ 这个地址,就会执行 views.index 函数
]


浏览器 访问 http://127.0.0.1:8000/index/ 这样 就会 执行 views.index

编写视图函数

在 views.py 文件中

1
2
3
4
5
6
7

from django.shortcuts import render, HTTPResponse

# Create your views here.
def index(req):
return HTTPResponse("welcome to my django website!!!")

启动django项目

1
2
3
python manage.py runserver


模板文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [], # setting.py 文件这里没有配置,就会在app下面找,如果这里配置了,就优先在这里查找模板文件
'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',
],
},
},
]

views.py 文件添加个新的函数

1
2
3
4
5
6

def user_list(req):
return render(req, "user_list.html")



urls.py 文件加个新的映射

1
2
3
4
5
6
7
8
9


from myapp01 import views

urlpatterns = [
path('index/', views.index),
path('user_list/', views.user_list),
]

模板语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

def tpl(req):
roles = ["管理员", "ceo", 'CTO']
param_D = {
"n1": roles,

}
return render(req, "tpl.html", param_D)

通过 render 渲染,可以传过去一共 字典参数,


在 模板的html文件中 可以使用,类似 插值语法
<h1>{{ n1 }}</h1>
这样可以直接用 传过去的 字典 中 n1 键对应的 那个变量,这样直接显示 出来是列表


<h3>{{ n1.0 }}</h3>
<h3>{{ n1.1 }}</h3>
<h3>{{ n1.2 }}</h3>
这样来访问 列表中每一个元素的值。



<h1>{{ n2 }}</h1>
这样可以直接用 传过去的 字典 中 n2 键对应的 那个变量,这样直接显示 出来是字典

<h1>{{ n2.name }}</h1>
<h1>{{ n2.age }}</h1>
这样来访问字典中的每个键对应的值


{% if latest_question_list %}
<ul>
{% for question in latest_question_list %}
<li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>
{% endfor %}
</ul>
{% else %}
<p>No polls are available.</p>
{% endif %}

静态文件

开发过程中,图片,css,js 文件都是 静态文件,static 文件。
要在app 下面搞一个 static 目录。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
最后的目录结构是这样的
│   ├── static
│   │   ├── css
│   │   ├── img
│   │   └── js
│   ├── templates
│   │   └── user_list.html


Make sure that django.contrib.staticfiles is included in your INSTALLED_APPS.

In your settings file, define STATIC_URL, for example:
STATIC_URL = '/static/'

In your templates, use the static template tag to build the URL for the given relative path using the configured STATICFILES_STORAGE.
{% load static %}



<!DOCTYPE html>

{% load static %}

<html lang="zh-CN">
<head>
<title>火狐主页</title>
<meta name="keywords" content="火狐主页,网址导航,网址大全,火狐浏览器,火狐官方社区,Firefox,Mozilla Firefox,Mozilla">
<meta name="description" content="火狐主页为您提供最新最全的搜索、网址导航、新闻资讯、网络购物等服务。">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="shortcut icon" href="{% static 'favicon.ico' %}" type="image/x-icon">
<link rel="stylesheet" href="{% static 'css/app.css' %}">
<link rel="stylesheet" href="{% static 'css/default.css' %}">
<script src="{% static 'js/app.js' %}" defer></script>
<base target="_blank">
</head>



http://127.0.0.1:8000/static/favicon.ico

http://127.0.0.1:8000/static/css/app.css 直接这样访问 就能访问到 static 下面的 路径文件了


数据库

修改 models.py 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

from django.db import models

# Create your models here.

class UserInfo(models.Model): # 这个就会和数据库中的表对应上
name = models.CharField(max_length=30)
passwrod = models.CharField(max_length=16)
age = models.IntegerField()

django定义了好几种 xxxxField。当然有额可以自己继承一个Field类自己定义一个

class PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField[_ST, _GT]): ...
class PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, SmallIntegerField[_ST, _GT]): ...
class PositiveBigIntegerField(PositiveIntegerRelDbTypeMixin, BigIntegerField[_ST, _GT]): ...
class SmallIntegerField(IntegerField[_ST, _GT]): ...
class BigIntegerField(IntegerField[_ST, _GT]): ...

class FloatField(Field[_ST, _GT]):
class DecimalField(Field[_ST, _GT]):

class CharField(Field[_ST, _GT]):
class CommaSeparatedIntegerField(CharField[_ST, _GT]): ...
class SlugField(CharField[_ST, _GT]):
class EmailField(CharField[_ST, _GT]): ...
class URLField(CharField[_ST, _GT]):
class TextField(Field[_ST, _GT]):
class BooleanField(Field[_ST, _GT]):
class NullBooleanField(BooleanField[_ST, _GT]):
class IPAddressField(Field[_ST, _GT]):
class GenericIPAddressField(Field[_ST, _GT]):
class DateField(DateTimeCheckMixin, Field[_ST, _GT]):
class TimeField(DateTimeCheckMixin, Field[_ST, _GT]):
class DateTimeField(DateField[_ST, _GT]):
class UUIDField(Field[_ST, _GT]):
class FilePathField(Field[_ST, _GT]):
class BinaryField(Field[_ST, _GT]):
class DurationField(Field[_ST, _GT]):
class AutoField(AutoFieldMixin, IntegerField[_ST, _GT], metaclass=AutoFieldMeta):
class BigAutoField(AutoFieldMixin, BigIntegerField[_ST, _GT]): ...
class SmallAutoField(AutoFieldMixin, SmallIntegerField[_ST, _GT]): ...


数据库表格 和 一个 类 要想映射上,
数据库的列名称,对应 类 里面的一个一个属性名称, 列名 对应 属性名,这是默认行为,如果属性名 不想和列名一模一样,可以使用 Field.db_column¶ 单独设置
数据库的列的类型,对应 类 里面 属性的类型,属性的类型 封装成 Field 类型 的 子类了。
数据库的每一行 对应 类 的一个实例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

(django) $ python manage.py makemigrations 先执行这个命令
Migrations for 'myapp01':
myapp01/migrations/0001_initial.py
- Create model UserInfo

(django) $ python manage.py migrate 再执行这个命令
Operations to perform:
Apply all migrations: admin, auth, contenttypes, myapp01, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying auth.0012_alter_user_first_name_max_length... OK
Applying myapp01.0001_initial... OK
Applying sessions.0001_initial... OK


最后会创建一个 表 myapp01_userinfo
# 名字 类型 排序规则 属性 空 默认 注释 额外
1 id 主键 bigint(20) 否 无 AUTO_INCREMENT
2 name varchar(30) utf8mb4_bin 否 无
3 passwrod varchar(16) utf8mb4_bin 否 无
4 age int(11) 否 无


当然 django 连带着创建了好几个其他表。
auth_group
auth_group_permissions
auth_permission
auth_user
auth_user_groups
auth_user_user_permissions
django_admin_log
django_content_type
django_migrations
django_session

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

class UserInfo(models.Model):
name = models.CharField(max_length=30)
passwrod = models.CharField(max_length=16)
age = models.IntegerField()

class OtherInfo(models.Model):
char = models.CharField(max_length=300)
slug =models.SlugField()
email =models.EmailField()
url =models.URLField()
text =models.TextField()
boolean =models.BooleanField()
null =models.BooleanField(null=True)
generic_ip =models.GenericIPAddressField()
date =models.DateField()
time =models.TimeField()
date_time =models.DateTimeField()
uuid =models.UUIDField()
file_path=models.FilePathField()
binary =models.BinaryField()
duration =models.DurationField()


Field Type Null Key Default Extra
id bigint(20) NO PRI NULL auto_increment
char varchar(300) NO NULL
slug varchar(50) NO MUL NULL
email varchar(254) NO NULL
url varchar(200) NO NULL
text longtext NO NULL
boolean tinyint(1) NO NULL
null tinyint(1) YES NULL
generic_ip char(39) NO NULL
date date NO NULL
time time(6) NO NULL
date_time datetime(6) NO NULL
uuid char(32) NO NULL
file_path varchar(100) NO NULL
binary longblob NO NULL
duration bigint(20) NO NULL

如果
duration =models.DurationField(db_column="my_col_duration")
数据库表的列名就会对应成下面这个样子
my_col_duration bigint(20) NO NULL

class AutoInfo1(models.Model):
auto = models.AutoField( primary_key=True)
Field Type Null Key Default Extra
auto int(11) NO PRI NULL auto_increment

默认的django 添加的那个住建就是 BigAutoField 类型的。 在 apps.py 文件中 有配置 default_auto_field = 'django.db.models.BigAutoField'
class AutoInfo2(models.Model):
big_auto =models.BigAutoField( primary_key=True)
Field Type Null Key Default Extra
big_auto bigint(20) NO PRI NULL auto_increment


class AutoInfo3(models.Model):
small_auto =models.SmallAutoField( primary_key=True)
Field Type Null Key Default Extra
small_auto smallint(6) NO PRI NULL auto_increment

数据库表增删改查

新建一行数据,那就是 调用 对应 model 类对象,然后 create 一个实例就可以了

1
2
3
4
5
6
7
8
9
10
11

class UserInfo(models.Model):
name = models.CharField(max_length=30)
password = models.CharField(max_length=16)
age = models.IntegerField()


UserInfo.objects.create(name="ailala", password="123", age="27")
UserInfo.objects.create(name="annie", password="abc", age="17")


删除

1
2
3
4
5
6
7
8
9
10
11
12
13
14
obj = UserInfo.objects.filter(id=4)  # 这里直接在 models.py 文件里面进行测试了,这个要写在 类外部,相当于 文件的第一层代码结构的地方。
print(obj[0].name, obj[0].password, obj[0].age)
obj.delete()
上面删除的代码就不能写在 models.py 里面了,不然会报下面的错误
django.core.exceptions.AppRegistryNotReady: Models aren't loaded yet.

把删除 代码 放到 views.py 里面,单独搞个函数,弄一个 url映射一下,从浏览器访问一下这个url,然后调用这个函数。
def orm(req):
UserInfo.objects.filter(id=4).delete() # 这里 可以理解为 先 过滤出来 id = 4的然后进行删除,其实就是按条件 删除
return HttpResponse("welcome to my django website!!!")


UserInfo.objects.all().delete() # 删除所有

更新

1
2
3
4
5
6
7
8
9
10
11


def orm(req):
# UserInfo.objects.all().update(password="sdfsdfs") # 把所有行数据的 password都更改了。。。。。


UserInfo.objects.filter(id=7).update(password="33333333333")

return HttpResponse("welcome to my django website!!!")


查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class UserInfo(models.Model):
name = models.CharField(max_length=30)
password = models.CharField(max_length=16)
age = models.IntegerField()


# UserInfo.objects.create(name="ailala", password="123", age="27")
# UserInfo.objects.create(name="annie", password="abc", age="17")

obj = UserInfo.objects.filter(id=4) # 这里直接在 models.py 文件里面进行测试了,这个要写在 类外部,相当于 文件的第一层代码结构的地方。
print(obj)


(django) $ python manage.py makemigrations # 命令行执行 这个会打印出来查询的数据库内容的。
<QuerySet [<UserInfo: UserInfo object (4)>]>
No changes detected

obj = UserInfo.objects.filter(id=4)
print(obj[0].name, obj[0].password, obj[0].age)

(django) $ python manage.py makemigrations # 命令行执行 这个会打印出来查询的数据库内容的。
annie abc 17