Django

1.准备

首先在当前pycharm终端运行pip install django,然后在我们想创建的目录下运行django-admin startproject 文件名 就会在当前目录下创建这个文件夹,然后进入并运行python manage.py runserver,访问地址就好了

1771659111386

项目的文件介绍

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
> tree /f
C:.
│ db.sqlite3
│ manage.py

└─my_django
│ asgi.py #不动
│ settings.py 要
│ urls.py 要,url调用->函数
│ wsgi.py #不动
│ __init__.py#不动

└─__pycache__ #不管他
settings.cpython-314.pyc
urls.cpython-314.pyc
wsgi.cpython-314.pyc
__init__.cpython-314.pyc

我们上面运行了django-admin后会生成三个部分manage.py,db.sqlite3,my_django,前两个都是默认的目前不用管,my_django是与所生成的django文件名一致的文件夹,其中asgi.py和wsgi.py都是网络请求部分,不要动,我们主要编辑的部分是settings.pyurls.py

app的创建

1
python manage.py startapp app1(这是名字)
1
2
3
4
5
6
7
8
9
10
11
12
> tree /f
C:.
│ admin.py #固定,django提供admin后台管理
│ apps.py #固定,app启动类
│ models.py 堆数据库进行操作
│ tests.py #固定,单元测试
│ views.py 函数部分,url会调用这一部分
│ __init__.py

└─migrations #固定,数据库变更记录
__init__.py

2.快速上手

先写一个简单网页

1.确保app已注册(settings.py)

my_django目录下的settings.py文件的INSTALLED_APPS的类中添加app1.apps.App1Config

1771747894695

1771747940023

2.编写URL和视图函数的关系(urls.py)

1
2
3
4
5
6
from django.contrib import admin
from django.urls import path
from app1 import views #调用app1中的views.py
urlpatterns = [
path('index/', views.index), #意思就是说访问www.xxx.com/index时会调用views文件的index函数
]

3.编写视图函数(views.py)

因为我们第二步不是导入views的index函数,那么接下来就是在views.py中编写index函数

1
2
3
4
5
6
from django.shortcuts import render,HttpResponse
#要借用HttpResponse库

# Create your views here.
def index(request):
return HttpResponse("hello world")

4.启动Django函数

1
python manage.py runserver

1771748939218

templates模板

views.py部分,要注意的是通常情况下程序会根据INSTALLED_APPS的目录下的按顺序寻找每一个app的templates文件中的index.html

1
2
3
4
5
from django.shortcuts import render,HttpResponse

# Create your views here.
def index(request):
return render(request,'index.html')

但是要注意的是有的人的settings文件会有这个内容,DIRS部分,那么每次寻找templates会有优先在根目录中寻找templates文件,然后再寻找app中的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import os
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]

静态文件

图片,css,js都是当作静态文件处理

静态文件只能放在当前app的static文件夹中

1771750368225

然后是引用,我们正常的<img src="/>是可以的,但是Django更推荐这样子写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="{% static 'plungs/bootstrap/bootstrap.css' %}">
</head>
<body>
<h1>欢迎光临</h1>
<script src="{% static 'plungs/js/bootstrap.js' %}"></script>
<script src="{% static 'js/jquery-4.0.0.js' %}"></script>
</body>
</html>

3.模板语法

本质:在HTML中写一些占位符,有数据对其中的占位符进行替换和处理

字符型

1
2
3
4
5
#views.py
def tpl(request):
name="hello"
return render(request,'tpl.html',{"n1":name})

1
2
3
4
<body>
<h1>{{n1}}</h1>
</body>

字符串型

1
2
3
4
def tpl(request):
name=["hello","world"]
return render(request,'tpl.html',{"n1":name})

1
2
3
4
5
6
7
8
<body>
<h1>{{n1}}</h1>
<div>{{n1.0}} {{n1.1}}</div>
{% for it in n1 %}
<span>{{it}}</span>
{% endfor %}
</body>

1771936756671

字典型

1
2
3
4
def tpl(request):
man={"name":"lion","age":18}
return render(request,'tpl.html',{"n1":man})

1
2
3
4
5
6
7
8
9
10
11
12
<body>
<h1>{{n1}}</h1>
<div>{{n1.name}} {{n1.age}}</div>
{% for it in n1.items %}
<span>{{it}}</span>
{% endfor %}
<hr/>
{% for it1,it2 in n1.items %}
<div>{{it1}}={{it2}}</div>
{% endfor %}
</body>

1771937170136

但是大多数遇到的都是字符里面嵌套字典

if型调用

1
2
3
4
5
6
7
8
{% if n1 == "lion" %}
...
{% elif n1 == "XX" %}
...
{% else %}
...
{% endif %}

流程

1771937977903

爬虫

1
2
3
4
5
import requests
res=requests.get("XXX") #get请求
date_list=res.json() #爬取fetch类文件
print(date_list)

4.请求和响应

请求

1
2
3
4
5
6
7
8
def tpl(request):
#1.获取请求数据
print(request.method)
#2.获取数据
print(request.GET)
print(request.POST)
return render(request,'tpl.html')

响应

1
2
3
4
5
6
7
#1.直接将内容发给请求者
return HttpResponse("返回内容")
#2.读取HTML内容+替换->字符串,返回给用户
return render(request,"tpl.html",{"n1":date})
#3.重定向,但是记得要加上redirect库
return redirect("https://www.doubao.com/chat")

关于重定向

案例

账号注册

1
2
3
4
5
6
7
8
9
<body>
<form method="post" action="/login/"> <--还有这个是/login/,不是/login -->
{% csrf_token %} <----> 要记得加上这个,不然过不了</---->
<input type="text" name="user" placeholder="账号">
<input type="password" name="pwd" placeholder="密码">
<input type="submit" value="提交">
</form>
</body>

1
2
3
4
5
6
7
def login(request):
if request.method=="GET":
return render(request,'login.html')
else:
print(request.POST)
return HttpResponse("注册成功")

账号登陆

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def login(request):
if request.method=="GET":
return render(request,'login.html')
else:
print(request.POST)
username = request.POST.get("user")
password = request.POST.get("pwd")
print(username,password)
if username=="admin" and password=="root":
return HttpResponse("登录成功")
else:
msg="登陆失败"
return render(request,'login.html',{"msg":msg})

1
2
3
4
5
6
7
8
9
10
<body>
<form method="post" action="/login/">
{% csrf_token %}
<input type="text" name="user" placeholder="账号">
<input type="password" name="pwd" placeholder="密码">
<input type="submit" value="提交">
</form>
<span>{{msg}}</span>
</body>

5.数据库操作

1771943113640

这是我们的sql语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import pymysql
while True:
user=input("Enter your username: ")
pwd=input("Enter your password: ")
phone=input("Enter your phone number: ")
#1.连接mysql的unicom库
conn=pymysql.connect(host='127.0.0.1',port=3306,user='root',passwd='666666',charset='utf8',db='unicom')
cursor=conn.cursor(cursor=pymysql.cursors.DictCursor)
#2.发送指令
sql="insert into admin(username,passward,mobile) values(%s,%s,%s)"
cursor.execute(sql,[user,pwd,phone])
#3.确认指令
conn.commit()
#4.关闭
cursor.close()
conn.close()

但是在Django中更加简单,因为其内部提供了orm框架

所以这一部分我们主要是介绍orm框架对数据库的增删改查

安装模块

1
2
3
#其实这个是等效与pymysql,但是pymysql源码中有个编译错误,所以我们用这个
pip install mysqlclient

ORM优势

1.创建修改删除数据库中的表(但是不能对库进行创建)

2.操作表中的数据

自己创建数据库

1
2
3
4
5
6
7
8
9
10
Microsoft Windows [版本 10.0.26100.7623]
(c) Microsoft Corporation。保留所有权利。
C:\Windows\System32>net start mysql
请求的服务已经启动。
请键入 NET HELPMSG 2182 以获得更多的帮助。
C:\Windows\System32>mysql -u root -p
Enter password: ******
mysql> create database orm DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
Query OK, 1 row affected, 2 warnings (0.01 sec)

Django连接数据库

settings.py中进行修改

找到这个DATABASES部分

1771944270039

替换模板,内容改为自己的

1
2
3
4
5
6
7
8
9
10
11
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', #这个是django可以连接到mysql数据库,也可以连接oracle数据库
'NAME':'orm', #这是我们要连接的数据库名称
'USER': 'root',
'PASSWORD': '666666',
'HOST': '127.0.0.1',
'PORT': '3306',
}
}

基于Django添加表

在models.py操作

这段代码就是创建一个名为app1_userinfo的表,表的元素有name,password,age,并且自带id

1
2
3
4
5
6
7
from django.db import models

class UserInfo(models.Model):
name=models.CharField(max_length=32)
password=models.CharField(max_length=64)
age=models.IntegerField()

然后是执行命令,在项目终端执行

1
2
3
python manage.py makemigrations
python manage.py migrate

1771945204431

但是注意,我们的mysql数据库增加了许多表,那是因为settings.py的Installed_app的表结构有许多个app,程序执行的时候是按照那个目录来的

1771945424063
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
mysql> show tables;
+----------------------------+
| Tables_in_orm |
+----------------------------+
| app1_userinfo |
| 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 |
+----------------------------+
11 rows in set (0.00 sec)

mysql> desc app1_userinfo;
+----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+----------------+
| id | bigint | NO | PRI | NULL | auto_increment |
| name | varchar(32) | NO | | NULL | |
| password | varchar(64) | NO | | NULL | |
| age | int | NO | | NULL | |
+----------+-------------+------+-----+---------+----------------+
4 rows in set (0.01 sec)

mysql>

创建和修改表结构

如果我不想要这个类时,注释掉重新运行终端代码,这个类就消失了,表元素操作也是类似的

但是如果我要在某个生成的表中再次添加一个元素

可以看到此时的age被我删掉了

1
2
3
4
5
6
7
8
9
10
11
12
mysql> desc app1_userinfo;
+----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+----------------+
| id | bigint | NO | PRI | NULL | auto_increment |
| name | varchar(32) | NO | | NULL | |
| password | varchar(64) | NO | | NULL | |
+----------+-------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)

mysql>

然后我再添加age,可以看到终端给了我两个选项,一个是给他已添加数据的部分的age设置成统一的值,一个是退出

1
2
3
4
5
6
7
(.venv) PS C:\Users\shizihang\Desktop\学习\PythonProject1\my_django> python manage.py makemigrations
It is impossible to add a non-nullable field 'age' to userinfo without specifying a default. This is because the database needs something to populate existing rows.
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 manually define a default value in models.py.
Select an option:

选2退出后这样子写,再次执行终端代码就好了

1
2
age=models.IntegerField(default=0)	#默认值为0

操作表中的数据

新建

1
2
3
4
def orm(request):
UserInfo.objects.create(name="lion",password="root",age=10)
return HttpResponse("成功")

1
2
3
4
5
6
7
from django.db import models

class UserInfo(models.Model):
name=models.CharField(max_length=32)
password=models.CharField(max_length=64)
age=models.IntegerField(default=0)

1
2
3
4
5
6
7
8
9
10
mysql> select * from app1_userinfo;
+----+------+----------+-----+
| id | name | password | age |
+----+------+----------+-----+
| 1 | lion | root | 10 |
+----+------+----------+-----+
1 row in set (0.00 sec)

mysql>

删除

1
2
3
4
5
6
def orm(request):
UserInfo.objects.create(name="lion",password="root",age=10)
UserInfo.objects.all().delete() #清空
#UserInfo.objects.filter(id=1).delete() #删除id=1的内容
return HttpResponse("成功")

获取数据

1
2
3
4
5
6
7
def orm(request):
date_list=UserInfo.objects.all()
print(date_list)
for item in date_list:
print...
return HttpResponse("成功")

我们看下输出,可以发现,我们通过这个获取到的数据时queryset型的

1771948016130

接下来看看单个输出,可以使用以下两个方法

1771948216580

修改

1
2
3
4
5
6
from app1.models import UserInfo
def orm(request):
UserInfo.objects.all().update(age=30)
UserInfo.objects.all().filter(id=3).update(age=30)
return HttpResponse("成功")

案例:用户管理(简略版)

views.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def login(request):
date=UserInfo.objects.all()
return render(request,'login.html',{"date":date})
def subscribe(request):
if request.method=="GET":
return render(request,'subscribe.html')
else:
name=request.POST.get("name")
age=request.POST.get("age")
pwd=request.POST.get("password")
UserInfo.objects.create(name=name,age=age,password=pwd)
date="success"
return render(request,'subscribe.html',{"date":date})
def delete(request):
nid=request.GET.get("nid")
UserInfo.objects.filter(id=nid).delete()
return HttpResponse("ok")

models.py

1
2
3
4
5
6
7
from django.db import models

class UserInfo(models.Model):
name=models.CharField(max_length=32)
password=models.CharField(max_length=64)
age=models.IntegerField(default=0)

urls.py

1
2
3
4
5
6
7
8
9
from django.contrib import admin
from django.urls import path
from app1 import views
urlpatterns = [
path('info/list', views.login),
path('info/subscribe', views.subscribe),
path('info/delete', views.delete),
]

subscribe.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form method="post">
{% csrf_token %}
<input type="text" name="name" placeholder="姓名">
<input type="password" name="password" placeholder="密码">
<input type="text" name="age" placeholder="年龄">
<input type="submit" value="提交">
</form>
<span>{{date}}</span>
<a href="/info/list" style="text-decoration:none">查看注册成员</a>
</body>
</html>

login.html

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<h1>用户列表</h1>
<body>
<table border="1">
<thead>
<tr>
<th>姓名</th>
<th>年龄</th>
<th>密码</th>
<th>删除</th>
</tr>

</thead>
{% for it in date %}
<tbody>
<tr>
<td>{{it.name}}</td>
<td>{{it.age}}</td>
<td>{{it.password}}</td>
<td>
<a href="/info/delete?nid={{it.id}}">删除</a>
</td>
</tr>
</tbody>
{% endfor %}
</table>
</body>
</html>
<a href="/info/subscribe" style="text-decoration:none">添加</a>