五分喜欢的人,恨不得把他挂在嘴上招摇过市。

有七分喜欢,就只能跟至亲密友分享。

有十分喜欢 ,那就谁也不舍得说了,憋着,每天憋着一点小高兴,

像只松鼠攒着满腮帮子的果仁(*❦ω❦)

 

---------------------不定时的更新又又叕开始了,且更且珍惜------------------------ 

我要每次都写一遍:前面的还没补完,以此催促不定时更新的我
-----------------------------------------------------------------------------------------------

 

 

 

✪ 知识准备

  要想更好的掌握后面的内容,你需要先学习这些内容。

  💧 路由访问

    路由访问如果不加斜杠 会内部自动重定向加斜杠的路由

    (表面看起来像直接给你加了斜杠,但本质是先去查找不带斜杠的,

    如果匹配不上,再重定向加上斜杠的路由。)  

   💧 templates文件夹

    所有的HTML文件默认都放在templates文件夹下。

   💧 static文件夹

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

    这个文件夹是需要我们自己手动创建的,可以建在与templates同级目录,

    每个app都可以有自己的static文件夹(包含css和js文件夹)

   💧 HTML页面引入外部资源两种方式

    ①cdn              ②本地

    这时候如果我们在浏览器中访问本地服务端的时候,你会发现你所设置的

    css,js样式并没有生效(虽然你一顿操作猛如虎,此刻也是黑人问号脸)

    这是因为服务端用的本地的时候,客户端是访问不到的

    客户端在访问的时候静态文件夹路由会变成127.0.0.1/8080/mydjango/static

    而你的静态文件夹路径可能是D:\mydjango\static,那么结果可想而知。

    为了让客户端能访问到静态文件(比如本地导入的Bootstrap等),

    我们需要修改Django的settings.py:

    1.找到 settings.py,最下面

      

    2. 在其下面添加STATICFILES_DIRS = [],

     里面存放静态文件夹的路径。    

      STATICFILES_DIRS = [
          os.path.join(BASE_DIR,'static')
      ]

    注意: 

      
 # /xxx/ 这是接口前缀,跟你的静态文件夹的名字一点关系都没有
  它规定了你HTML界面导入静态文件的路径前缀
  /名字/ 这个名字可以随意取,,默认情况下这个前缀跟静态文件夹名字一样!!!
    STATICFILES_DIRS = [
        os.path.join(BASE_DIR,'static')
    ]
    # 暴露给外界能够访问服务器静态文件夹下面所有的资源


STATIC_URL = '/xxx/'  # 接口前缀 跟你的静态文件夹的名字一点关系都没有
# 默认情况下这个前缀跟静态文件夹名字一样!!!
# 静态文件配置(静态文件夹路径,可以有多个,因为每个app也可以有自己的static文件夹)

STATICFILES_DIRS = [
os.path.join(BASE_DIR,'static'),  # 就是你的静态文件夹路径
    os.path.join(BASE_DIR,'static1'),
    os.path.join(BASE_DIR,'static2')
]
# ps:浏览器访问时会依次查找列表中所有的静态文件路径 
   找到的话立刻停止,都没有找到返回404
配置静态文件夹的注意事项

     3. 修改HTML文件中导入静态文件的路径,路径开头都换成接口前缀,

      后面跟static文件下你要导入的文件的相对路径即可。

     

✪ 补充:

 form表单提交数据的方式

   💧 form表达提交数据的两种方式

      方式一:submit

          <input type="submit">

        方式二:button按钮

          <button>button</button>

   💧 form提交数据的地址如何指定及方式?

      指定:action属性控制提交的地址

      方式

        1:全路径

          <form action="http://127.0.0.1:8000/login/">

        2:只写路径后缀(浏览器会自动拿当前页面的host、

         ip帮你补全路径)

          <form action="/login/">

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

     注意:form表单默认是GET请求,当用户向后端提交form表单数据时,

        我们需要通过method属性将其改为POST。

      

        <form action="/login/" method='POST'>

      单单这样还不够,为了POST请求不报错,我们需要先将Django的

      settings.py中注释掉一个中间件。

      

      说是这样说,但难免总有人会忘,出现了下面的报错,你就注释掉

      

 

 后端如何获取前端的数据

    当后端接收到前端传来的请求时,要先判断具体的请求方式,

    判断浏览器是单纯想获取页面信息还是有数据提交给后端

    根据客户端请求方式的不同执行不同的逻辑代码

    👉如何判断请求方式

      request.method

        以登录为例使用request.method判断请求方式:

     根据客户端请求方式的不同执行不同的逻辑代码
        def login(request):
            # 获取用户端提交的请求方式
            print(request.method)  # 拿到的请求方式是全大写的字符串
            if request.method == 'GET':
                return render(request,'login.html')
            elif request.method == 'POST':
                return HttpResponse("收到了 老弟")
    
      建议按照下面这种方式书写 减少代码冗余及结构混乱的问题
        def login(request):
            if request.method == 'POST':
                return HttpResponse('OK')
            return render(request,'login.html')

    👉如何获取请求带来的数据

       request.POST  /  request.GET

print(request.GET) 
<QueryDict: {'username': ['jason'], 'password': ['123']}> request.GET.get('user') <QueryDict: {'username': ['jason','egon'], 'password': ['123']}> request.GET.getlist('username')
['jason', 'egon']

      得到的结果都是类似于一个大字典,具备字典get和[]取值的方式,

      字典的value是个列表,但在获取value的时候拿到的却是单个的元素,

      这里默认value只取最后一个元素,获取列表里面全部的数据可以用

      getlist()。具体示例请戳下👇:

          
def login(request):
    # 获取用户端提交的请求方式
    print(request.method)  # 拿到的请求方式是全大写的字符串
    # if request.method == 'GET':
    #     return render(request,'login.html')
    # elif request.method == 'POST':
    #     return HttpResponse("收到了 老弟")
    if request.method == 'POST':
        print(request.POST)  # 你就把它当成一个大字典里面存放了客户端post提交的所有的数据
        # request.POST:< QueryDict: {'username': ['jason'], 'password': ['123']} >
        print(request.POST.get('username'))  # value虽然是个列表但是获取value的时候拿到却是单个元素
        # 默认只会取value列表里面的最后一个元素
        # request.POST:<QueryDict: {'username': ['jason', 'egon'], 'password': ['123']}>
        print(request.POST.getlist('username'))  # 要想一次性获取value列表里面所有的数据需要用getlist()
        # ['jason', 'egon']
        print(request.POST['password'])  # 不推荐使用该方法获取数据
        return HttpResponse('OK')
    return render(request,'login.html')
获取具体数据

      注意:1、获取value列表里面所有元素需要使用getlist,

         应用场景:用户的爱好--多选框

         2、get只能拿到value列表的最后一个元素。

      还没完:不论你的请求方式是GET或者是POST,

          只要你的路径携带了信息,

          后端都可以通过request.GET来得到

      比如:127..0.1:8080/index/?id=1,我们可以通过

         request.GET.get('id')拿到id)。这就意味着

         前端请求方式是POST得时候,后端也是可以通过

         request.GET来得到消息,举个实例。

      那如果我们一些数据想要给后端,

      但是又不想让其显示在前端界面的时候,

      该怎么办?

      有两种方式可以实现,请看:

         方式一:将id放在action提交的URL后面

         <form action="/edit/?edit_id={{ user_obj.pk }}" method="post">

         方式二:利用input隐藏

         <input type="hidden" name="edit_id" value="{{ user_obj.pk }}">

 

✪ django实现登录功能

  没错,和上面一样的  

def login(request):
    if request.method == 'POST':
        print(request.POST)  # 你就把它当成一个大字典里面存放了客户端post提交的所有的数据
        # request.POST:< QueryDict: {'username': ['jason'], 'password': ['123']} >
        print(request.POST.get('username'))  # value虽然是个列表但是获取value的时候拿到却是单个元素
        # 默认只会取value列表里面的最后一个元素
        # request.POST:<QueryDict: {'username': ['jason', 'egon'], 'password': ['123']}>
        print(request.POST.getlist('username'))  # 要想一次性获取value列表里面所有的数据需要用getlist()
        # ['jason', 'egon']
        print(request.POST['password'])  # 不推荐使用该方法获取数据
        return HttpResponse('OK')
    return render(request,'login.html')

 

  

✪ django连接数据库

  Django自带的有一个数据库,但是我们要用mysql,不用这个sqlite3。

  👉sqlite3数据库

    sqlite是特别小的数据库功能很少,只是用来帮你做一些本地的测试

   

   👉连接MySQL数据库

    1.需要修改配置文件

     

    ps:键必须都是大写!!

 

    2.告诉django用pymysql替换它默认mysqldb模块连接数据库

  方式1:在你的项目文件夹下面的__init__.py

  方式2:也可以在你的应用文件夹下面的__init__.py  

  # 固定写法

  import pymysql

  pymysql.install_as_MySQLdb()  # 告诉django用pymysql代替mysqldb连接数据库

  因为Django现在不兼容mysqldb了

   3. 点击pycharm右侧的database,选择要连接的数据库

    

   4. 最后一步准备

    

    正常情况下完成这一步数据库就连接上了,

    下面一张图告诉你简单的一些操作

    

 

再强调一下一些需要注意的点:

  • 数据库迁移记录都存放在migrations文件夹下。
  • tools选项中的Run manage.py Task敲命令更方便,因为有提示,

   而且不需要输入前面的python3 manage.py。

   (当然前期不推荐这么干,要不然完整命令都忘了)

  • 只要修改了模型层(models.py)的与表相关的任何数据,

   都必须重新执行数据库迁移命令。

  • 一个Django项目用一个库,不要多个Django项目共用一个库!!!

 

 

✪ 什么是ORM?

  💧orm简介

对象关系映射

  类》》》  表

  对象   》》》  表记录

  对象的属性  》》》 一条记录某个字段对应的值

   注:django的orm不能够自动帮你创建库,但是可以自动帮你创建表,

     所以在创建表之前我们一定要先创建库 

  提示:一个django项目就使用一个库,不要多个django项目使用一个库,

     否则会出现莫名其妙的bug

 

  💧数据库迁移(同步)命令(******)

python3 manage.py makemigrations 

将你的数据库变动记录到一个小本本上(并不会帮你创建表)

 

python3 manage.py migrate         

将你的数据库变动正在同步到数据库中

(这一步才是真正真正操作数据库)

   注:!!!!!!!!!!!!

    修改模型层里面的跟表相关的所有的数据,

    只要你修改了就必须重新执行数据库迁移命令

    否则你所做的任何改动都是无效的。

 

  💧orm对数据库的增删改查

    新增数据

  # 操作数据库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方法保存到数据库 

    查询数据

     查全部数据:

user_list = models.User.objects.all() 
print(user_list)
print(user_list.query) #只要是QuerySet对象,就能用.query获取它内部的MySQL语句

  根据条件查询:

res = models.User.objects.filter(id=delete_id) 
#这样回来的是QuerySet对象,如果条件不存在返回空的QuerySet对象 res = models.User.objects.filter(id=delete_id).first()
#取出里面的第一个对象,虽然可以索引取,但是不推荐使用

 

  根据条件查询直接拿一个数据对象(该方法不推荐使用,因为存在报错的情况)

res = models.User.objects.get(id=edit_id)  #如果id不存在会直接报错

     注:

查询数据需要注意的是你获取到的到底是一个queryset还是一个数据对象

user_query = models.User.objects.filter(id=edit_id).first()  # 如果你是要获取数据对象first千万别忘了

# filter当条件不存在的情况下会返回一个空的queryset对象

<QuerySet []> <class 'django.db.models.query.QuerySet'>

 

get和filter相比,get能直接拿回一个数据对象,但是查询条件不满足时会报错。而filter查询条件满足

或者不满足时返回的都是QuerySet对象,可以通过.first()、.last()取其中的数据对象,不存在报错的情况。

所以一般选择用filter方法。

    补充: 

user_obj = models.User.objects.get(id=edit_id) 

# 用get可以直接获取到数据对象本身但是查询条件不存在的情况下直接报错

利用a标签href属性 可以指定页面跳转的路径  href可以写全路径 但是推荐写后缀即可

<a href="/reg/" class="btn btn-success">添加数据</a>

# 注意 路径的书写一定要加斜杠

 

queryset对象支持索引取值 但是不推荐你使用  推荐使用自带的.first()帮你获取第一条数据

 

重定向  可以写别人的网址也可以是自己的路径

return redirect('/userlist')

return redirect('/userlist/')

 

    删除数据

models.User.objects.filter(id=delete_id).delete() 
#会将该QuerySet里面的数据对象都删除掉(会同步到数据库)

 

    修改数据

复制代码
#方式一(推荐使用该方式):
models.User.objects.filter(id=edit_id).update(name=username, password=password)

#方式二:
user_obj = models.User.objects.filter(id=edit_id).first()
user_obj.name = username
user_obj.save()

 

 

 示例

编辑

编辑对象的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()
添加编辑功能让用户可以修改

 

django请求生命周期

看图说话

 

 

图书管理系统表设计

书籍表

作者

出版社

创建表时需要注意:

 

 

外键字段名 orm会自动在字段名后面加_id.无论你的字段名有没有_id

 

ps:视图函数必须返回一个HttpResponse对象