Django 之 文件配置、pycharm及django连接数据库、创表及表的增删改查02

创建项目后的文件夹配置

用pycharm >settings创建项目时可以自定义一个app名,帮你自动创建一个应用,并自动创建template文件夹,查看配置INSTALLED_APPS没有自动添加新建的app,如果没有手动添加,TEMPLATES列表的“DIRS”如果没有添加templates文件夹的路径,手动添加一下。

登录功能
1.路由l(r'^login/', views.login),访问如果不加斜杠,内部自动重定向加斜杠的路由

所有的

2.所有前端渲染出来的浏览器页面,都是在后端写好的html文件,这些文件默认都写在templates文件夹;

3.所有的静态文件(css,js,前端第三方类库)默认都放在static文件夹下

html页面引入外部资源的方式
1) cdn
2) 本地

静态文件配置

静态文件配置,暴露给外界能够访问服务器静态文件夹下面所有的资源

STATIC_URL = '/static/' # 访问静态文件资源接口前缀
"""
如果你想访问静态文件资源 你必有以上面的名字开头
你才有访问静态文件资源的权限

一旦你是以接口前缀开头 我会拿着接口前缀后面的文件路径
去下面的列表中从上往下去每一个文件夹 找寻是否存在该文件 如果是直接返回
"""
自己手动配置路径
STATICFILES_DIRS = [
os.path.join(BASE_DIR,'static'), # 就是你的静态文件夹路径
os.path.join(BASE_DIR,'static1'),
os.path.join(BASE_DIR,'static2')
]

STATIC_URL = '/static/' # 接口前缀(template文件夹中的每一个html文件内的导入链接前缀) 跟你的静态文件夹的名字一点关系都没有,默认情况下这个前缀跟静态文件夹名字一样!
template 的html文件中导入的JQuery,css,js链接前缀会到static文件夹查找对应的导入文件,

ps:html文件内的导入链接前缀会依次查找列表中所有的静态文件路径是否与自己的链接匹配(是否有前缀static的路径文件)找到的话立刻停止,都没有找到返回404

接口前缀动态绑定

		html页面上的接口前缀跟你的配置文件中接口前缀动态绑定
		
		在html页面上  固定写句式
		{% load static %}
		<script src='{% static 'Bootstrap/css/min.css' %}'></script>

form表单回顾

form表单触发提交数据的动作两种方式

<input type="submit">
<button></button>

orm提交数据的地址指定方式
action属性控制提交的地址
1.全路径

<form action="http://127.0.0.1:8000/login/",method="post"> # method不写默认是get请求

改成post请求,记得将settings配置文件中的中间件注销掉。不然报黄页

2.只写路径后缀

<form action="/login/">

3.不写 (默认往当前路径提交)

form表单默认是get请求

根据请求方式的不同,返回前端不同的信息

<!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 class="text-center">登录页面</h1>
        <div class="col-md-6 col-md-offset-3">
            <form action="" method="post">
                <p>username:<input type="text" class="form-control" name="username"></p>
                <p>username:<input type="text" class="form-control" name="username"></p>
                <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">
            </form>
        </div>
    </div>
</div>
</body>
</html>
根据客户端请求方式的不同执行不同的逻辑代码
from django.shortcuts import render,HttpResponse

# Create your views here.
def login(request):
    # print(request)   # request:<WSGIRequest: GET '/login/'>

    # print(request.method)  # 获取的是用户的请求方式,是全大写的字符串
    if request.method == "POST":
        print(request.POST)  # 你就把它当成一个大字典里面存放了客户端post提交的所有的数据
        # <QueryDict: {'username': ['zhang'], 'password': ['123']}>
        print(request.POST.get('username'))  # value虽然是个列表但是获取value的时候拿到却是单个元素
        # 默认只会取value列表里面的最后一个元素
        # <QueryDict: {'username': ['zhang', 'li', 'zhao'], 'password': ['1234']}>

        # 一次性获取value列表里面所有的数据需要用getlist()
        print(request.POST.getlist('username'))  # ['zhang', 'li', 'zhao']
        print(request.POST['password'])  # 不推荐使用该方法获取数据
        return HttpResponse('登录成功!')

    return render(request,'login.html')
'''
获取value列表里面所有的元素需要使用getlist  应用场景:用户的爱好 多选框get只会获取到value列表的最后一个元素
'''
  # print(request.environ)
    '''
{'ALLUSERSPROFILE': 'C:\ProgramData',
'APPDATA': 'C:\Users\Administrator\AppData\Roaming',
'COMMONPROGRAMFILES': 'C:\Program Files\Common Files',
'COMMONPROGRAMFILES(X86)': 'C:\Program Files (x86)\Common Files',
'COMMONPROGRAMW6432': 'C:\Program Files\Common Files',
'COMPUTERNAME': 'WIN-KIJ962UBO3B',
'COMSPEC': 'C:\windows\system32\cmd.exe',
'DJANGO_SETTINGS_MODULE': 'day52.settings',
'FP_NO_HOST_CHECK': 'NO', 
'HOMEDRIVE': 'C:',
'HOMEPATH': '\Users\Administrator', 
'LOCALAPPDATA': 'C:\Users\Administrator\AppData\Local', 
'LOGONSERVER': '\\WIN-KIJ962UBO3B',
'NUMBER_OF_PROCESSORS': '4',
'OS': 'Windows_NT', 
'PATH': 'G:\python36;G:\python36\Scripts;G:\Python27;G:\Python27\Scripts;G:\Python27\Scripts;G:\python36\Scripts;C:\windows\system32;C:\windows;C:\windows\System32\Wbem;C:\windows\System32\WindowsPowerShell\v1.0\;C:\Users\Administrator\Desktop\new 1.py;G:\sub3;G:\MYSQL\bin;G:\Git\cmd;G:\Git\mingw64\bin;G:\Git\usr\bin;G:\python36\lib\site-packages\numpy\.libs;G:\python36\lib\site-packages\numpy\.libs', 'PATHEXT': '.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC', 'PROCESSOR_ARCHITECTURE': 'AMD64', 'PROCESSOR_IDENTIFIER': 'Intel64 Family 6 Model 69 Stepping 1, GenuineIntel',
'PROCESSOR_LEVEL': '6',
'PROCESSOR_REVISION': '4501',
'PROGRAMDATA': 'C:\ProgramData',
'PROGRAMFILES': 'C:\Program Files',
'PROGRAMFILES(X86)': 'C:\Program Files (x86)',
'PROGRAMW6432': 'C:\Program Files', 
'PSMODULEPATH': 'C:\windows\system32\WindowsPowerShell\v1.0\Modules\',
'PUBLIC': 'C:\Users\Public',
'PYCHARM_HOSTED': '1',
'PYCHARM_MATPLOTLIB_PORT': '49203',
'PYTHONIOENCODING': 'UTF-8', 
'PYTHONPATH': 'G:\PyCharm 2018.1.4\helpers\pycharm_matplotlib_backend;G:\Python代码日常\day52'
'PYTHONUNBUFFERED': '1',
'SESSIONNAME': 'Console',
'SYSTEMDRIVE': 'C:', 
'SYSTEMROOT': 'C:\windows',
'TEMP': 'C:\Users\ADMINI~1\AppData\Local\Temp',
'TMP': 'C:\Users\ADMINI~1\AppData\Local\Temp',
'USERDOMAIN': 'WIN-KIJ962UBO3B',
'USERNAME': 'Administrator',
'USERPROFILE': 'C:\Users\Administrator',
'WINDIR': 'C:\windows',
'WINDOWS_TRACING_FLAGS': '3',
'WINDOWS_TRACING_LOGFILE': 'C:\BVTBin\Tests\installpackage\csilogfile.log',
'RUN_MAIN': 'true',
'SERVER_NAME': 'WIN-KIJ962UBO3B', 
'GATEWAY_INTERFACE': 'CGI/1.1',
'SERVER_PORT': '8000', 
'REMOTE_HOST': '', 
'CONTENT_LENGTH': '', 
'SCRIPT_NAME': '', 
'SERVER_PROTOCOL': 'HTTP/1.1',
'SERVER_SOFTWARE': 'WSGIServer/0.2',
'REQUEST_METHOD': 'GET', 
'PATH_INFO': '/login/', 
'QUERY_STRING': '',
'REMOTE_ADDR': '127.0.0.1',
'CONTENT_TYPE': 'text/plain',
'HTTP_HOST': '127.0.0.1:8000', 
'HTTP_CONNECTION': 'keep-alive', 
'HTTP_UPGRADE_INSECURE_REQUESTS': '1',
'HTTP_USER_AGENT': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36',
'HTTP_ACCEPT': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
'HTTP_ACCEPT_ENCODING': 'gzip, deflate,
br', 'HTTP_ACCEPT_LANGUAGE': 'zh-CN,zh;q=0.9,en;q=0.8',
'HTTP_COOKIE': 'csrftoken=YN8zgrVrZ4rrIZpWwFmyKY6yp2ggTCaUsDT4HJYUn36OY7Ijk7LpGTHtKbNML8EB',
'wsgi.input': <_io.BufferedReader name=656>,
'wsgi.errors': <_io.TextIOWrapper name='<stderr>' mode='w' encoding='UTF-8'>,
'wsgi.version': (1, 0), 'wsgi.run_once': False,
'wsgi.url_scheme': 'http',
'wsgi.multithread': True, 
'wsgi.multiprocess': False,
'wsgi.file_wrapper': <class 'wsgiref.util.FileWrapper'>}
    '''

pycharm 连接MYSQL数据库

直接上图:

可以达到与数据库的数据同时更新 删除;

Django 连接MYSQL数据库的配置

其实python解释器在运行django程序时,django的orm底层操作数据库的python模块默认是mysqldb而非pymysql,然而对于解释器而言,python2.x解释器支持的操作数据库的模块是mysqldb,而python3.x解释器支持的操作数据库的模块则是pymysql,,毫无疑问,目前我们的django程序都是运行于python3.x解释器下,于是我们需要修改django的orm默认操作数据库的模块为pymysql,具体做法如下:

settings.py文件>DATABASES

DATABASES = {    'default': {        'ENGINE': 'django.db.backends.sqlite3',        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),    }}

	django连接数据库
	1.需要修改配置文件
    
# 修改为:
		DATABASES = {
			'default': {
				'ENGINE': 'django.db.backends.mysql',
				'NAME': 'day54',
				'HOST':'127.0.0.1',
				'PORT':3306,
				'USER':'root',
				'PASSWORD':'123'
			}
		}
		ps:键必须都是大写
            
2.告诉django用pymysql替换它默认mysqldb模块连接数据库
		方式1:在你的项目文件夹下面的__init__.py
		方式2:也可以在你的应用文件夹下面的__init__.py
		
		# 固定写法
		import pymysql
		pymysql.install_as_MySQLdb()  # 告诉django用pymysql代替mysqldb连接数据库

Django的ORM

什么是ORM?

对象关系映射
	类			》》》  表
	对象   		》》》  表记录
	对象的属性  》》》 一条记录某个字段对应的值

django的orm不能够自动帮你创建库,但是可以自动帮你创建表
提示:一个django项目就使用一个库,不要多个django项目使用一个库

Django 对表操作

models中写建表的类

from django.db import models

# Create your models here.
class User(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    password = models.CharField(max_length=16)  

数据库的迁移命令

cmd 终端敲下面命令,将建表的各字段记在migration文件夹下面的一个自动生成的.py文件中,然后将建的表的字段同步更新到数据库当中。

# 数据库迁移(同步)命令(******)
python3 manage.py makemigrations  # 将你的数据库变动记录到一个小本本上(并不会帮你创建表)
python3 manage.py migrate         # 将你的数据库变动正在同步到数据库中

表字段的增删改查

改字段(字段的长度)

# 直接修改代码 然后执行数据库迁移命令即可(两条一条不能少)
			    # 方式1  设置默认值
				email = models.EmailField(default='123@qq.com')  # varchar
				# 方式2   允许字段为空
				phone = models.BigIntegerField(null=True)
				# 直接在提示中给默认值
				gender = models.CharField(max_length=32)

增字段

直接增加对应的字段 然后再执行数据库迁移命令即可(谨慎使用)

字段的删除
直接注释掉对应的字段 然后再执行数据库迁移命令即可(谨慎使用)

模型表数据的增删改查

# 查
	data = models.User.objects.filter(username=username)  #queryset对象 <QuerySet [<User: User object>]>,filter当条件不存在的情况下会返回一个空的queryset对象==><QuerySet []> <class'django.db.models.query.QuerySet'>
    
# 方式1:
data = models.User.objects.filter(username=username)[0]  # 不推荐使用
# 方式2
data = models.User.objects.filter(username=username).first()  # 获取列表(QuerySet对象)内索引0的数据对象数据对象,数据对象通过点方法获取属性值,queryset对象支持索引取值 但是不推荐你使用  推荐使用自带的.first()帮你获取第一条数据
    	
"""
filter返回的结果是一个"列表",里面才是真正数据对象
filer括号内可以放多个关键字参数 这多个关键字参数在查询的时候 是and关系
"""
user_list = models.User.objects.all()  #查出所有的数据对象,返回的是列表,里面是一个个User对象 <QuerySet [<User: User object>, <User: User object>]>
"""
结果是一个"列表" 里面是一个个的数据对象
"""

登录功能代码

def login(request):
    if request.method=='POST':
        username = request.POST.get('username')
        password = request.POST.get('password')

        data = models.User.objects.filter(name = username)
        if not data:
            return HttpResponse('当前用户不存在!')
        user_obj = data[0]
        print("对象的id:",user_obj.pk)  # 同 user_obj.id  获取主键的id值
        # data1 = models.User.objects.all()
        if user_obj.password == password:
            return HttpResponse('登录成功!')
        return HttpResponse('密码错误')
    return render(request,'login.html')

# 方式1:
user_obj = models.User.objects.create(username=username,password=password)
        print(user_obj,user_obj.username,user_obj.password)
		# create方法会有一个返回值  返回值就是当前被创建的对象本身
# 方式2:
user_obj = models.User(name=username,password=password)
user_obj.save()  # 对象调用save方法保存到数据库

添加用户代码

# userlist.py文件  以表格的形式向浏览器页面展示用户信息,点击新增按钮,跳到添加用户页面
<!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>
    {% load static %}   {# 改成这种形式,即使urls文件中的STATIC_URL = '/static/'后缀名改成其他的,link和script中的static前缀也能识别#}
    <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">
        <div class="col-md-8 col-md-offset-2">
            <h1 class="text-center">数据展示</h1>
            <a href="/add_user/" class="btn btn-success">新增</a>
            <table class="table table-hover table-bordered table-striped">
                 <thead>
                 <tr>
                     <th>id</th>
                     <th>username</th>
                     <th>password</th>
                     <th>actions</th>
                 </tr>
                 </thead>
                 <tbody>
                    {% for user in user_list %}
                        <tr>
                            <td>{{user.id}}</td>
                            <td>{{user.name}}</td>
                            <td>{{user.password}}</td>
                            <td>
                                <!--href跟的是跳转的后缀,问号后是get请求携带的参数 -->
                                 <a href="/edit_user/?edit_id={{ user.id }}" class="btn btn-primary btn-sm">编辑</a>
                                 <a href="/delete_user/?delete_id={{ user.id }}" class="btn btn-danger btn-sm">删除</a>
                            </td>
                        </tr>
                    {% endfor %}
                 </tbody>
             </table>
        </div>
    </div>
</div>
</body>
</html>
# add_user.py文件  输入信息,点击提交,跳到查看用户页面,此时新增用以添加
<!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>
    {% load static %}
    <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">
            <div class="col-md-8 col-md-offset-2">
                <h1 class="text-center">添加用户</h1>
                <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-warning pull-right">
                </form>
            </div>
        </div>
    </div>
</body>
</html>
def userlist(request):

    user_list = models.User.objects.all()
    # print(user_list)  # <QuerySet [<User: User object>, <User: User object>]>

    return render(request,'userlist.html',{'user_list':user_list})

def add_user(request):
    if request.method=='POST':
        username = request.POST.get('username')
        password = request.POST.get('password')

        user_list = models.User.objects.filter(name = username)
        if user_list:
            return HttpResponse('用户已存在!')
        # 增
        user_obj = models.User.objects.create(name=username,password=password)
        print(user_obj,user_obj.name,user_obj.password)
        # 跳转到查看页面
        return redirect('/userlist/')
    return render(request,'add_user.html')

# 方式1:
models.User.objects.filter(id=edit_id).update(username=username,password=password)

# 方式2:获取到当前数据对象
user_obj = models.User.objects.filter(id=edit_id).first()
user_obj.name = username
user_obj.save()
"""
批量操作  会将filter查询出来的列表中所有的对象全部更新
"""

修改用户代码

输入后缀/userlist/,返回给用户所有用户的信息,用户点击“编辑”“按钮,触发edit_user函数,携带id,后端获取id,去数据区查取对应的用户对象,通过对象点属性,将用户的属性值("edit_user.html"文件)渲染到浏览器,用户点击提交按钮,后端再将用户提交(post请求)的已修改的数据保存到数据库,并将修改过后的所有用户的信息(userlist.html文件)渲染到前端

def edit_user(request):
    # print(request.GET)  # <QueryDict: {'edit_id': ['2']}>
    if request.method =='POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        models.User.objects.filter(id=edit_id).update(name=username,password=password)
        return redirect('/userlist/')
    
	# 如何获取用户想要编辑的数据ID  利用get请求携带参数的方式 获取用户想要编辑的数据id值
    edit_id = request.GET.get('edit_id')
    # 将用户想要编辑的数据查询出来 展示到编辑页面上 供用户修改
    # edit_obj = models.User.objects.filter(id=edit_id)[0]
    edit_obj = models.User.objects.filter(id=edit_id).first()
    # 返回一个编辑页面  该编辑页面上 应该展示用户想要编辑的数据信息
    return render(request,'edit_user.html',{'edit_obj':edit_obj})
<!--edit_user.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>
    {% load static %}
    <link rel="stylesheet" href="{% static 'bootstrap-3.3.7/css/bootstrap.min.css' %}">
    <script src="{% static 'bootstrap-3.3.7/css/bootstrap.min.css' %}"></script>

</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <h1 class="text-center">编辑用户</h1>
            <form action="" method="post">
                <p>username:<input type="text" class="form-control" name="username" value="{{ edit_obj.name }}"></p>
                <p>password:<input type="text" class="form-control" name="password" value="{{ edit_obj.password }}"></p>
                <input type="submit" class="btn btn-info pull-right">
            </form>

        </div>
    </div>
</div>
</body>
</html>

删除

models.User.objects.filter(id=delete_id).delete()
"""
批量操作  会将filter查询出来的列表中所有的对象全部删除
"""
def delete_user(request):
    delete_id = request.GET.get('delete_id')
    models.User.objects.filter(id = delete_id).delete()
    return render(request,'userlist.html')

本次内容总结

下一篇:django 路由层(反向解析)03

原文地址:https://www.cnblogs.com/zhangchaocoming/p/11921184.html