Django 资源 与 知识 Django中自建脚本并使用Django环境 model中的save()方法说明 filter()用法
2018/11/06 Chenxin

资料说明
Django基础入门 http://www.liujiangblog.com/blog/36/ 版本2.1.3
Django晋级教程 http://www.liujiangblog.com/course/django/2 版本1.11.6 其中的"综合篇"里有不少是实际项目会碰到的问题.实战里有个开源的CMDB.
Django官方教程 https://docs.djangoproject.com/zh-hans/2.1/ 已经出了中文版(但还有很多地方没有翻译好) 版本:最新
HTML语法
https://www.cnblogs.com/wanglisong/p/6924886.html
http://www.w3school.com.cn/html/html_jianjie.asp
Django基础指令
创建Django项目,然后创建应用
python manage.py startapp polls
写好对应的模型,admin.py,视图,然后生成DB
python manage.py makemigrations
python manage.py migrate
创建Django的admin账户
python manage.py createsuperuser

Django模板语法
2018/12/04
参考
http://www.runoob.com/django/django-template.html
说明
模板不是html语法的概念,是Django专有的概念.
html本身不支持继承,但Django的模板有继承的概念.
模板对外键的使用,过滤,请参考运维portal系统中的相关代码"monitor.html".
Django 模板标签
if/else 标签
基本语法格式如下:
{% if condition %}
... display
{% endif %}
或者:
{% if condition1 %}
... display 1
{% elif condition2 %}
... display 2
{% else %}
... display 3
{% endif %}
根据条件判断是否输出。if/else 支持嵌套。
{% if %} 标签接受 and , or 或者 not 关键字来对多个变量做判断 ,或者对变量取反( not ),例如:
{% if athlete_list and coach_list %}
athletes 和 coaches 变量都是可用的。
{% endif %}
for 标签
{% for %} 允许我们在一个序列上迭代。
循环语法是 for X in Y 。
每一次循环中,模板系统会渲染在 {% for %} 和 {% endfor %} 之间的所有内容。
例如,给定一个运动员列表 athlete_list 变量,我们可以使用下面的代码来显示这个列表:

    {% for athlete in athlete_list %}
  • {{ athlete.name }}
  • {% endfor %}
给标签增加一个 reversed 使得该列表被反向迭代: {% for athlete in athlete_list reversed %} ... {% endfor %} 可以嵌套使用 {% for %} 标签: {% for athlete in athlete_list %} {{ athlete.name }}
    {% for sport in athlete.sports_played %}
  • {{ sport }}
  • {% endfor %}
{% endfor %} ifequal/ifnotequal 标签 {% ifequal %} 标签比较两个值,当他们相等时,显示在 {% ifequal %} 和 {% endifequal %} 之中所有的值。 下面的例子比较两个模板变量 user 和 currentuser : {% ifequal user currentuser %} Welcome! {% endifequal %} 和 {% if %} 类似, {% ifequal %} 支持可选的 {% else%} 标签: {% ifequal section 'sitenews' %} Site News {% else %} No News Here {% endifequal %} 注释标签 Django 注释使用 {# #}。 {# 这是一个注释 #} 过滤器 模板过滤器可以在变量被显示前修改它,过滤器使用管道字符,如下所示: {{ name|lower }} 意思为 {{ name }} 变量被过滤器 lower 处理后,大写转换为小写。 过滤管道可以被套接,即一个过滤器管道的输出又可以作为下一个管道的输入: {{ my_list|first|upper }} 以上实例将第一个元素并将其转化为大写。 有些过滤器有参数。 过滤器的参数跟随冒号之后并且总是以双引号包含。 例如: {{ bio|truncatewords:"30" }} 这个将显示变量 bio 的前30个词。 其他过滤器: addslashes : 添加反斜杠到任何反斜杠、单引号或者双引号前面。 date : 按指定的格式字符串参数格式化 date 或者 datetime 对象,实例:{{ pub_date|date:"F j, Y" }} length : 返回变量的长度。 include 标签 {% include %} 标签允许在模板中包含其它的模板的内容。 这个例子都包含了 nav.html 模板: {% include "nav.html" %} 模板继承 模板可以用继承的方式来实现复用。接下来我们先创建之前项目的 templates 目录中添加 base.html 文件,代码如下: HelloWorld/templates/base.html 文件代码: 菜鸟教程(runoob.com) Hello World!

菜鸟教程 Django 测试。

{% block mainbody %}

original

{% endblock %} 以上代码中,名为 mainbody 的 block 标签是可以被继承者们替换掉的部分。所有的 {% block %} 标签告诉模板引擎,子模板可以重载这些部分。 如hello.html 继承 base.html,并替换特定 block.hello.html 修改后的代码如下: HelloWorld/templates/hello.html 文件代码: {%extends "base.html" %} #这行说明 hello.html 继承了 base.html 文件 {% block mainbody %} #可以看到,这里相同名字的 block 标签用来替换 base.html 里相应 block。

继承了 base.html 文件

{% endblock %} 重新访问地址 http://127.0.0.1:8000/hello,就会输出"继承了 base.html 文件". Django表单处理知识 参考 http://www.runoob.com/django/django-form.html Django之Form组件的使用 参考 https://docs.djangoproject.com/zh-hans/2.1/topics/forms/ 官网 参考 https://www.cnblogs.com/wupeiqi/articles/6144178.html Django的Form主要具有一下几大功能: * 生成HTML标签 * 验证用户数据(显示错误信息) * HTML Form提交保留上次提交数据 * 初始化页面显示内容 Django中解决Not Found: /favicon.ico报错 参考: https://blog.csdn.net/HHTNAN/article/details/78549561 在对应的html中的head里添加如下内容,将该图片文件指向到固定文件夹. {% load staticfiles %}

django-simple-captcha 验证码(图片验证)插件使用 以及添加动态ajax刷新验证
参考: https://blog.csdn.net/tanzuozhev/article/details/50458688
如果当前验证码看不清,我们可以刷新一下,这个我们用ajax来做。 jango-simple-captcha本身提供了一个刷新页面,/refresh 在captcha/urls.py中:
url(r’refresh/$’, views.captcha_refresh, name=’captcha-refresh’)
这里在我们自己的urls.py中可以不做处理,直接使用 /captcha/refresh/ . views.captcha_refresh 源码:

以下只是源码介绍不用写入自己的代码中

def captcha_refresh(request):
""" Return json with new captcha for ajax refresh request """
if not request.is_ajax(): # 只接受ajax提交
raise Http404
new_key = CaptchaStore.generate_key()
to_json_response = {
'key': new_key,
'image_url': captcha_image_url(new_key),
}
return HttpResponse(json.dumps(to_json_response), content_type='application/json')
通过阅读源代码我们发现, views.captcha_refresh 只接受ajax提交,最后返回 key 和 image_url 的json数据,这里的key就是 hashkey, 需要我们写入id为id_captcha_1的隐藏字段, image_url为验证码图片的新url,这里我们加入ajax刷新,点击验证码图片即可实现刷新,将以下内容添加到login.html 中即可实现点击验证码图片自动刷新自身.

Django项目里自建的脚本通过Django访问DB.自建脚本通过Django来执行.
2019/01/17
一并解决1,2两个报错,参加下方"其他说明"->"3"内容.
以下是分步解决的.
1.报错内容:(没有环境变量DJANGO_SETTINGS_MODULE)
django.core.exceptions.ImproperlyConfigured: Requested setting LOGGING_CONFIG, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.
配置方式为: pycharm右上角,进入"Edit Configrations..."->Python->选择需要单独运行的脚本->配置Environment variables->如下:
PYTHONUNBUFFERED=1;DJANGO_SETTINGS_MODULE=login_regs.settings
其中"DJANGO_SETTINGS_MODULE=login_regs.settings"是额外增加的一行.
2.报错内容
django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.
则需要在该脚本的最上方(第一个import上面)添加如下:
import django
django.setup()
其他说明:
1.新加的脚本(或者是通过python manage.py startapp aliyun_ecs 生成的),无需在setting里配置INSTALLED_APPS.因为这个脚本是单独运行的.
2.该脚本在未启动Django主项目(比如login_regs未run的时候)也是可以自己运行的.
3.也可以只修改脚本文件,一并解决1,2两个报错.解决方法是,在get_ecs_info.py文件(需要运行的独立脚本)的最上面添加如下代码(不需要在pycharm右上角修改"Edit Configrations..."):
import os
import django
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "login_regs.settings") # login_regs是主项目,也就是根目录.
django.setup()

django model中的save()方法 models.Server().save()
2019/01/18
Model.save(force_insert=False, force_update=False, using=DEFAULT_DB_ALIAS, update_fields=None)
一般只需
new_server = models.Server() # Server是在models.py里创建的表格
new_server.save()
id和pk
如果一个model里没有显示声明哪一个字段(field)是主键(即在某个字段里声明primary_key=True),则django会自动生成一个名为id的AutoFields作为主键。model里的主键都有一个别名叫做pk(primary_key的缩写),无论这个主键是自动生成的还是我们指定的。
使用pk和使用主键的名字是一样的效果。
注意1:对于一个要新加入数据库的model实例,在save()执行之前是无法知道它的id的,因为要算数据库中已有多少个本model才能算出它的id值。

b2 = Blog(name='Cheddar Talk', tagline='Thoughts on cheese.')
b2.id # Returns None, because b doesn't have an ID yet.
b2.save()
b2.id # Returns the ID of your new object.
save()到底是执行insert还是update的说明
force_update和force_insert
这两个参数一般较少用到,因为执行save()之后,django默认执行的是UPDATE或者INSERT这两条SQL语句的哪一条,遵循如下算法:
1.如果这个对象已经有主键而且主键的值是True的(即不是None或者空字符串等),就执行UPDATE。
2.如果没有主键或者这条save()不会update任何字段,那么它就INSERT。
只有在某些特定情况下,需要强制save()执行INSERT或UPDATE时才会使force_update=True或force_insert=True(比如我要求能UPDATE就UPDATE,不能我也不取INSERT,那么我就把这个force_update参数设置为True)。
update_fields
用来指定哪些字段需要更新,别的不更新。默认是None,这样所有字段都会更新一遍。有时候字段很多而我们只需要更新很少的字段,可以用这个参数来提高一下效率。注意要给它的是一个可迭代对象(比如list等)。如果给它一个空的可迭代对象,那么就什么都不更新(注意和None不同,如果等于None是更新全部字段)。
一旦update_fields参数不使用默认值None,那么这条save()语句就是强制执行UPDATE的。
product.name = 'Name changed again'
product.save(update_fields=['name'])
objects.filter()用法
2019/01/18
示例
多个filter一起使用(多个过滤条件)
def record_delete(): # 其中Server是DB的一张表

# 删除自动记录且没有添加过备注信息的record.2个filter
models.Server.objects.filter(get_mode_type='自动录入').filter(mark='').delete()
# 删除自动记录,且很久都没有更新过的record(比如大于一周,则说明云平台上已经没有该服务器了)
now_today = datetime.datetime.now()
previously_days = datetime.timedelta(days=2)
interval = now_today - previously_days  # 返回值类似 2019-01-12 15:24:11.531584
models.Server.objects.filter(get_mode_type='自动录入').filter(c_time__lte=interval).delete()    # c_time是DB里的一个字段,__lte是小于等于

使用说明
条件选取querySet的时候,filter表示=,exclude表示!=。如:
host_ip_list = models.Server.objects.exclude(instance_status='stopped').values_list('project_name', 'server_name', 'wan_ip')
querySet.distinct() 去重复
__exact 精确等于 like ‘aaa’ __iexact 精确等于 忽略大小写 ilike ‘aaa’
__contains 包含 like ‘%aaa%’ __icontains 包含 忽略大小写 ilike ‘%aaa%’,但是对于sqlite来说,contains的作用效果等同于icontains。
__gt 大于
__gte 大于等于
__lt 小于
__lte 小于等于
__in 存在于一个list范围内
__startswith 以…开头
__istartswith 以…开头 忽略大小写
__endswith 以…结尾
__iendswith 以…结尾,忽略大小写
__range 在…范围内
__year 日期字段的年份
__month 日期字段的月份
__day 日期字段的日
__isnull=True/False

Django系统计划任务 django-crontab计划任务 自定义命令 三种方式
2019/01/29
参考:
https://www.jianshu.com/p/27f003149090
https://blog.csdn.net/qq_34971175/article/details/79430274
http://wiki.jikexueyuan.com/project/django-chinese-docs-18/6_4_2_Adding-custom-commands.html
直接通过系统cron执行(推荐)

调用aliyun的API/aws的API,将ECS/EC2写入CMDB

19 * * * * export PYTHONIOENCODING='utf-8' && cd /home/admin/django-cmdb/aliyun_ecs/ && /usr/bin/python3 get_aliyun_ecs_info_linux.py
19 * * * * export PYTHONIOENCODING='utf-8' && cd /home/admin/django-cmdb/aws_ec2/ && /usr/bin/python3 get_aws_ec2_info_linux.py
cat get_aliyun_ecs_info_linux.py

因系统编码,以及linux下python3调用的时候发生的一些找不到对应模块等原因,故这个脚本只用于linux. 以下是为了便于python36直接调用本脚本(不通过django-cron和manage.py命令的方式)而加入的.主要为植入当前路径.

import sys
import os
curPath = os.path.abspath(os.path.dirname(file))
rootPath = os.path.split(curPath)[0]
sys.path.append(rootPath)

import django 和 django.setup() 必须放在最上方.否则无法加载配置.就无法使用Django.

import django
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "login_regs.settings")
django.setup()
...
cat signature_auth_py3_linux.py

因系统编码,以及linux下python3调用的时候发生的一些找不到对应模块等原因,故这个脚本只用于linux. 该脚本适用于python3.x版本 本脚本调用的时候可以给一些参数,执行对应的操作

import sys
import os
from six.moves.urllib.parse import quote
from six.moves.urllib.parse import urlencode
import urllib
import base64
import hmac
from hashlib import sha1
import time
import uuid
from optparse import OptionParser
try:
import configparser
except:
from six.moves import configparser
import traceback

公共变量

access_key_id = ''
access_key_secret = ''

定义终端节点地址(服务节点)

handle_server_address = 'https://ecs.aliyuncs.com'
if os.name == 'nt':
CONFIGFILE = os.getcwd() + 'aliyun.ini'
else:
CONFIGFILE = os.getcwd() + '/aliyun.ini'

[Credentials] 是配置文件中的一个章节

CONFIGSECTION = 'Credentials'
cmdlist = '''接口说明请参考线上文档'''
...

django-crontab实现定时任务
安装django-crontab库
这里使用pip安装即可,在终端输入以下命令即可 pip-3.6 install django-crontab
在工程里使用django-crontab
在django项目的settings.py的INSTALLED_APPS添加django-crontab,记得将此添加到自建的所有app的最前面.
django-crontab配置
django-crontab可以定时运行自定义命令和函数两种方式
定时函数
在django项目的settings.py中添加以下命令
CRONJOBS = (
('*/1 * * * *', '你的app名.定时函数所在的py文件名.定时函数名'), # 每一分钟执行一次你的定时函数
('0 0 1 * *', '你的app名.定时函数所在的py文件名.定时函数名', '> 输出文件路径和名称'), # 定时函数输出的内容到指定文件(如果该路径不存在会自动创建)
)
定时命令
CRONJOBS = (
('10 12 * * *', 'django.core.management.call_command', ['要执行的命令']), # 在12点10分执行命令
)
定时任务的操作
python36 manage.py crontab add  添加定时任务 # 当你添加了或者修改的定时任务
python36 manage.py crontab remove 清除定时任务 # 当想删除当前用户所有定时任务
python36 manage.py crontab show 显示定时任务
自定义manage.py运行命令