写在前面

一直都写的是前后端分离,当初学php的时候对不分离的形式有一点点印象,这次用Django也试一试,感觉这种不分离的形式起一个网站速度很快很快,比分离的写法简单很多,只可惜Django的教程太少了,自己还是比较喜欢分离的写法,于是在学了半天时间后遂放弃,因此只能称作浅尝。本来感觉java没啥前途不想学springboot的,现在看来还是要转到主流的,学起来也方便很多。

一、环境搭建

1.1 创建项目

使用conda activate conda环境名称启动环境

使用django-admin startproject 项目名称创建项目,文件结构如下:

mysite
├── manage.py           [管理项目文件,例如:运行、类自动生成数据表]
└── mysite
    ├── __init__.py
    ├── settings.py     [项目配置文件,例如:连接哪个数据库... ]
    ├── urls.py         [根路由,URL和函数的对应关系  /x1/login ->do_login ]
    ├── asgi.py         [异步运行项目,编写socket,处理网络请求]
    └── wsgi.py         [同步运行项目,编写socket,处理网络请求]

1.2 快速上手

urls.py

from django.contrib import admin
from django.urls import path
from django.shortcuts import HttpResponse

def login(request):
    return HttpResponse("登录页面")


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

1.3 快速启动

目录中不能出现中文

网站启动起来,通过浏览器就可以访问。

  • 打开终端并进入项目根目录(看到manage.py)
  • 执行命令,启动网站
python manage.py runserver 127.0.0.1:8000
或
python manage.py runserver

image-20240624115921462

image-20240624115957354

1.4 APP

一个业务创建一个app,除非是业务很多的大型项目可以创建多个app,可以通俗的理解为模块化。

譬如之前的ctf平台,题目相关的一个app,社区相关的一个app。

在django项目中创建app,在app中编写项目中的具体业务,python manage.py startapp web

django_study
├── manage.py           [管理项目文件,例如:运行、类自动生成数据表]
└── django_study
    ├── __init__.py
    ├── settings.py     [项目配置文件,例如:连接那个数据... ]
    ├── urls.py         [根路由,URL和函数的对应关系  /x1/login ->do_login ]
    ├── asgi.py         [异步运行项目,编写socket,处理网络请求]
    ├── wsgi.py         [同步运行项目,编写socket,处理网络请求]
    └── templates(可能有)[如果前后端不分离的话,放html模板文件]
└── web
    ├── __init__.py
    ├── admin.py        [内部后台管理的配置,不要动]
    ├── apps.py         [App名字,不要动]
    ├── migrations      [迁移记录,不要修改他,自动生成]
    │   └── __init__.py
    ├── models.py       [数据库,类->SQL语句(ORM)]        【经常使用】
    ├── tests.py        [单元测试,不要动]
    ├── views.py        [视图函数,do_login]               【经常使用】
	└── templates(可能有)[如果前后端不分离的话,放html模板文件]
# views.py

from django.shortcuts import render
from django.shortcuts import HttpResponse


def login(request):
    return HttpResponse("登录页面")
# urls.py

from django.contrib import admin
from django.urls import path
from django.shortcuts import HttpResponse
from web.views import login


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

二、初识视图函数

# urls.py

from django.contrib import admin
from django.urls import path
from web.views import login


urlpatterns = [
    path('admin/', admin.site.urls),
    path('login/', login),
]
# views.py

from django.shortcuts import render
from django.shortcuts import HttpResponse


def login(request):
  
    # ...例如:用户名、密码  -> 数据库校验
  
    return HttpResponse("登录页面")
  • request是什么?用户请求相关的所有内容。

    去request中获取用户提交的数据等信息。

  • 中间,业务逻辑操作。

  • 返回值,返回的什么体现用户浏览器的行为不同。

    • return HttpResponse("登录页面")

    • return render(request, "login.html")(更常见)

      # views.py
      
      from django.shortcuts import render
      from django.shortcuts import HttpResponse
      
      
      def login(request):
          return render(request, "login.html")
      
    • return redirect("https://www.baidu.com")

如果开发中用到了return render(request, "login.html") 寻找HTML模板:

  • 根目录下的templates中找【优先】

    TEMPLATES = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            'DIRS': [os.path.join(BASE_DIR, 'templates')],
            'APP_DIRS': True,
            'OPTIONS': {
                'context_processors': [
                    'django.template.context_processors.debug',
                    'django.template.context_processors.request',
                    'django.contrib.auth.context_processors.auth',
                    'django.contrib.messages.context_processors.messages',
                ],
            },
        },
    ]
    
  • 根据app的注册顺序,逐一去每个app目录下templates文件夹中寻找【如果上面的没有,就去app里找】【推荐,除公用的属于哪个app的放在哪个中】

    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        "web.apps.WebConfig"
    ]
    

    单独app的模板,在app中写; 公共的就在最外层的templates中写HTML模板。

三、初识模板

web框架中都要用到模板的语法,用看的值是动态的。

def user_list(request):
    # 1.数据库获取所有的用户列表
    data = ["武沛齐", "李立权", "张弛"]

    mapping = {"name": "武沛齐", "age": 19, "size": 18}

    # 2.打开文件并读取内容
    # 3.模板的渲染 -> 文本替换
    return render(request, "user_list.html", {"message": "标题来了", "data_list": data, "xx": mapping})
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>{{ message }}</h1>
<ul>
    {% for item in data_list %}
        <li>{{ item }}</li>
    {% endfor %}
</ul>
  
# 不支持<a>{{ data_list[0] }}</a>这种写法
<a>{{ data_list.0 }}</a>
<a>{{ data_list.1 }}</a>
<a>{{ data_list.2 }}</a>

<p>{{ xx.name }}</p>
<p>{{ xx.age }}</p>
<p>{{ xx.size }}</p>
<ul>
    {% for item in xx.keys %}
        <li>{{ item }}</li>
    {% endfor %}
</ul>

<hr/>

<ul>
    {% for item in xx.values %}
        <li>{{ item }}</li>
    {% endfor %}
</ul>

<hr/>
<ul>
    {% for k,v in xx.items %}
        <li>{{ k }}   {{ v }}</li>
    {% endfor %}
</ul>

</body>
</html>

四、号码列表案例

  • URL访问
  • 去数据库获取号码列表
  • 页面上展示
# urls.py

from django.contrib import admin
from django.urls import path
from django.shortcuts import HttpResponse
from web import views


urlpatterns = [
    path('admin/', admin.site.urls),
    path('login/', views.login),
    path('user_list/', views.user_list),
    path('phone/list/', views.phone_list),
]
# views.py

def phone_list(request):
    # 1.获取数据
    queryset = [
        {"id":1, 'phone':"18611168611", 'city':"北京"},
        {"id":2, 'phone':"18611168612", 'city':"上海"},
        {"id":3, 'phone':"18611168613", 'city':"广州"},
        {"id":4, 'phone':"18611168615", 'city':"山西"},
    ]
  
    # 2.通过页面渲染返回给用户(表格)
    return render(request, "phone_list.html", {"data": queryset})

五、静态文件处理

图片、css、js等。

  • 静态文件放在app目录下 static 文件夹中

  • 页面中使用

    {% load static %}
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" href="{% static 'bootstrap-3.4.1/css/bootstrap.min.css' %}">
    </head>
    <body>
    <div class="container">
        <h1>号码列表</h1>
    	...
        <script src="{% static 'jquery-3.6.0.min.js' %}"></script>
        <script src="{% static 'bootstrap-3.4.1/js/bootstrap.min.js' %}"></script>
    </div>
    </body>
    </html>
    

六、登录跳转案例

image-20240624214821646

  • 移除

    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',
    ]
    
  • 生成token

    <div class="login-box">
        <h2>用户登录</h2>
        <form method="post" action="/login/">
            {% csrf_token %}
            <div class="form-group">
                <label>用户名</label>
                <input type="text" class="form-control" placeholder="请输入用户名" name="user">
            </div>
            <div class="form-group">
                <label>密码</label>
                <input type="password" class="form-control" placeholder="请输入密码" name="pwd">
            </div>
            <button type="submit" class="btn btn-primary">提 交</button>
            <span style="color: red;">{{ error }}</span>
        </form>
    </div>