django基本操作
在settings里面的INSTALLED_APPS添加上你所创建的应用。
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01.apps.App01Config', # ***** 'app01' # 也可以简写成app01 ]
urls.py
from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^login/',views.login) # 登录路由 ]
views.py
from django.shortcuts import render,HttpResponse,redirect # Create your views here. def login(request): return HttpResponse('login')
开启服务器后,客户端页面输入127.0.0.1:8000/login/时最后面的/加不加都没影响,原因时:路由访问如果不加斜杠,会内部自动重定向加斜杠的路由。
所有的html文件默认都写在templates文件夹下。
所有的静态文件(css,js,前端第三方类库)默认都放在static文件夹下。
html页面引入外部资源的方式
cdn / 本地
静态文件配置
直接在html文件里引入本地bootstrap会没有效果,原因是在客户端浏览器根本就访问不到这个路径,所以要把它加到static文件里。
# 在settings.py最下面加上 STATIC_URL = '/static/' # 接口前缀,跟你的静态文件夹的名字一点关系都没有,如果你把static改为xxx,则你的html文件里引入bootstrap时前面的地址也应该改为xxx,默认情况下这个前缀跟静态文件夹名字一样 # 静态文件配置 STATICFILES_DIRS = [ os.path.join(BASE_DIR,'static'), #就是你的静态文件夹路径 os.path.join(BASE_DIR,'static1'),#会依次查找列表中所有的静态文件路径,找到的话立刻停止,都没有找到返回404 os.path.join(BASE_DIR,'static2') ] # 暴露给外界能够访问服务器静态文件夹下面所有的资源。
然后再login.html文件里导入文件路劲:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.min.css"> <script src="/static/bootstrap-3.3.7/js/bootstrap.min.js"></script> </head> <body> <div class = "container"> <div class="row"> <h1>登录页面</h1> <div class="col-md-6 col-md-offset-3"> <form action="" method="post"> # 这里采用方式3:默认形式 <p>username:<input type="text" class="form-control" name="username"></p> <p>password:<input type="password" class="form-control" name="password"></p> <input type="submit" class="btn btn-success"> <!--input是get请求提交--> </form> </div> </div> </div> </body> </html>
<input type='submit'>
<button></button>
form提交数据的地址如何指定及方式?
action属性控制提交的地址
方式:
1、全路径 <form action="http://127.0.0.1:8000/login/> 2、只写路径后缀 <form action="/login/"> 3、不写(默认往当前路径提交)http://127.0.0.1:8000/
form表单默认是get请求,但可以通过method改为post请求
post请求和get请求的区别:
# views.py文件下
from django.shortcuts import render,HttpResponse,redirect
def login(request):
# print("ok") # 测试通过form表单能触发回来
# 获取用户的提交的请求方式
print(request.method) # 默认是get请求,但把action里的methon改为post并且把settings中MIDDLEWARE列表下的中间件注释掉会返回post请求
return render(request,'login.html')
注意:在客户端中输入用户名和密码会返回黄页,解决方法是在settings文件中找到MIDDLEWARE列表下的'django.middleware.csrf.CsrfViewMiddleware',并把它注释掉,在不管为什么,后面会讲,如下:
MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', # 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ]
# 在views.py文件下的登录代码
def login(request): # print("ok") # 获取用户端提交的请求方式 print(request.method) # 默认是get请求,但把action里的methon改为post并且把settings中MIDDLEWARE列表下的中间件注释掉在返回用户名和密码等数据时会返回post请求 # if request.method == 'GET': # 这里相当于只访问http:127.0.0.1:8000/login/,会返回一个注册页面 GET # return render(request,'login.html') # elif request.method == 'POST': # 这里相当于在注册页面输入了用户名和密码提交给服务端然后会返回POST # return HttpResponse("收到了 老弟")
# 上面4行代码也可以简写成下面形式,减少代码冗余及结构混乱的问题
if request.method == 'POST': ''' # 接下来就要思考如何获得具体的数据了 print(request.POST) #得到的结果是<QueryDict: {'username': ['jason'], 'password': ['123']}> 你就把它当成一个大字典里面存放了客户端post提交的所有的数据 print(request.POST.get('username')) # 得到jason print(request.POST['password']) # 得到123 不推荐用这种方法,因为不存在会报错,最好用get方法 # 疑问:为什么取到的值是一个字符串而不是列表? # 简单测试:在login.html中再加一个username输入框,会得到username列表里有两个值,这时会取最后一个值 # 如:<QueryDict: {'username': ['jason', 'egon'], 'password': ['123']}> 这时取request.POST.get('username')得到egon # 结论:默认只会取列表里面的最后一个元素 # 如果我不只想取一个值,而是取多个值,可以用getlist方法 print(request.POST.getlist('username')) # ['jason','egon'] ''' return HttpResponse('OK') # 在客户端浏览器的搜索框内输入http://127.0.0.1:8000/login/?username=jason&password=123会得到get请求 print(request.GET) # <QueryDict: {'username': ['jason'], 'password': ['123']}> # 获取get请求数据的方式跟post请求完全一样 ''' request.GET.get('password') request.GET.getlist('username') ''' return render(request,'login.html')
小总结:获取value列表里面所有的元素需要使用getlist 应用场景:用户的爱好,多选框
get只会获取到value列表的最后一个元素
GET请求和POST请求操作方法一样
# 在views.py文件下的完整登录代码
from django.shortcuts import render,HttpResponse,redirect import pymysql def login(request): # print("ok") # 获取用户端提交的请求方式 # print(request.method) # 默认是get请求,但把action里的methon改为post并且把settings中MIDDLEWARE列表下的中间件注释掉在返回用户名和密码等数据时会返回post请求 # if request.method == 'GET': # 这里相当于只访问http:127.0.0.1:8000/login/,会返回一个注册页面 GET # return render(request,'login.html') # elif request.method == 'POST': # 这里相当于在注册页面输入了用户名和密码提交给服务端然后会返回POST # return HttpResponse("收到了 老弟") # 上面4行代码也可以简写成下面形式,减少代码冗余及结构混乱的问题 if request.method == 'POST': ''' # 接下来就要思考如何获得具体的数据了 print(request.POST) #得到的结果是<QueryDict: {'username': ['jason'], 'password': ['123']}> 你就把它当成一个大字典里面存放了客户端post提交的所有的数据 print(request.POST.get('username')) # 得到jason print(request.POST['password']) # 得到123 不推荐用这种方法,因为不存在会报错,最好用get方法 # 疑问:为什么取到的值是一个字符串而不是列表? # 简单测试:在login.html中再加一个username输入框,会得到username列表里有两个值,这时会取最后一个值 # 如:<QueryDict: {'username': ['jason', 'egon'], 'password': ['123']}> 这时取request.POST.get('username')得到egon # 结论:默认只会取列表里面的最后一个元素 # 如果我不只想取一个值,而是取多个值,可以用getlist方法 print(request.POST.getlist('username')) # ['jason','egon'] ''' # 获取用户输入的用户名和密码 username = request.POST.get('username') password = request.POST.get('password') conn = pymysql.connect( host = '127.0.0.1', port = 3306, user = 'root', password = '123456', database = 'day54', charset = 'utf8', autocommit = True ) cursor = conn.cursor(pymysql.cursors.DictCursor) cursor.execute('select * from userinfo where name=%s and password=%s',(username,password)) user_info = cursor.fetchall() if user_info: return HttpResponse('登录成功') # 在客户端浏览器的搜索框内输入http://127.0.0.1:8000/login/?username=jason&password=123会得到get请求 # print(request.GET) # <QueryDict: {'username': ['jason'], 'password': ['123']}> # 获取get请求数据的方式跟post请求完全一样 ''' request.GET.get('password') request.GET.getlist('username') ''' return render(request,'login.html')
如何在django里面直接和数据库相连
# 首先修改配置文件 settins里面的DATABASES DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', #django默认自带一个小型的sqlite3数据库,可以用来做本地测试 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } }
# 1、修改配置文件
DATABASES = { 'default': { # 'ENGINE': 'django.db.backends.sqlite3', # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 'ENGINE': 'django.db.backends.mysql', 'NAME':'day55', 'HOST':'127.0.0.1', 'PORT':3306, 'USER':'root', 'PASSWORD':'123456' } }
ps:键必须都是大写
# 2、告诉django用pymysql替换它默认的mysql_db模块连接数据库
方式1:在你的项目文件夹下面的__init__.py
方式2:也可以在你的应用文件夹下面的__init__.py
# 固定写法
import pymysql pymysql.install_as_MySQLdb() #告诉django用pymysql代替mysqldb连接数据库 # 在models.py文件下 from django.db import models # Create your models here. class User(models.Model): # user表的主键字段名就是id id = models.AutoField(primary_key=True) # varchar(32) name字段是varchar(32) CharField在定义的时候必须要加max_length参数 name = models.CharField(max_length=32) # varchar(16) name字段是varchar(32) CharField在定义的时候必须要加max_length参数 password = models.CharField(max_length=16)
django的orm不能够自动帮你创建库,但是可以自动帮你创建表
提示:一个django项目就使用一个库,不要多个django项目使用一个库
数据库迁移(同步)命令
python3 manage.py makemigrations # 将你的数据库变动记录到一个小本本上(并不会帮你创建表)
python3 manage.py migrate # 将你的数据库变动正在同步到数据库中
注册功能
<!-- reg.html --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.min.css"> <script src="/static/bootstrap-3.3.7/js/bootstrap.min.js"></script> </head> <body> <div class="container"> <div class="row"> <h1>注册页面</h1> <div class="col-md-8 col-md-offset-2"> <form action="" method="post"> <p>username:<input type="text" name="username" class="form-control"></p> <p>password:<input type="password" name="password" class="form-control"></p> <input type="submit" class="btn btn-primary"> </form> </div> </div> </div> </body> </html> # views.py def reg(request): if request.method == 'POST': # 获取用户输入的用户名和密码 username = request.POST.get('username') password = request.POST.get('password') # 操作数据库user表插入数据 # 方式1: # user_obj = models.User.objects.create(name=username,password=password) # 方式2: user_obj = models.User(name=username,password=password) user_obj.save() print(user_obj.pk) #pk获取主键字段对应的值 无论你的主键叫什么名字 print(user_obj.name) #获取用户数据的name值 print(user_obj.password) # 获取用户数据的password值 return HttpResponse('注册成功') #return redirct(requset,'reg.html') #这是在查询数据功能写完后直接链接过去 return render(request,'reg.html')
新增数据
操作数据库user表插入数据
方式1: user_obj = models.User.objects.create(name=username,password=password) 方式2: user_obj = models.User(name=username,password=password) user_obj.save() # 对象调用save方法保存到数据库
# 查询数据
def __str__(self): return self.name <!-- userlist.html --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.min.css"> <script src="/static/bootstrap-3.3.7/js/bootstrap.min.js"></script> </head> <body> <div class="container"> <div class="row"> <h1>展示数据</h1> <div class="col-md-8 col-md-offset-2"> <table class="table-hover table table-bordered table-striped"> <thead> <tr> <th>id</th> <th>name</th> <th>password</th> </tr> </thead> <tbody> {% for user_obj in user_list %} {# 模型注释: user_list = [obj1,obj2,obj3 #} <tr> <td>{{ user_obj.pk }}</td> <td>{{ user_obj.name }}</td> <td>{{ user_obj.password }}</td> </tr> {% endfor %} </tbody> </table> </div> </div> </div> </body> </html> # views.py def userlist(request): # 获取数据库数据 user_list = models.User.objects.all() # select id,name,password form user; print(user_list.query) #只要是QuerySet就可以点query查看获取到当前QuerySet对象的内部sql语句 for user_obj in user_list: print(user_obj.pk,user_obj.name) return render(request,'userlist.html',locals()) # locals()也可以是字典,表示给userlist.html传值过去
增加一个添加数据的按钮
<div class="container"> <div class="row"> <h1>展示数据</h1> <div class="col-md-8 col-md-offset-2"> <a href="/reg/" class="btn btn-success">添加数据</a> <!--*****--> <table class="table-hover table table-bordered table-striped">
利用a标签href属性 可以指定页面跳转的路径 href可以写全路径 但是推荐写后缀即可
<a href="/reg/" class="btn btn-success"添加数据
注意 路径的书写一定要加斜杠
重定向 可以写别人的网址也可以是自己的路径
return redirect('/userlist')
return redirect('/userlist/')
增加编辑删除两个按钮
<tbody> {% for user_obj in user_list %} {# user_list = [obj1,obj2,obj3] #} <tr> <td>{{ user_obj.pk }}</td> <td>{{ user_obj.name }}</td> <td>{{ user_obj.password }}</td> <td> <a href="/edit/?edit_id={{ user_obj.pk }}" class="btn btn-primary">编辑</a> <a href="/delete_user/?delete_id={{ user_obj.pk }}" class="btn btn-danger">删除</a> </td> </tr> {% endfor %} </tbody>
删除
def delete_user(request): # 从get请求携带的参数中获取用户想要删除的数据id delete_id = request.GET.get('delete_id') # res = models.User.objects.filter(id=delete_id)[0] # 过滤方法,会过滤所有满足filter()里面的条件的值 # res = models.User.objects.filter(id=delete_id).first() models.User.objects.filter(id=delete_id).delete() # 会将queryset所有的数据对象全部删除 # print(res) # <QuerySet [<User: jason>]> # # print(res.query) # print(type(res)) return redirect('/userlist')
queryset对象支持索引取值 但是不推荐你使用 推荐使用自带的.first()帮你获取第一条数据
models.User.objects.filter(id=1).delete() # 会将queryset所有的数据对象全部删除
查询数据
edit.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.min.css"> <script src="/static/bootstrap-3.3.7/js/bootstrap.min.js"></script> </head> <body> <div class="container"> <div class="row"> <h1>编辑数据</h1> <div class="col-md-6 col-md-offset-3"> <form action="/edit/?edit_id={{ user_obj.pk }}" method="post"> <input type="hidden" name="edit_id" value="{{ user_obj.pk }}"> <p>username:<input type="text" name="username" value="{{ user_obj.name }}" class="form-control"></p> <p>password:<input type="text" name="password" value="{{ user_obj.password }}" class="form-control"></p> <input type="submit" class="btn btn-warning"> </form> </div> </div> </div> </body> </html> views.py def edit(request): if request.method == 'POST': print(request.POST) print(request.GET) username = request.POST.get('username') password = request.POST.get('password') # 获取编辑对象的id方式 edit_id = request.POST.get('edit_id') edit_id = request.GET.get('edit_id') # 更新数据库 models.User.objects.filter(id=edit_id).update(name=username,password=password) return redirect('/userlist') # 获取用户想要修改的数据的id edit_id = request.GET.get('edit_id') # 将该数据查询出来渲染到一个编辑页面 # 查询数据方式1 user_obj = models.User.objects.filter(id=edit_id).first() # 查询数据方式2 # # user_obj = models.User.objects.get(id=edit_id) # print(user_obj,type(user_obj)) # 将当前数据渲染到一个编辑页面上 return render(request,'edit.html',locals())
查询数据需要注意的是你获取到的到底是一个queryset还是一个数据对象
user_query = models.User.objects.filter(id=edit_id).first() # 如果你是要获取数据对象first千万别忘了
filter当条件不存在的情况下会返回一个空的queryset对象
<QuerySet []> <class 'django.db.models.query.QuerySet'>
user_obj = models.User.objects.get(id=edit_id) # 用get可以直接获取到数据对象本身但是查询条件不存在的情况下直接报错
编辑对象的id的获取方式
方式1:利用input隐藏一个标签
<input type="hidden" name="edit_id" value="{{ user_obj.pk }}">
方式2:
<form action="/edit/?edit_id={{ user_obj.pk }}" method="post">
注意:queryset对象点修改 删除 会作用于对象内部所有的数据对象 类似于批量操作
方式1:
models.User.objects.filter(id=edit_id).update(name=username,password=password)
方式2:获取到当前数据对象
user_obj = models.User.objects.filter(id=edit_id).first()
user_obj.name = username
user_obj.save()
修改模型层里面的跟表相关的所有的数据,只要你修改了就必须重新执行数据库迁移命令
python manage.py makemigrations 记录到小本本上
python manage.py migrate 真正操作数据库
# models.py from django.db import models # Create your models here. class User(models.Model): # user表的主键字段名就是id id = models.AutoField(primary_key=True) # varchar(32) name字段是varchar(32) CharField在定义的时候必须要加max_length参数 name = models.CharField(max_length=32) # varchar(16) name字段是varchar(32) CharField在定义的时候必须要加max_length参数 password = models.CharField(max_length=16) def __str__(self): return self.name class Book(models.Model): id = models.AutoField(primary_key=True) title = models.CharField(max_length=32) author = models.CharField(max_length=32) # 一对多外键字段的建立 publish = models.ForeignKey(to='Publish') # 默认是与publish表的id字段建立关联 # 多对多外键字段建在关联的两张表的任何一张都可以 # author = models.ManyToManyField(to='Author') # 注意多对多字段不会显示到表的字段中 class Publish(models.Model): name = models.CharField(max_length=32) email = models.CharField(max_length=32) class Author(models.Model): name = models.CharField(max_length=32) age = models.IntegerField() phone = models.CharField(max_length=32)