Django 之基础续

1.路由系统之动态路由

前言:还记得之前的分页效果,这个如何实现呢?答案就是动态路由。

url(r'^detail/(d+)/$', views.detail),
url(r'^detail2/(d+)/(d+)/$', views.detail2),
url(r'^detail3/(?P<p1>d+)/(?P<x2>d+)/', views.detail3),#设定后端对应处理的函数分别为p1,x2

 通过正则表达式,匹配包含数字的URL,交给views中的函数处理,对应的函数要传送匹配的参数,具体如下:

def detail(request, nid):
    print(nid)
    return HttpResponse('OK')
# detail2(1,2)
def detail2(request, xid, nnid):
    print(xid,nnid)
    return HttpResponse('OK')

# detail3(x2=234,p1=123)
def detail3(request, p1, x2):
    print(p1,x2)
    return HttpResponse('OK')

那么分页是怎么实现的呢,代码如下:

##url
url(r'^index/(d+)/', views.index),
##view
#生成一个包含字典的列表
USER_LIST = []
for item in range(94):
    temp = {"id": item, 'username':'jason'+str(item), 'email': 'email' + str(item)}
    USER_LIST.append(temp)
def index1(request, page):
    print(page)
    # 1,0-9
    # 2,10-19
    # 3,20-29
    page = int(page)
    start = (page - 1) * 10
    end = page * 10
    user_list = USER_LIST[start:end]#设定每页取值的范围
    # return HttpResponse('OK')
    return render(request, 'index1.html', {'user_list': user_list})
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <table>
        <tr>
            <td>ID</td>
            <td>用户名</td>
            <td>详细</td>
        </tr>
        {% for item in user_list %}
            <tr>
                <td>{{ item.id }}</td>
                <td>{{ item.username }}</td>
                <td>
                    <a href="/cmdb/detail/{{ item.id }}">查看详细</a>
                </td>
            </tr>
        {% endfor %}
    </table>

</body>
</html>
index1.html

效果如下:

2.自定义标签方法

自定义标签目录名必须为templatetags, 否则django无法识别,分两步实现:

1、创建指定文件,名称不能改 templatetags
2、创建任意 .py 文件,如:mytag.py
# 必须不变
register = template.Library()
			
# 创建函数
@register.filter
def f1(value):
      value + "666"
3、在html模版的头部执行

{% load mytag %}
4、html代码
 k1 = 'VVV'
   {{k1}}    => vvv
   {{k1|f1}} => vvv666 ##将k1通过管道传给f1函数
5、 settings.py 中注册app

如下图:

from django import template
from django.utils.safestring import mark_safe
from django.template.base import Node,TemplateSyntaxError

register = template.Library()
@register.filter
def f1(value,arg):
    ##filter只能传一个参数,可以使用html中的if语句
    return value + "666" + arg

@register.simple_tag
def f2(s1,s2,s3,s4):
    #simplet tag 不支持html中的if语句
    return s1 + s2 + s3 + s4

@register.filter
def f3(value):
    ##filter支持if语句
    if value == 'VVV':
        return True
    return False
mytag
def template(request):
    return render(request,
                  'template.html',
                  {'k1':'vvvv','k2':[11,22,33],'k3':{'nid':12,'name':'Jason'}}
Views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    {% load mytag %}
</head>
<body>
    {{ k1 }}
    {{ k1.1 }}
    {{ k1.name }}
    {% for item in k2 %}
        <p>{{ item }},{{ forloop.counter }},{{ forloop.counter0 }},{{ forloop.revcounter }},{{ forloop.first }},{{ forloop.last }}</p>
    {% endfor %}
    {% if k1 == 'vvvv' %}
        <h1>V1</h1>
    {% elif k1 == 'v2' %}
        <h1>V2</h1>
    {% else %}
        <h1>7777</h1>
    {% endif %}
    {% if k1|f3 %}
    <h1>True</h1>
    {% else %}
    <h1>False</h1>
    {% endif %}
    {{ k1 }}
    {{ k1|lower }}
    {{ k1|f1:"jason"}}
    <br>
    {%   f2 1 2 3 4 %}
</body>
</html>
template.html 

 需要注意的tip:

1.filter

   限制:传参
支持:模版语言的 if 条件

2.simple_tag

   不支持:模版语言的 if 条件

 3.模板的继承

首先了解下模板是什么概念?首先已博客园为例:

看下面的图片,在点击首页、精华、候选、新闻、管住、我评、我赞的时候  上面、左侧的红色框体都没有变,变得是中间的内容是怎么实现的呢?就是通过母版来实现的

我们创建一个母版  - 子版去继承母版就可以了,子版里是变化的内容即可。

详见下面的例子

1.母版:layout.html

提别提醒:母版最多允许出现一个母版(可以写多个,但是建议不要写多个)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <link rel="stylesheet" href="..." />
    <style>
        .pg-header{
            height: 48px;
            background-color: cadetblue;
        }
        .pg-body{
            min-height: 500px;
        }
        .pg-body .body-menu{
             20%;
            float: left;
        }
        .pg-body .body-content{
             80%;
            float: left;
        }
        .pg-footer{
            height: 100px;
            background-color: brown;
        }
        .active{
            background-color: aquamarine;
            color: white;
        }
    </style>

    {% block css %}{% endblock %}#子模板替换的部分
</head>
<body>
    <div class="pg-header">
        后台系统V1
    </div>
    <div class="pg-body">
        <div class="body-menu">
            <ul>
                <li><a id="userinfo" href="/web/userinfo">用户管理</a></li>
                <li><a id="assets" href="/web/assets">资产管理</a></li>
            </ul>
        </div>
        <div class="body-content">

            {% block body %}{% endblock %} #此处为子模板替换的部分
        </div>

    </div>
    <div class="pg-footer"></div>
    <script src="xxx"></script>
    {% block js %}{% endblock %}
</body>
</html>

 2.子模板

 需要在HTML头部以如下的方式导入母版,有点类似Python导入模块的方式,extends 集成那个模板   ,在加一个block content 来书写变化的内容。

{% extends '母板html文件名' %}
{% block 名称 %} 
				
					具体子页面的内容...
					
{% endblock %}

 实例如下:

{% extends 'layout.html' %}

{% block css %}
    <style></style>
{% endblock %}

{% block body %}
    <ul>
    {% for item in user_list %}
        <li>{{ item.username }},{{ item.salary }}</li>
    {% endfor %}
    </ul>

{% endblock %}

{% block js %}
    <script>
        document.getElementById('userinfo').className = 'active';
    </script>
{% endblock %}

 3.导入标签

如何在html中导入我们想导入的别人的或定制的标签呢,答案是include方法;

son.html:

<form>
    <input />
    <input />
    <input />
    <input />
</form>

 include.htm:

{% extends 'master/layout.html' %}

{% block body %}
    <table>
        {% for item in assets_list %}
            <tr>
                <td>{{ item.hostname }}</td>
                <td>{{ item.port }}</td>
            </tr>
        {% endfor %}
    </table>

    {% include 'include/son.html' %}
    {% include 'include/son.html' %}
    {% include 'include/son.html' %}
    {% include 'include/son.html' %}
    {% include 'include/son.html' %}
    {% include 'include/son.html' %}
    <h3></h3>

{% endblock %}

{% block js %}
    <script>
        document.getElementById('assets').className = 'active';
    </script>
{% endblock %}

 效果如下:

以后比如某些公共的模块可以使用include的方式导入!很方便

4.Django静态文件配置

把所有的静态都放在static目录下,比如:css、js、imgs、等

配置引入static目录,在settings里,否则无法使用static目录下的静态文件,因为他找不到路径!的需要告诉django

STATIC_URL = '/ff/' #可以自己制定,html引用时要加入此前缀
STATICFILES_DIRS = (
   os.path.join(BASE_DIR,'statics'),
)

 静态文件目录如下:

html引用方式如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/ff/style/style.css">
    {#    然后在模板里,我们也会写一个block,如果子版里有需要使用自己的css样式可以自己定义#}
    {% block css %} {% endblock %}
</head>
<body>
    <div class="header"><h1>LOGO</h1></div>
    <div class="body">
        <div class="menu">左侧菜单</div>
        <div class="content">
            {#可变的子版内容,这个content和class content无关#}
            {% block content %} {% endblock %}
        </div>
    </div>
    {#    公共的js写到母版中,如果某一个模板里使用自己的js,在写一个block即可#}
    {% block js %} {% endblock %}
</body>
</html>

 注:在模板里引入了相应的css和js之后,子版里是默认继承的。如果某个子版想独立使用它自己的js,我们可以通过:{% block css %} {% endblock %}  ||  {% block js %} {% endblock %}来定义!

登录注册实例

1.url

在mysite 这个project下的urls定义路由如下

 url(r'^app01/',include('app01.urls')),

 在cmdb这个app中urls定义路由如下:

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

urlpatterns = [
            url(r'^register/', views.register),
            url(r'^login/',views.login),
    ]

 views函数定义如下:

def login(request):
    return render(request,'login.html')

 html中form表单如何提交的呢?

<form class="form-horizontal" action="/login/" method="post">

提交到在form表单中的action里定义:这里的/login/是URL,当咱们访问URL的时候回给执行咱们定义的函数,前面和后面都要有/  并且使用方法为post

咱们访问的时候是使用的GET方式,当咱们提交的时候使用的是post请求!我们就可以判断!

def login(request):
    #如果是GET请求
    #如果是POST,检查用户输入
    #print request.method 来查看用户是通过什么方式请求的
    #还有个问题:当你POST的时候,会出现问题,现在临时解决方法是:在seetings里注释掉
    '''
    MIDDLEWARE_CLASSES = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    #'django.middleware.csrf.CsrfViewMiddleware',  注释掉这一行
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    ]
    '''
    if request.method == 'POST':
        input_email = request.POST['email']
        input_pwd = request.POST['pwd']
        if input_email == 'jason' and input_pwd == '123':
            #当登录成功后给它跳转,这里需要一个模块from django.shortcuts import redirect
            #成功后跳转到指定网址
            return redirect('http://www.baidu.com')
        else:
            #如果没有成功,需要在页面告诉用户用户名和密码错误.
            return render(request,'login.html',{'status':'用户名或密码错误'})
            #通过模板语言,来在login.html中添加一个status的替换告诉用户<span>{{ status }}</span>

    return render(request,'login.html')
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
    <!--指定告诉ID用高版本的解析-->
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
    <!-- Bootstrap -->
    <!-- 新 Bootstrap 核心 CSS 文件 -->
    <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.4-dist/css/bootstrap.min.css">
</head>
<body>
    <div style=" 200px;">
        <form class="form-horizontal" action="/login/" method="post">
          <div class="form-group">
            <label for="inputEmail3" class="col-sm-2 control-label">Email</label>
            <div class="col-sm-10">
              <input type="email" class="form-control" name="email" placeholder="Email">
            </div>
          </div>
          <div class="form-group">
            <label for="inputPassword3" class="col-sm-2 control-label">Password</label>
            <div class="col-sm-10">
              <input type="password" class="form-control" name="pwd" placeholder="Password">
            </div>
          </div>
          <div class="form-group">
            <div class="col-sm-offset-2 col-sm-10">
              <button type="submit" class="btn btn-default">Sign in</button>
                <span style="color: red;">{{ status }}</span>
            </div>
          </div>
        </form>


    </div>

  <!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
  <script src="/static/js/jquery-2.2.1.min.js"></script>
  <!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
  <script src="/static/plugins/bootstrap-3.3.4-dist/js/bootstrap.min.js"></script>
</body>
</html>
login.html

如何利用JQuery封装的ajax实现提交数据到后台呢,方法如下:

a. 下载Jquery
b. 放置在static目录下
c. setting配置
c. html导入

$.ajax({
   url: '/index/',
   type: 'POST',
   data: {'username': 'alex','password': '123'},
   success: function(data){
      // 当后台return之后,该函数自动执行
      // data就是后台返回的数据
   }
})

 此例子中ajax非Jquery独有,详细说明详见:http://www.cnblogs.com/wupeiqi/articles/5703697.html

原文地址:https://www.cnblogs.com/jasonwang-2016/p/5838673.html