Django 1.准备 首先在当前pycharm终端运行pip install django,然后在我们想创建的目录下运行django-admin startproject 文件名 就会在当前目录下创建这个文件夹,然后进入并运行python manage.py runserver,访问地址就好了
项目的文件介绍
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.py和urls.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 │ apps.py │ 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
2.编写URL和视图函数的关系(urls.py)
1 2 3 4 5 6 from django.contrib import adminfrom django.urls import pathfrom app1 import views urlpatterns = [ path('index/' , views.index), ]
3.编写视图函数(views.py)
因为我们第二步不是导入views的index函数,那么接下来就是在views.py中编写index函数
1 2 3 4 5 6 from django.shortcuts import render,HttpResponsedef index (request ): return HttpResponse("hello world" )
4.启动Django函数
1 python manage.py runserver
templates模板 views.py部分,要注意的是通常情况下程序会根据INSTALLED_APPS的目录下的按顺序寻找每一个app的templates文件中的index.html
1 2 3 4 5 from django.shortcuts import render,HttpResponsedef 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 osTEMPLATES = [ { '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文件夹中
然后是引用,我们正常的<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 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 >
字典型 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 >
但是大多数遇到的都是字符里面嵌套字典
if型调用 1 2 3 4 5 6 7 8 {% if n1 == "lion" %} ... {% elif n1 == "XX" %} ... {% else %} ... {% endif %}
流程
爬虫 1 2 3 4 5 import requestsres=requests.get("XXX" ) date_list=res.json() print (date_list)
4.请求和响应 请求
1 2 3 4 5 6 7 8 def tpl (request ): print (request.method) print (request.GET) print (request.POST) return render(request,'tpl.html' )
响应
1 2 3 4 5 6 7 return HttpResponse("返回内容" )return render(request,"tpl.html" ,{"n1" :date})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.数据库操作
这是我们的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 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部分
替换模板,内容改为自己的
1 2 3 4 5 6 7 8 9 10 11 DATABASES = { 'default' : { 'ENGINE' : 'django.db.backends.mysql' , '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 modelsclass 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
但是注意,我们的mysql数据库增加了许多表,那是因为settings.py的Installed_app的表结构有许多个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 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 )
操作表中的数据 新建
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 modelsclass 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() 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型的
接下来看看单个输出,可以使用以下两个方法
修改
1 2 3 4 5 6 from app1.models import UserInfodef 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 modelsclass 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 adminfrom django.urls import pathfrom app1 import viewsurlpatterns = [ 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 >