Django 基础

Django 的路由系统

1、django 处理一个请求的流程

  • django 使用一个 URLconf 模块,默认为 urls.py 文件,可以通过 setting.py 配置文件修改
ROOT_URLCONF = "Day15.urls"  # 默认值
  • django 加载 URLconf 模块并寻找 urlpatterns( django.conf.url.url() 实例的列表)
  • django 依次匹配每一个 url 条目,直到请求的 URL 与第一个条目匹配
  • 一旦一个正则表达式匹配上,Django 将导入并调用给出的视图(一个 python 函数或者是一个基于类的视图)
  • 如果没有匹配到正则表达式,或者如果过程中抛出了一个异常,Django 将调用一个适当的错误处理视图

默认的 urls.py 文件内容如下:

from django.conf.urls import url
from django.contrib import admin


urlpatterns = [
    url(r'^admin/', admin.site.urls),
]

2、url() 方法

url(regex, view, kwargs=None, name=None)​
    # regex:正则表达式
    # view:当正则表达式匹配到后执行的 python 函数或者基于类的视图
    # kwargs:任意数量的关键字参数可以作为一个字典传递给目标视图
    # name:对 URL 进行命名,可以在 django 的任意地方,尤其是模板中进行显式的引用它

3、基本的 urls 对应

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^hello/', views.hello),
]

4、动态路由对应

将 URL 内容的一部分作为参数传递给函数,如分页,当页面有很多的时候,可以使用动态路由对应,不需要写重复的路由对应.

编辑 Day15 目录下的 urls.py 文件

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^hello/', views.hello),

    # 基于位置传递参数,可传递多个
    url(r'^page/(d+)/', views.page),
    
    # 基于名称传递参数,可传递多个
    url(r'^manage/(?P<name>w*)/(?P<nid>d*)/', views.manage),

    # 为路由添加额外的参数
    url(r'^manage1/(?P<name>w*)/', views.manage1, {'nid': 444}),
]

编辑 Day15 目录下的 views.py 文件

from django.shortcuts import HttpResponse


def hello(request):
    return HttpResponse("Hello World")


def page(request, p):
    # urls 中 d+ 匹配的值会传递给 p
    return HttpResponse("page: {}".format(p))


def manage(request, name, nid):
    # urls 中 name 和 nid 匹配到的值会分别传递给 name 和 nid
    return HttpResponse("name: {}<p>id: {}".format(name, nid))


def manage1(request, name, nid):
    # urls 中匹配到的 name 值传递给 name, 而 nid 是始终是固定值 444
    return HttpResponse("name: {}<p>id: {}".format(name, nid))

5、基于 app 的路由映射

首先在项目的 urls.py 中配置:

from django.conf.urls import url, include

urlpatterns = [
    # 通过 app 对路由进行分发,必须在 settings 的 INSTALLED_APPS 中添加 app 名称
    url(r'app01/', include('app01.urls')),
]

编辑 settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01',    # 添加 app01
]

然后在 app01 中创建 urls.py 文件

from django.conf.urls import url
from app01.views import index


urlpatterns = [
    url('^index/', index),
]

最后编辑 views.py 文件

def index(request):
    return HttpResponse("<h3>index web page.</h3>")

访问测试: http://127.0.0.1:8000/app01/index ,正常显示内容为 index web page。

模板

模板其实就是一些嵌套着固定语法的文本,然后将获取到的数据根据语法插入到模板中,最终将信息返回给客户端

在 settings 中指定模板文件的位置

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        # 指定模板的路径, BASE_DIR 为项目的根目录
        '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',
            ],
        },
    },
]

常用方法

{{ item }}
{% for item in item_list %} {{ item }}  {% endfor %}
    {{ forloop.counter }}     // item 的序号(从1开始)
    {{ forloop.counter0 }}    // item 的序号(从0开始)
    {{ forloop.first }}       // item 是否为 list 的第一个元素
    {{ forloop.last }}        // item 是否为 list 的最后一个元素
    {{ forloop.revcounter }}  // item 的序号(反序)
{% if ordered_warranty %}  {% else %} {% endif %}
母板:{% block title %}{% endblock %}
子板:{% extends "base.html" %}
   {% block title %}{% endblock %}
导入:{% include "public.html" %} 帮助方法: {{ item.event_start
|date:"Y-m-d H:i:s"}} {{ bio|truncatewords:"30" }} {{ my_list|first|upper }} {{ name|lower }}
自定义方法:
filter    // 只能传递一个参数,可以作为模板语言的 if 条件
simple_tag  // 支持多个参数,不能作为模板语言的 if

实例1 [取值]:

修改 views.py 中的 index 函数

from django.shortcuts import render

def index(request):
    return render(request,  # 必须参数
                  "index.html",  # 模板文件
                  {
                      "k1": "v1",
                      "k2": [1, 2, 3, 4],
                      "k3": {"name": "wenchong", "age": 10}
                      }  # 给模板传递的值
    )

在 templates 目录中创建 index.html

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <h1>单独获取</h1>
    获取 k1 对应的值: {{ k1 }} <br />
    获取 k2 对应的列表中的第二个元素: {{ k2.1 }} <br />
    获取 k2 对应的列表中的第三个元素: {{ k2.2 }} <br />
    获取 k3 对应的字典中 name 和 age 的值: {{ k3.name }}  {{ k3.age }} <p>

    <h1>循环获取 k2 中的每一个元素: </h1>

    <table border="1">
        <tr>
            <th>列表元素</th>
            <th>从1开始的序号</th>
            <th>从0开始的序号</th>
            <th>是否为第一个元素</th>
            <th>是否为最后一个元素</th>
            <th>从1开始的序号【反序】</th>
            <th>从0开始的序号【反序】</th>
        </tr>
        {% for item in k2 %}
            <tr>
                <td> {{ item }} </td>
                <td> {{ forloop.counter }}  </td>      {# item 的序号(从1开始) #}
                <td> {{ forloop.counter0 }} </td>      {# item 的序号(从0开始) #}
                <td> {{ forloop.first }}    </td>      {# item 是否为第一个元素 #}
                <td> {{ forloop.last }}     </td>      {# item 是否为最后一个元素 #}
                <td> {{ forloop.revcounter }}  </td>   {# item 的序号(从1开始,反序) #}
                <td> {{ forloop.revcounter0 }} </td>   {# item 的序号(从0开始,反序) #}
            </tr>
        {% endfor %}
    </table>

    <h1>if 判断:</h1>
    {% if k1 == "v1" %}
        <h3>v1</h3>
    {% elif k1 == "v2" %}
        <h3>v2</h3>
    {% else %}
        <h3>v3</h3>
    {% endif %}

</body>
</html>

访问页面:

实例2 [母版和子版]

创建母版 base.html

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>测试页面V1</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        .page-header {
            background-color: blue;
            height: 50px;
            text-align: center;
            line-height: 50px;
        }
        .page-content {

        }
        .page-content .left-menu {
            background-color: aqua;
            height: 500px;
            width: 200px;
            float: left;

        }
        .page-content .left-menu ul li {
            list-style-type: none;
            width:100%;
            height:50px;
            background-color: aqua;
            border-bottom: 1px solid ;
            line-height: 50px;
        }
        .page-content .right-content {
            float: left;
        }

    </style>
</head>
<body>

    <div class="page-header">
        <h1>这里是不变化的开头部分</h1>
    </div>
    <div class="page-content">
        <div class="left-menu">
            <ul>
                <li><a href="/app01/index"> 首页</a></li>
                <li><a href="/app01/menu1"> 菜单一</a></li>
                <li><a href="/app01/menu2"> 菜单二</a></li>
                <li><a href="/app01/menu3"> 菜单三</a></li>
                <li><a href="/app01/menu4"> 菜单四</a></li>
            </ul>
        </div>
        <div class="right-content">
            {% block content %}{% endblock %}
        </div>
    </div>

</body>
</html>

创建子版:

# 分别创建下面 5 个 html 文件
### index.html
{%  extends "base.html" %}

{% block content %}
    <h1>这里是首页</h1>
{% endblock %}


### page1.html

{% extends "base.html" %}

{% block content %}
    这个是菜单二的页面
{% endblock %}


### page2.html

{% extends "base.html" %}

{% block content %}
    这个是菜单三的页面
{% endblock %}


### page3.html

{% extends "base.html" %}

{% block content %}
    这个是菜单四的页面
{% endblock %}


### page4.html

{% extends "base.html" %}

{% block content %}
    这个是菜单一的页面
{% endblock %}

编辑 app01/views.py:

def index(request):
    return render(request,  "index.html")


def menu(request, id):
    return render(request, "page{}.html".format(id))

编辑 app01/urls.py:

from django.conf.urls import url
from app01.views import index, menu


urlpatterns = [
    url('^index/', index),
    url('^menu(d)+/', menu),
]

访问页面:

http://127.0.0.1:8000/app01/index,并点击菜单,会发现只有内容部分变化,其他部分均不发生变化。

 实例3 [导入公共标签]

当一段代码需要在多个页面中重复利用时,可以使用导入 include 导入

创建公共代码 public.html:

<h1>这是公共代码块</h1>

修改 index.html 页面

{%  extends "base.html" %}

{% block content %}
    <h1>这里是首页</h1>
    
    {#导入 public.html 的内容#}
    {% include "public.html" %}
    
{% endblock %}

访问页面 http://127.0.0.1:8000/app01/index

实例4 [自定义 simple_tag 和 filter]

1、在 app01 目录下创建 templatetags 目录

** 目录名称必须为 templatetags,app01 在 settings 中已经添加。

2、在 templatetags 下创建 custom.py 文件,名称可自定义

# /user/bin/env python
__author__ = 'wenchong'


from django import template

# 变量名必须为 register
register = template.Library()


@register.simple_tag
def my_simple_tag(v1, v2, v3):
    return v1+v2+v3

# 无参数的 filter
@register.filter
def my_filter(num):
    return int(num) + 100


# 有参数的 filter
@register.filter
def filter_add(value, arg):
    return int(value) + int(arg)

3、修改 views.py

def tags(request):
    return render(request, "tags.html")

4、创建 tags.html

{#加载自定义方法#}
{% load custom %}

{#直接调用 filter#}
调用无参数的filter: {{ 1|my_filter }} <br />
调用带参数的filter: {{ 1|filter_add:100 }} <br />

调用 my_simple_tag: {% my_simple_tag 1 2 3 %}  <br />

{% if 1|my_filter == 101 %}
    原始数字为 1
{% endif %}

5、访问页面

http://127.0.0.1:8000/app01/tags

静态文件

web 请求时会有很多的静态文件,需要放在指定的目录中供下载,比如 js,css,imgs 文件

1、在项目目录下创建 statics 目录,目录名可自定义

2、在 settings 中配置静态文件路径

# 页面调用静态文件的前缀
STATIC_URL = '/static/'
# 静态文件存放路径
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'statics'),
)

 AJAX

AJAX = 异步 JavaScript 和 XML。

AJAX 是一种用于创建快速动态网页的技术。

通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。

传统的网页(不使用 AJAX)如果需要更新内容,必需重载整个网页面。

通常使用 AJAX 的场景:

  • 用户注册时,通过 AJAX 检查用户名是否存在
  • 用户登录时,检查用户名密码是否正确
  • 删除数据时,通过 AJAX 把 ID 发送给后端服务器,后端服务器在数据库中删除,前段页面通过 JS 删除,页面不用重新加载

实现步骤:

1、配置静态文件目录

2、在静态文件目录 statics 中上传 jquery 文件

3、创建 login.html 文件

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <div>
        <div id="message" style="color: red"></div>
        用户名:<input type="text" id="username" /> <br />
        密码:<input type="password" id="password" /> <br />
        <input type="button" value="登陆" onclick="login()">
    </div>

    <script type="application/javascript" src="/static/jquery-1.7.1.min.js"></script>
    <script>
        function login(){
            $.ajax({
                url: "/app01/login/", {# ajax 请求的 URL #}
                type: "POST",       {# 指定 ajax 请求的访问为 post #}
                dataType: "json",   {# 指定 ajax 返回的数据为 json 格式,默认为 str #}
                {# data 为 ajax 向 URL 发送的数据 #}
                data: {"username": $("#username").val(), "password": $("#password").val()},
                success: function(data){
                    {# 当用户名密码正确时,跳转到 https://www.baidu.com, 否则提示消息 #}
                    if(data.status) {
                        location.href = "https://www.baidu.com";
                    }
                    else{
                        $("#message").text(data.msg)
                    }
                }
            })

        }
    </script>
</body>
</html>

编辑 views.py

import json

def login(request):
    result = {"status": False, "msg": None}
    if request.method == "POST":
        username = request.POST.get("username", None)
        password = request.POST.get("password", None)
if username == "wenchong" and password == "123":
            result["status"] = True
        else:
            result["msg"] = "用户名或密码错误!"
        return HttpResponse(json.dumps(result))
    return render(request, "login.html")

编辑 urls.py

from app01.views import login


urlpatterns = [
    url('^login/', login),
]

访问页面

http://127.0.0.1:8000/app01/login

Model 的简单使用

1、在 settings 中 INSTALLED_APPS 添加 app01

2、创建数据库表

from django.db import models

class UserInfo(models.Model):
    # 创建数据库表 UserInfo,表中有 username 和 password 两列
    username = models.CharField(max_length=64)
    password = models.CharField(max_length=64)

3、同步数据库

python3.5 manage.py makemigrations
python3.5 manage.py migrate

# 创建超级用户
python3.5 manage.py createsuperuser

4、在 admin 中注册 UserInfo 表,编辑 admin.py

from django.contrib import admin
from app01 import models

# 将 UserInfo 表的管理添加到后台 admin
admin.site.register(models.UserInfo)

5、访问页面添加用户名

6、修改 views 中的 login 函数

import json
# 导入 UserInfo
from app01.models import UserInfo
def login(request):
    result = {"status": False, "msg": None}
    if request.method == "POST":
        username = request.POST.get("username", None)
        password = request.POST.get("password", None)
        
        # 调用数据库检查用户名和密码是否正确
        if UserInfo.objects.filter(username=username, password=password):
        # if username == "wenchong" and password == "123":
            result["status"] = True
        else:
            result["msg"] = "用户名或密码错误!"
        return HttpResponse(json.dumps(result))
    return render(request, "login.html"
原文地址:https://www.cnblogs.com/wenchong/p/6241248.html