Django 进阶篇二

规范

确立规范的好处

  1. 代码可读性高
  2. 方便代码的定位极其查找
  3. 为以后代码扩容带来便利

场景:

在多个APP的场景下,单个app的URL函数功能较多的时候,我们可以通过以下方法来解决。

把Views写成模块的方式并且为不同的功能进行不同的划分,并且在Templates中使用同样规则,如下图:

我根据不同的html然后创建不同的函数,命名和templates模板目录一样这样非常方便找到,这个页面中的函数在哪里。

  

设置路由的时候就得导入相应的函数(下面的函数是在app01中的url,通过object的url转发过来):

from cmdb.views import account
from cmdb.views import home
from cmdb.views import asset

urlpatterns = [

    #账户操作登录登出
    url(r‘^login/$‘, account.login),
    url(r‘^logout/$‘, account.logout),

    #home操作
    url(r‘^index/$‘, home.index),

    #资产信息操作
    url(r‘^lists/$‘, asset.lists),
    url(r‘^save_hostinfo/$‘, asset.save_hostinfo),
    url(r‘^del_hostinfo/$‘, asset.del_hostinfo),
    url(r‘^add/$‘, asset.add),

    #default url
    url(r‘‘, account.login),

]

还有就是Form也是有很多文件的所以我们也要单独创建下!

2、静态文件导入优化

看下面的一种情况首先咱们在导入静态的css和js的时候是怎么导入的?

{#CSS#}
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <link rel="stylesheet"  href="/static/plugins/bootstrap/css/bootstrap.min.css"/>
    <link rel="stylesheet"  href="/static/plugins/font-awesome/css/font-awesome.min.css"/>
    <link rel="stylesheet"  href="/static/css/commons.css"/>
    <link rel="stylesheet"  href="/static/css/account.css"/>
</head>

{#JS#}
<script src=‘/static/js/jquery-1.8.2.min.js‘></script>
<script src=‘/static/js/valid.js‘></script>

这个static在哪里设置的呢?在object的settings里设置的:

########### 静态文件路径 ##########
STATIC_URL = ‘/static/‘
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, ‘static‘),
)

########### 增加‘django.core.context_processors.static‘, 在OPTIONS里

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‘,
                ‘django.core.context_processors.static‘,
            ],
        },
    },
]"""
## 查看原理 ##
‘django.core.context_processors.static‘,

def static(request):
    """
    Adds static-related context variables to the context.
    """
    return {‘STATIC_URL‘: settings.STATIC_URL} # 这里和模板语言一样返回一个字典
"""

那如果以后想把static目录改成content怎么改呢?难道要在每个html中去修改路径吗?这样如果html文件多的话会疯的,所以我们可以这么修改:

如果想修改路径的话直接修改:settings里的   STATIC_URL = ‘/static/‘ 指定新的目录即可

{#CSS#}
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <link rel="stylesheet"  href="{{ STATIC_URL }}plugins/bootstrap/css/bootstrap.min.css"/>
    <link rel="stylesheet"  href="{{ STATIC_URL }}plugins/font-awesome/css/font-awesome.min.css"/>
    <link rel="stylesheet"  href="{{ STATIC_URL }}css/commons.css"/>
    <link rel="stylesheet"  href="{{ STATIC_URL }}css/account.css"/>
    <link rel="stylesheet"  href="{{ STATIC_URL }}css/login.css"/>
</head>

{#JS#}
<script src=‘{{ STATIC_URL }}js/jquery-2.1.4.min.js‘></script>
<script src=‘{{ STATIC_URL }}js/valid.js‘></script>

上面的原理就类似模板语言的渲染一样!

效果如下:

2、还有一种方式

通过simple_tag 的方式进行导入,他不需要注册option即可。注意里面的路径

{#在顶部load 一个staticfiles#}
{% load staticfiles %}

{#在底部使用#}
<script src=‘{% static "js/jquery-2.1.4.min.js" %}‘></script>

Form

首先看下,在Form里和Views里都使用了account很容易造成混乱所以我们可以使用别名来区分:

from cmdb.forms import account as AccountForm

1、Form保存用户输入内容

场景:比如有一个html页面有很多的input标签需要你输入,但是如果你输入错误了,数据已经提交过去了,所有数据需要你在写一遍是不是非常不人性化,看下面的例子:(我故意输入错误了密码之后信息还需要我在重新写一遍)

代码如下:

def login(request):
    obj = AccountForm.LoginForm()
    if request.method == ‘POST‘:
        # 获取用户输入
        login_form = AccountForm.LoginForm(request.POST)
        # 判断用户输入是否合法
        if login_form.is_valid():      # 如果用户输入是合法的
            username = request.POST.get(‘username‘)
            password = request.POST.get(‘password‘)
            user_info_list = models.UserInfo.objects.all()
            for i in user_info_list:
                if username == i.email and password == i.passwords:
                    request.session[‘auth_user‘] = username
                    return redirect(‘/index/‘)
            else:
                return render(request,‘account/login.html‘,{‘model‘: obj,‘backend_autherror‘:‘用户名或密码错误‘})
        else:
            error_msg = login_form.errors.as_data()
            return render(request,‘account/login.html‘,{‘model‘: obj,‘errors‘:error_msg})

    # 如果登录成功,写入session,跳转index
    return render(request, ‘account/login.html‘, {‘model‘: obj})

优化的方法就是:

def login(request):
    # 获取用户输入
    login_form = AccountForm.LoginForm(request.POST)
    if request.method == ‘POST‘:
        # 判断用户输入是否合法
        if login_form.is_valid():     # 如果用户输入是合法的
            username = request.POST.get(‘username‘)
            password = request.POST.get(‘password‘)
            user_info_list = models.UserInfo.objects.all()
            for i in user_info_list:
                if username == i.email and password == i.passwords:
                    request.session[‘auth_user‘] = username
                    return redirect(‘/index/‘)
            else:
                return render(request,‘account/login.html‘,{‘model‘: login_form,‘backend_autherror‘:‘用户名或密码错误‘})
        else:
            error_msg = login_form.errors.as_data()
            return render(request,‘account/login.html‘,{‘model‘: login_form,‘errors‘:error_msg})

    # 如果登录成功,写入session,跳转index
    return render(request, ‘account/login.html‘, {‘model‘: login_form})

这里,我们把用户输入的请求封装到Form表单给用户返回回去了!这样用户提交的数据就可以在同样返回给用户!

那有人会问如果不是POST的时候,你也这样返回没有问题吗?没有问题的,没有POST请求的话request.POST是空所以不影响。

效果如下:

2、Form错误信息

Form的错误信息有3种,咱们常用的就是:

error_msg = errors

error_msg = errors.as_json()             # 返回字符串形式

error_msg.as_ul很少用

在返回Ajax的请求的时候能返回对象吗?是不可以的!(咱们一般返回字符串,或字符串类型的字典),但是咱们可以通过error_msg = errors.as_json()来返回!

print type(login_form.errors)
print type(login_form.errors.as_json())

结果:

<class ‘django.forms.utils.ErrorDict‘>
<type ‘str‘>

第一个是ErrorDict是Django定义的一个类,第二个是字符串。

看下第一个错误信息,他是一个字典我们可以通过字典来取他的值看下(Views):

error_msg = login_form.errors.as_data()
print (error_msg[‘username‘][0])
print (error_msg[‘password‘][0])

然后当我们发送数据的时候通下面的方式发送在模板中我们不能通过字典的方式取值只能通过“.”的方式取字典的值怎么办?所以就需要simple_tag来做了:

return render(request,‘account/login.html‘,{‘model‘: login_form,‘errors‘:error_msg})
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from django import template
from django.utils.safestring import mark_safe
from django.template.base import resolve_variable, Node, TemplateSyntaxError

register = template.Library()

@register.simple_tag
def error_message(arg):
    if arg:
        return arg[0][0]
    else:
        return ‘‘

2、对于Ajax来说

error_msg = login_form.errors.as_json()
print error_msg,type(error_msg)
{"username": [{"message": "\u90ae\u7bb1\u8d26\u6237\u4e0d\u80fd\u4e3a\u7a7a", "code": "required"}],
"password": [{"message": "\u5bc6\u7801\u4e0d\u80fd\u4e3a\u7a7a", "code": "required"}]}
<type ‘str‘>

之前说过的在error的时候有多个错误,我们默认取第0个就可以了,我们在通过Ajax发送登录认证的时候可以通过返回来的错误信息通过js来进行显示即可!

3、FormSelect更新

看下面的这种情况基本的通过form生成select标签

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>可更新下拉菜单</h1>
    <p>{{ obj.host }}</p>
</body>
</html>

form

class ImportForm(forms.Form):
    HOST_TYPE_LIST = (
        (1,‘物理机‘),
        (2,‘虚拟机‘),
    )

    host = forms.IntegerField(
        widget=forms.Select(choices=HOST_TYPE_LIST)
    )

views

def index(request):
    obj = HomeForm.ImportForm(request.POST)
    return render(request,‘home/index.html‘,{‘obj‘:obj})

这个select里面的选项是写死的就两个选项他是静态的,如果这个是业务线的话,是动态的话,我有新增了一个业务线怎么办?先拿文件举例,后面会跟上从数据库取数据的例子!

有一个文件db_admin通过json.dumps生成的文本

[[1, "物理机"], [2, "虚拟机"]]

然后在form里调用,html&views不变,修改下form

class ImportForm(forms.Form):

    f = open(‘db_admin‘)
    data = f.read()
    data_tuple = json.loads(data)
    f.close()
    host = forms.IntegerField(
        widget=forms.Select(choices=data_tuple)
    )

现在是动态生成了,我现在在db_admin里在增加一个字段

[[1, "物理机"], [2, "虚拟机"],[3, "云主机"]]

当我在刷新页面的时候发现:为什么我添加的‘[3,"云主机"]’,为什么没有出现呢?我已经添加了!

当类在被调用的时候首先执行的是类的构造方法:__init__方法,每当调用类的实例化的时候他都执行!所以我们可以给form定义一个form方法。

class ImportForm(forms.Form):
    f = open(‘db_admin‘)
    data = f.read()
    data_tuple = json.loads(data)
    f.close()
    host = forms.IntegerField(
        widget=forms.Select(choices=data_tuple)
    )

    def __init__(self, *args, **kwargs):
        super(ImportForm, self).__init__(*args, **kwargs)
        f = open(‘db_admin‘)
        data = f.read()
        data_tuple = json.loads(data)
        f.close()

        # 通过self.fields找到host这个静态字段的.wideget.choices属性并重新给他赋值!
        self.fields[‘host‘].widget.choices = data_tuple

优化:

class ImportForm(forms.Form):
    host = forms.IntegerField(
        widget=forms.Select()  # 这里默认是空值,每一次我们使用的时候通过__init__进行赋值
    )

    def __init__(self, *args, **kwargs):
        super(ImportForm, self).__init__(*args, **kwargs) #执行当前类的父类的构造方法(__init__)
        f = open(‘db_admin‘)
        data = f.read()
        data_tuple = json.loads(data)
        f.close()

        # 通过self.fields找到host这个静态字段的.wideget.choices属性并重新给他赋值!
        self.fields[‘host‘].widget.choices = data_tuple
时间: 2024-12-09 23:29:34

Django 进阶篇二的相关文章

Django进阶篇(二)

中间件 解析 django 中的中间件(middleware),在django中,中间件其实就是一个类,在请求到来和结束后, django会根据自己的规则在合适的时机执行中间件中相应的方法. 在django项目的settings模块中,有一个 MIDDLEWARE_CLASSES 变量, 其中每一个元素就是一个中间件, MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.

python Django 进阶篇

Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM.模型绑定.模板引擎.缓存.Session等诸多功能. 1,基本配置 一.创建django程序 终端命令:django-admin startproject sitename IDE 创建Django程序时,本质上都是自动执行上述命令 其他常用命令: python manage.py runserver 0.0.0.0 python manage.py

Python之路【第十七篇】Django进阶篇

规范 确立规范的好处: 代码可读性高 方便代码的定位极其查找 为以后代码扩容带来便利 场景: 在多个APP的场景下,单个app的URL函数功能较多的时候,我们可以通过以下方法来解决. 把Views写成模块的方式并且为不同的功能进行不同的划分,并且在Templates中使用同样规则,如下图: 我根据不同的html然后创建不同的函数,命名和templates模板目录一样这样非常方便找到,这个页面中的函数在哪里. 设置路由的时候就得导入相应的函数(下面的函数是在app01中的url,通过object的

Web框架django进阶篇

分页 一.Django内置分页 from django.shortcuts import render from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger L = [] for i in range(999): L.append(i) # 模拟数据库 生成数据 def index(request): current_page = request.GET.get('page') # 通过get请求得到当前

Django进阶(二)

Template 之前的好多HTML文件中都包含类似"{{ }}"."{% %}",其实他们都是模板语言,模板本质上是HTML,但是夹杂了一些变量和标签,可以方便后端的修改前端的内容,而前端代码不用改变. 模板的组成:HTML代码+逻辑控制代码 变量:(使用双大括号来引用变量)语法格式:       {{var_name}} 实例一 新建项目:mysit,app名:blog,实现功能:后台获取当前年月日,返回给页面显示 mysit/mysit/urls.py fro

Django进阶篇

一.Django框架 1.MVC框架 MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑.数据.界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑.MVC被独特的发展起来用于映射传统的输入.处理和输出功能在一个逻辑的图形化用户界面的结构中.具有耦合性低.重用性高.生命周期成本低等优点. 2.Django的MTV框

Python之路【第十六篇续】Django进阶篇

Django请求生命周期 首先:对于所有的web框架来说本质就是一个socket服务端,浏览器是socket客户端 路由系统 在Django的urls中我们可以根据一个URL对应一个函数名来定义路由规则如下: from cmdb import views urlpatterns = [ url(r'^login/$', views.login), url(r'^index/$', views.index), url(r'^lists/$', views.lists), url(r'^add/$'

Django 进阶篇

>>> models.UserInfo.objects.create(username='jason',pwd='56789',user_type_id='1') <UserInfo: UserInfo object> >>> models.UserInfo.objects.values() <QuerySet [{'pwd': '56789', 'username': 'jason', 'id': 1, 'user_type_id': 1}]>

大话重构读书笔记——进阶篇二

我们怎样拥抱变化 软件系统应对快速变化的终极利器,是以领域模型为核心建立的软件架构. 软件发展的基本特征就是变更,不论是源于需求的变更还是源于技术的变更. 运用领域模型,通过图形化的分析,可以让我们快速掌握真实世界的规律,进而指导软件的设计与开发.领域模型是联系真实世界与软件世界的枢纽,首先通过对真实世界的分析绘制领域模型,然后照着领域模型设计软件,就可以保证真实世界与软件世界的对应关系. 一般来说,领域模型是基于用户业务领域知识的分析,这些领域知识源于用户对软件系统的业务需求,却超越了业务需求