Django学习笔记

学习视频来源:最新Python的web开发全家桶

代码仓库:https://gitee.com/m_engmeng/django-learning

1. 创建项目

Django中项目会有一些默认的文件和文件夹

1.1 在终端

  • 打开终端
  • 进入某个目录(项目放在哪里)
  • 输入命令——创建项目 (最后一个参数是项目名)

django-admin startproject mysite

  • 继续输入—— 创建app (最后一个参数是app所处的路径以及名字)

python manage.py startapp myApp

1.2 默认项目的文件介绍

windows命令展示目录结构:

输入:tree
此时展现的是所有文件夹的路径所构成的树。

如果想连文件夹中的文件都展示,则输入:tree /f命令,可以显示所有资源。

mysite
- manage.py     [项目的管理,启动项目、创建app、数据管理][不用改]
- mysite    
    - __init__.py
    - settings.py   [项目配置][**经常更改**]
    - urls.py   [URL和函数的对应关系] [**经常更改**]
    - asgi.py   [接收异步网络请求][不用改]
    - wsgi.py   [接受同步网络请求][不用改]

1.3 app(应用)

- 项目
    - app: 用户管理 [独立的表结构、函数、HTML模板、CSS]
    - app: 订单管理 [独立的表结构、函数、HTML模板、CSS]
    - app: 后台管理 [独立的表结构、函数、HTML模板、CSS]
    - app: 网站 [独立的表结构、函数、HTML模板、CSS]
    - app: API [独立的表结构、函数、HTML模板、CSS]
    ... 

APP 目录:

E:.
│  manage.py
│
├─myApp
│  │  admin.py  [ 固定,不用动] django默认提供了admin后台管理
│  │  apps.py   [ 固定,不用动] app启动类
│  │  models.py [ 重要 ] ,对数据库操作
│  │  tests.py  [ 做单元测试]
│  │  views.py  [ 重要 ] 函数
│  │  __init__.py
│  │
│  └─migrations [ 固定,不用动] 数据库变更记录
│          __init__.py
│
└─mysite
    │  asgi.py
    │  settings.py
    │  urls.py
    │  wsgi.py
    │  __init__.py
    └─__pycache__
                settings.cpython-310.pyc
                __init__.cpython-310.pyc

2 快速上手

2.1

  • 运行前确保app已注册

    • 首先找到 myApp中的apps文件,复制其中的类名MyappConfig
    • 在mysite的文件夹下找到settings.py文件,在其中的INSTALLED_APPS 列表中,加入一行 ‘myApp.apps.MyappConfig’。
  • 编写URL和视图函数的对应关系 (urls.py)

from myApp import views

urlpatterns = [
    # path('admin/', admin.site.urls),

    # 后面只要访问  xxx.com/index  -> 就会对应views文件中的index函数
    path('index/', views.index)
]
  • 编写视图函数 [views.py]
from django.shortcuts import render, HttpResponse

# Create your views here.
# request 是默认参数,要加上
def index(request):
    return HttpResponse("欢迎使用")
  • 启动Django
    • 命令行启动
      python manage.py runserver

2.2 templates模板

在对应的app目录下创建templates文件夹,里面放置html文件

2.3 静态文件

在开发过程中一般将:

  • 图片
  • CSS
  • js
    在对应的app目录下创建static文件夹,里面分别创建
    • css文件夹
    • img文件夹
    • js文件夹
    • plugins文件夹

如果想要引入static文件夹下的文件应作如下修改:

  • 在settings.py的最后一行,加入:
STATIC_URL = '/static/'
STATICFILES_DIRS=(
    os.path.join(BASE_DIR,'static'),
)
  • 在html文件的body部分加入 {% load static %}
  • 如果引用图片,则路径修改为:
    <p>
        <img src="{% static 'img/ger.jpg' %}" alt="germany" width="420" height="320">
    p>

3 Django模板语法

本质上:在HTML中写一些占位符,由数据对这些占位符进行替换和处理。

DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>tqltitle>

head>

<body>
    <h1> Django模板语法学习 h1>
    
    <div> {{ n1 }}div>
    <div> {{ n2 }} div>
    <hr />
    <h2> 列表 h2>
    
    <div> {{ n2.0 }} div>
    <div> {{ n2.1 }} div>
    <div> {{ n2.2 }} div>
    <div> {{ n2.3 }} div>
    
    <div>
        {% for item in n2 %}
        <span> {{ item }} span>
        {% endfor %}
    div>
    <hr />
    <h2> 字典 h2>
    <div> {{ n3 }} div>
    
    <div> {{ n3.伯 }} div>
    <div> {{ n3.仲 }} div>
    <div> {{ n3.叔 }} div>
    <div> {{ n3.季 }} div>
    
    <ul>
        {% for key,value in n3.items %}
        <li> {{key}} = {{value}}li>
        {% endfor %}
    ul>
    <hr />
    <h2> 条件语句 h2>
    
    {% if n1 == '季' %}
    <h3>疾行h3>
    {% elif n1 == '霁月' %}
    <h3>霁月h3>
    {% else %}
    <h3>霁月壬h3>
    <button type="button" class="btn btn-info">信息button>
    {% endif %}
body>

html>

4 请求和响应

重定向: 浏览器向某个网站发送请求,网站返回给浏览器一个新的URL,浏览器去访问这个新的URL地址

    # request 是一个对象,封装了用户发送过来的所有请求相关数据

    # 1. [请求] 获取请求方式
    print("用户请求的方式: " + request.method)

    # 2. [请求] 在URL上传递值,例如 例如: http://123.249.26.154:5900/something/?n1=1&n2=2
    print(request.GET)

    # 3. [请求]在请求体中提交数据,目前是空值
    print(request.POST)

    # 4. [响应]HttpResponse("返回内容"),内容字符串内容返回给请求者
    return HttpResponse("返回内容")

    # 5. [响应]读取HTML的内容 + 渲染(替换) => 最终都转化为字符串返回给用户浏览器
    return render(request, 'something.html', {"title":"Hello"})

    # 6. [响应] 让浏览器重定向到其他的页面
    return redirect("http://www.baidu.com")

5 数据库操作

Django 提供ORM框架来操控数据库

5.1 安装第三方模块

pip install mysqlclient

5.2 ORM

ORM可以帮助我们做两件事:

  • 创建、修改、删除数据库中的表。[注:无法创建数据库]
  • 操作表中的数据

5.2.1 自己创建数据库

  • 启动Mysql服务
  • 自带工具创建数据库
    create database mydb DEFAULT CHARSET utf8 COLLATE utf8_general_ci;

5.2.2 django连接数据库(settings.py文件修改)

DATABASES = {
    'default':{
        'ENGINE':'django.db.backends.mysql',
        'NAME':'mydb',  # 数据库名字
        'USER':'root',
        'PASSWORD':'meng_19210504',
        'HOST':'127.0.0.1',
        'PORT':'3306',
    }
}

5.2.3 Django操作表

  • 创建表(models.py)
class UserInfo(models.Model):
    name = models.CharField(max_length=32)
    password = models.CharField(max_length=64)
    age = models.IntegerField()

"""
上面的语句等同于
create table myapp_userinfo(
    id bigint auto_increment primary key,
    name varchar(32),
    password varchar(64),
    age int
)
"""

如果不想要某个表了,将class类注释后,重新执行 runsql.bat

  • python3 manage.py makemigrations
  • python3 manage.py migrate
  • 修改表
      1. 默认值
        修改表的话,如果原本表中存有数据,此时增加一个新的列,需要设定一个默认值。
        • 手动设定

          age = models.IntegerField(default=2)

        • 允许为空

          data = models.IntegerField(null=True, blank=True)

      1. 添加数据
        如果某一列设置有默认值,那么可以不设置该列的数据,使用默认值

      UserInfo.objects.create(name=“poker”, password=“123”, age=25)

      1. 删除数据
      # 删除数据
      UserInfo.objects.filter(id=2).delete()
      # 删除表中所有数据
      UserInfo.objects.all().delete()
      
      1. 获取数据
      data_list = UserInfo.objects.all()
      print(data_list)
      for obj in data_list:
          print(obj.id, obj.name, obj.password, obj.age)
      
      
      1. 更新数据
      UserInfo.objects.filter(name="roker").update(age=35)
      

案例:用户管理

  • urls.py

        urlpatterns = [
        # path('admin/', admin.site.urls),
    
        # 后面只要访问  xxx.com/index  -> 就会对应views文件中的index函数
        path('info/list/', views.info_list),
        path('info/add/', views.info_add),
        path('info/delete/', views.info_delete),
    ]
    
  • views.py中的info_list函数

    def info_list(request):
        # 获取表中所有数据
        data_list = UserInfo.objects.all()
    
        return render(request, 'info_list.html', {"data_list":data_list})
    
  • info_list.html

        DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <title>Documenttitle>
        
        <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
        <style>
    
        style>
    
    
    head>
    
    <body>
        <a href="/info/add">添加a>
        <table border="1" class="table table-hover">
            <thead>
                <tr>
                    <th>IDth>
                    <th>姓名th>
                    <th>密码th>
                    <th>年龄th>
                tr>
            thead>
    
            <tbody>
                {% for obj in data_list %}
                <tr>
                    <td> {{ obj.id }} td>
                    <td> {{ obj.name }} td>
                    <td> {{ obj.password }} td>
                    <td> {{ obj.age }} td>
                    <td>
                        
                        <a href="/info/delete?nid={{ obj.id }}">删除a>
                    td>
                tr>
                {% endfor %}
            tbody>
        table>
    
        
        <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js">script>
        
        <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js">script>
    
    body>
    
    html>
    
  • views.py中的info_add函数

    def info_add(request):
    if request.method == 'GET':
        return render(request, 'info_add.html')
    else:
        # 获取用户提交的数据
        name = request.POST.get("name")
        password = request.POST.get("pwd")
        age = request.POST.get("age")
    
        # 如果name或者password或者age有一个为空,就无法加入到数据库里面
        if name=='' or password =='' or age=='':
            err_msgs = ['用户名不能为空', '密码不能为空', '年龄不能为空']
            name_err, pwd_err, age_err = '', '', ''
            if name == '':
                name_err = err_msgs[0]
            if password == '':
                pwd_err = err_msgs[1]
            if age == '':
                age_err = err_msgs[2]
            return render(request, 'info_add.html', {"name_err":name_err, "pwd_err":pwd_err, "age_err":age_err})
        # 添加到数据库
        UserInfo.objects.create(name=name, password=password, age = age)
    
        # 自动跳转
        return redirect("/info/list/")
    
  • info_add.html

        DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <title>Documenttitle>
        
        <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
        <style>
    
        style>
    
    
    head>
    
    <body>
    
        <form class="form-horizontal" role="form" action="/info/add/" method="post">
            {% csrf_token %}
            <div class="form-group">
                <label for="name" class="col-sm-2 control-label">用户名label>
                <div class="col-sm-10">
                    <input type="text" class="form-control" id="name" name="name" placeholder="请输入名字">
                div>
                <label for="name_err" class="col-sm-2 control-label">label>
                <div class="col-sm-10" style="color:red" name="name_err"> {{ name_err }} div>
            div>
            <div class="form-group">
                <label for="pwd" class="col-sm-2 control-label">密码label>
                <div class="col-sm-10">
                    <input type="text" class="form-control" id="pwd" name="pwd" placeholder="请输入密码">
                div>
                <label for="pwd_err" class="col-sm-2 control-label"> label>
                <div class="col-sm-10" style="color:red" name="pwd_err"> {{ pwd_err }} div>
            div>
            <div class="form-group">
                <label for="age" class="col-sm-2 control-label">年龄label>
                <div class="col-sm-10">
                    <input type="text" class="form-control" id="age" name="age" placeholder="请输入年龄">
                div>
                <label for="age_err" class="col-sm-2 control-label">label>
                <div class="col-sm-10" style="color:red" name="age_err"> {{ age_err }} div>
            div>
    
            <div class="form-group">
                <div class="col-sm-offset-2 col-sm-10">
                    <div class="checkbox">
                        <label>
                            <input type="checkbox">请记住我
                        label>
                    div>
                div>
            div>
            <div class="form-group">
                <div class="col-sm-offset-2 col-sm-10">
                    <button type="submit" class="btn btn-default">登录button>
                div>
            div>
        form>
    
        
        <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js">script>
        
        <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js">script>
    
    body>
    
    html>
    
  • views.py中的info_delete函数

    def info_delete(request):
    nid = request.GET.get("nid")
    UserInfo.objects.filter(id=nid).delete()
    return redirect("/info/list/")
    

Django开发(二)——部门列表展示、添加、删除、编辑

模板继承

当开发项目的时候,网页的导航栏等信息在多个网页中是相同的,所以为了降低每个网页的代码量,可以将网页中的相同的元素抽取出来,形成一个html文件,然后其他的网页继承该模板,在该模板上增加内容即可。
例如: 模板文件 layout.html

DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Documenttitle>
    
    <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <style>

    style>


head>

<body>
    {% block content %}
    {% endblock %}
    
    <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js">script>
    
    <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js">script>

body>

html>

继承文件:list.html

{% extends 'layout.html' %}
{% block content %}
<body>
    <a href="/info/add">添加a>
    <table border="1" class="table table-hover">
        <thead>
            <tr>
                <th>IDth>
                <th>姓名th>
                <th>密码th>
                <th>年龄th>
            tr>
        thead>

        <tbody>
            {% for obj in data_list %}
            <tr>
                <td> {{ obj.id }} td>
                <td> {{ obj.name }} td>
                <td> {{ obj.password }} td>
                <td> {{ obj.age }} td>
                <td>
                    
                    <a href="/info/delete?nid={{ obj.id }}">删除a>
                td>
            tr>
            {% endfor %}
        tbody>
    table>
{% endblock %}

则在list.html文件中自动使用layout.html中的内容,将两块内容自动拼接。
如果想要不仅在网页的部分增添内容,还想要在等中添加内容,只需要多定义几个变量即可,示例如下:

DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Documenttitle>
    
    <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    {% block style %}
    {% endblock %}


head>

<body>
    {% block content %}
    {% endblock %}
    
    <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js">script>
    
    <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js">script>
    {% block script %}
    {% endblock %}

body>

html>

可以看到,可以在任何地方自行添加要补充的内容,同时要注意 {}中的block这个是不能变的,block后面跟的是自定义的变量,变量名自定义

该案例中的模板html depart_layout.html

DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Indextitle>
    
    <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">


head>

<body>

    <nav class="navbar navbar-default">
        <div class="container">
            
            <div class="navbar-header">
                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
                    data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                    <span class="sr-only">Toggle navigationspan>
                    <span class="icon-bar">span>
                    <span class="icon-bar">span>
                    <span class="icon-bar">span>
                button>
                <a class="navbar-brand" href="#">员工管理系统a>
            div>

            
            <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                <ul class="nav navbar-nav">
                    <li><a href="#">部门管理a>li>
                    <li><a href="#">部门管理a>li>

                ul>
                <ul class="nav navbar-nav navbar-right">
                    <li><a href="#">注册a>li>
                    <li class="dropdown">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
                            aria-expanded="false">poker <span class="caret">span>a>
                        <ul class="dropdown-menu">
                            <li><a href="#">Actiona>li>
                            <li><a href="#">Another actiona>li>
                            <li><a href="#">Something else herea>li>
                            <li role="separator" class="divider">li>
                            <li><a href="#">Separated linka>li>
                        ul>
                    li>
                ul>
            div>
        div>
    nav>
    
    <div>
        {% block content %}{% endblock %}
    div>

    
    <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js">script>
    
    <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js">script>

body>

html>

展示

1. 在 urls.py 文件中增加path

    path('depart/list/', views.depart_list)

2. 在 views.py 文件中编辑 depart_list 函数

def depart_list(request):
    """部门列表"""
    depart_list = Department.objects.all()

    return render(request, "depart_list.html", {"depart_list": depart_list})

3. 在templates文件夹下创建 depart_list.html (注:下面展示的是将所有功能都写好之后的html)

{% extends 'depart_layout.html' %}

{% block content %}
<div class="container">
    <div style="margin-bottom: 10px">
        <a class="btn btn-primary" href="/depart/add/" target="_blank">新建部门a>
    div>
    <div class="panel panel-default">
        
        <div class="panel-heading">
            <span class="glyphicon glyphicon-th-list" aria-hidden="true" style="margin-right: 5px;">span>
            <span> 部门列表 span>
        div>
        
        <table class="table table-vordered">
            <thead>
                <tr>
                    <th>IDth>
                    <th>名称th>
                    <th>操作th>
                tr>
            thead>
            <tbody>
                {% for obj in depart_list %}
                <tr>
                    <th>{{ obj.id }}th>
                    <td>{{ obj.title }}td>
                    <td>
                        <a class="btn btn-primary btn-xs" href="/depart/{{ obj.id }}/edit/">编辑a>
                        <a class="btn btn-danger btn-xs" href="/depart/delete/?nid={{ obj.id }}">删除a>
                    td>
                tr>
                {% endfor %}
            tbody>
        table>
    div>
div>
{% endblock %}

添加

1. 在 urls.py 文件中增加path

path('depart/add/', views.depart_add)

2. 在 views.py 文件中编辑 depart_add 函数

def depart_add(request):
    """添加部门"""
    if request.method == "GET":
        return render(request, "depart_add.html")
    else:
        # 获取用户提交的部门数据
        depart_title = request.POST.get("depart_title")
        
        # 保存用户提交的部门数据
        Department.objects.create(title=depart_title)

        return redirect("/depart/list/")

3. 在templates文件夹下创建 depart_add.html

{% extends 'depart_layout.html' %}

{% block content %}
<div class="container">
    <div class="panel panel-default">
        
        <div class="panel-heading">
            <span class="glyphicon glyphicon-th-list" aria-hidden="true" style="margin-right: 5px;">span>
            <span> 新建部门 span>
        div>
        <div class="panel-body">
            <form action="/depart/add/" method="post">
                {% csrf_token %}
                <div class="form-group">
                    <label>部门名称label>
                    <input type="text" class="form-control" placeholder="部门名称" name="depart_title" />
                div>
                <button type="submit" class="btn btn-primary">保存button>
            form>
        div>
    div>
div>
{% endblock %}

删除

1. 在 urls.py 文件中增加path

path('depart/delete/', views.depart_delete)

2. 在 views.py 文件中编辑 depart_delete 函数

def depart_delete(request):
    """部门删除"""

    nid = request.GET.get('nid')
    Department.objects.filter(id=nid).delete()

    # 重定向回部门列表
    return redirect('/depart/list/')

3. 这里不用专门创建一个删除页面,只需要在depart_list.html中的删除按钮添加一个跳转标签即可,在跳转标签中添加参数,如下:

                        <a class="btn btn-danger btn-xs" href="/depart/delete/?nid={{ obj.id }}">删除a>

编辑

1. 在 urls.py 文件中增加path

path('depart//edit/', views.depart_edit)

注: 其中表示一个变量名为nid 的一个int变量,也就是如果要访问edit页面,必须在该位置传入一个int型整数

2. 在 views.py 文件中编辑 depart_edit 函数

注:这里,函数的参数列表里面增加了一个nid变量,这正好对应了网页链接中的表示的整数,

def depart_edit(request, nid):
    """部门编辑"""
    if request.method=="GET":
        # 根据nid获取数据
        # 这里如果不加first()函数,获取到的数据是一个列表类型,所以需要first函数获取第一个值
        row_object = Department.objects.filter(id=nid).first()
        return render(request, 'depart_edit.html', {"row_object":row_object})
    else:
        # 如果是POST请求保存修改
        depart_title = request.POST.get('depart_title')
        Department.objects.filter(id=nid).update(title=depart_title)

        # 重定向回部门列表
        return redirect('/depart/list/')

3. 在templates文件夹下创建 depart_edit.html

{% extends 'depart_layout.html' %}

{% block content %}
<div class="container">
    <div class="panel panel-default">
        
        <div class="panel-heading">
            <span class="glyphicon glyphicon-th-list" aria-hidden="true" style="margin-right: 5px;">span>
            <span> 编辑部门 span>
        div>
        <div class="panel-body">
            <form action="/depart/{{ row_object.id }}/edit/" method="post">
                {% csrf_token %}
                <div class="form-group">
                    <label>部门名称label>
                    
                    <input type="text" class="form-control" placeholder="部门名称" name="depart_title"
                        value="{{row_object.title }}" />
                div>
                <button type="submit" class="btn btn-primary">保存button>
            form>
        div>
    div>
div>
{% endblock %}


<script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js">script>

<script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js">script>

body>

html>

4. 同时要注意在depart_list.html页面中的编辑按钮 添加跳转链接

                        <a class="btn btn-primary btn-xs" href="/depart/{{ obj.id }}/edit/">编辑a>

你可能感兴趣的:(Django,django,学习,笔记)