1.部署包报错案例:
报错内容:
------STARTING: Migrate Database------
Traceback (most recent call last):
File "manage.py", line 19, in
execute_from_command_line(sys.argv)
File "/cache/.bk/env/lib/python2.7/site-packages/django/core/management/__init__.py", line 354, in execute_from_command_line
utility.execute()
File "/cache/.bk/env/lib/python2.7/site-packages/django/core/management/__init__.py", line 303, in execute
settings.INSTALLED_APPS
File "/cache/.bk/env/lib/python2.7/site-packages/django/conf/__init__.py", line 48, in __getattr__
self._setup(name)
File "/cache/.bk/env/lib/python2.7/site-packages/django/conf/__init__.py", line 44, in _setup
self._wrapped = Settings(settings_module)
File "/cache/.bk/env/lib/python2.7/site-packages/django/conf/__init__.py", line 92, in __init__
mod = importlib.import_module(self.SETTINGS_MODULE)
File "/cache/.bk/env/lib/python2.7/importlib/__init__.py", line 37, in import_module
__import__(name)
File "/data/app/code/settings.py", line 2, in
from conf.default import *
SystemError: NULL result without error in PyObject_Call
------FAILURE: Migrate Database------
[192.168.10.112]20200418-160926 105 [JOB FAILURE]
现象:本地执行migrate正常,部署报错。
产生原因和解决方案:部署的代码包里有.pyc文件,将所有的.pyc文件删除,再进行部署,就不会出现这种问题了。
建议:不要本地打包自己的代码。
2.标准运维,自己开发的js模块同步到静态文件内命令:
python manage.py collectstatic --noinput
3.文件上传单元测试
需要模拟文件流数据
def test_upload_file(self):
import io
data = {
'file': io.StringIO('some initial text datal')
}
r = self.client.post('/api/contract/upload_file/', data=data,
ccontent_type='application/json')
self.assertEqual(r.status_code, 200)
content = json.loads(r.content)
print(content)
self.assertEqual(content['result'], True)
success_data = {
'result': bool,
'code': str,
'message': str,
'data': {}
}
self.judge_assert(content, self.data_reform(success_data))
4.Django的ORM操作之exclude过滤。
exclude(筛选条件1,筛选条件2)
筛选出来的结果为,数据库中,过滤掉同时符合两个筛选条件的那些数据
exclude(筛选条件1).exclude(筛选条件2)
筛选出来的结果为,数据库中,先过滤掉符合筛选条件1的数据,再在一的基础上过滤掉符合筛选条件2的数据,结果为去掉了,至少符合其中一个筛选条件的所有数据
需要注意:不要将第二种的效果误当成第一种的语法实现。
5.代码包部署之数据的初始化。
数据是至关重要的,项目可以不升级,可以延迟部署,但是数据不能丢,不能被污染。我认为初始化的数据需要满足几个条件:
①未存在的数据可以进行更新进去;
②禁止更改数据库源数据;
③尽量初始化的数据是配置数据,不要和客户的数据产生交集;
④数据初始化之前一定要先备份数据,以防出现重大事故。
下面是初始化的数据代码,效果:存在的不更改,不存在的创建。
init.py文件
# -*- coding: utf-8 -*-
default_app_config = 'apps.zabbix.apps.ModulesConfigConfig'
apps.py文件
def app_ready_handler(sender, **kwargs):
from apps.zabbix.models import ModulesConfig, ThresholdConfig, EnvironmentVariable, RequestConfig
from apps.home.models import ConstantInfo
ConstantInfo.init_data()
print("update ConstantInfo")
print("update Modules Config")
ModulesConfig.init_data()
print("update Threshold Config")
ThresholdConfig.init_data()
print("update EnvironmentVariable Config")
EnvironmentVariable.init_data()
print("update Request Config")
RequestConfig.init_data()
class ModulesConfigConfig(AppConfig):
name = 'apps.zabbix'
def ready(self):
post_migrate.connect(app_ready_handler, sender=self)
model.py文件(在这里只展示一个)
# -*- coding: utf-8 -*-
from django.db import models
from .contants import (MODULES, MAX_XX_LEN, MAX_XXX_LEN, REQUEST_METHOD, THRESHOLD_CONFIG, SORT_ORDER, ENV_CONSTANT,
REQUEST_CONSTANT)
from common.log import logger
import json
class ModulesConfig(models.Model):
key = models.CharField(verbose_name=u'zabbix请求内容唯一标志', max_length=MAX_XX_LEN, null=True)
desc = models.CharField(verbose_name=u'描述', max_length=MAX_XXX_LEN, null=True, blank=True)
method = models.CharField(verbose_name=u'zabbix请求method', max_length=MAX_XX_LEN, null=True)
params = models.TextField(verbose_name=u'请求参数配置', null=True)
class Meta:
app_label = "zabbix"
db_table = "zabbix_module_config"
verbose_name = u"模块请求配置"
@classmethod
def init_data(cls):
try:
for item in MODULES:
cls.objects.get_or_create(
key=item['key'],
defaults={
"key": item['key'],
"desc": item['desc'],
"method": item['method'],
"params": json.dumps(item["config"])
}
)
except Exception as e:
logger.error('init module config fail, errror: %s' % e)
注意:Django的ORM操作之get_or_create方法,当你设置的key字段,获取到了,则不会更新,当没有的时候,才会创建,避免更改源数据。
6.Django ORM之分组
分组展示字段加入外键表的其它字段
以外键名称+__+外键表的相关字段
如:c_type__name
def home_info(self, request):
contract_queryset = Contract.objects.exclude(is_delete=1)
# 除归档的合同
contract_count_list = contract_queryset.exclude(status=3)
# 过期的合同数
expire_count_list = contract_queryset.filter(status=2)
# 合同过期折线图
month = request.GET.get('number', 12)
expire_data = []
x_data = list(reversed([x for x in self.date_range(num=int(month))]))
for item in x_data:
task_record = expire_count_list.filter(create_time__year=int(item[0:4]),
create_time__month=int(item[-2:]))
expire_data.append(len(task_record))
# 合同类型饼状图数量统计
c_type_data = contract_queryset.values('c_type', 'c_type__name').annotate(count=Count('c_type')).all()
# 合同类型正常财产统计
normal_cost = contract_queryset.values('c_type', 'c_type__name').annotate(cost=Sum('cost'))
return Response({
'contract_count': contract_count_list.count(),
'expire_count': expire_count_list.count(),
'expire_data': {
'data': expire_data,
'xAxis': x_data
},
'c_type_data': c_type_data,
'normal_cost': normal_cost
})