蓝鲸简单入门

1.前言

本文示例效果可参考3.1处的配置完后浏览器访问,输入用户名和密码,点击设备管理,即可查看效果。

2. 建议:对以下知识点有一些了解并能简单应用

2.1 python:python官方中文文档

2.2 django:The Django Book

2.3 前端知识(除了常见的HTML/CSS/JQuery,还需了解Mako):mako官网

2.4 gitlab:Git思维导图

3.准备

3.1 搭建蓝鲸社区版:单机蓝鲸平台或多机版蓝鲸部署 或参考官方安装文档

若不想自己搭建,直接使用已搭建好的,需在本地配置hosts文件后访问。

       例:用notepad++打开C:\Windows\System32\drivers\etc\hosts,添加以下内容、保存                  

                    172.16.44.104 paas.blueking.com 
                    172.16.44.104 cmdb.blueking.com 
                    172.16.44.104 job.blueking.com 
                    172.16.44.104 bknetwork.blueking.com

       打开浏览器,输入相应的账号密码(admin/hjMRN1L4bt)即可访问。

3.2 基于Pycharm搭建Python本地开发环境,完成HelloWorld

官方文档

3.3 提示

3.3.1 若是自己在本地另外安装Python环境时,版本需与framework代码里requirements.txt中版本一致。’

3.3.2 pycharm社区版不支持django,专业版才支持,下载时注意下的是什么版本。

3.3.3 在继续后面的步骤前,没有敲HelloWorld的伙伴请确认以下提到的内容,若有哪项有问题,请参考准备工作:有可访问的社区版蓝鲸;已有安装、配置好的Python环境;在Python环境能导入django包;配置的数据库可通信;pycharm项目配置均配置OK;本地git和gitlab可通信;在我的应用中有自己新建的应用,没有请新建。tips:社区版的蓝鲸可直接使用已搭建好的(详见3.1)可不用自己搭gitlab,直接使用已搭好的,让伙伴帮忙创个git账号,自己再登录gitlab网页新建project。

4.编写简单的CRUD

4.1 前期

4.1.1配置:

4.1.1.1 修改conf目录下的default.py

                                    APP_ID 为创建应用后得到的应用 ID
                                    APP_TOKEN 为创建应用后得到的应用 TOKEN
                                    BK_PAAS_HOST 为3.1中提到的在hosts文件里配置的要访问的社区版PaaS平台域名

4.1.1.2 数据库配置:

 创建本地数据库,数据库名字为应用ID;测试环境和正式数据库创建(本例中开发测试环境正式环境用同一个数据库),并分别配置好文件:
      开发环境:settings_devlopment.py
      测试环境:settings_testing.py(HOST 为社区版 mysql 服务所在的内网 IP,如不知道是哪台可在社区版安装目录下的 install.config 查看,或者执行 echo $MYSQL_IP 查看)
      正式环境:settings_production.py

4.1.2 项目:若不想新建project可在刚刚的HelloWorldd的project中直接继续写

若想再熟悉可以另外重新新建project导入framework代码,更改配置,编写简单的CRUD。参考基于PyCharm熟悉Django开发来配置,跟着该链接做到3.3步骤,3.4开始不用。

4.1.3 应用:不管有没有新建project都可以在自带的home_application应用中编写

若想新建应用:需在终端输入python manage.py startapp app_id_name(注意:习惯上app_id_name就是你在新建应用中新建的应用名)

4.2 model

4.2.1 编写model

本文在作者自己新建的应用里的models.py文件中编写model(没有新建应用的伙伴则在home_application应用的models.py中编写,后续类似情况不再特地说明)。本文实例的models.py代码地址。读者可试着自己设计不同的model,不一定和示例一模一样。

# !/usr/bin/env python
# encoding:utf8
from django.db import models


class ServerDevice(models.Model):
    server_device_choice = (
        ('offline', u'下线'),
        ('online', u'上线'),
        ('to_be_online', u'待上线'),
        ('test_server', u'测试'),
    )

    """
    服务器设备
    """
    # 定义一个名称字段,blank没有设置默认为False不能为空,且unique=True必须唯一
    name = models.CharField(u'主机名称', max_length=100, unique=True)
    # 定义SN编号字段, blank=True可以为空
    sn = models.CharField(u'SN号', max_length=200, blank=True)
    # 公网IP字段,可以为空
    public_ip = models.CharField(u'外网IP', max_length=200, blank=True)
    # 私网IP,可以为空
    private_ip = models.CharField(u'内网IP', max_length=200, blank=True)
    # 定义mac地址字段
    mac = models.CharField(u'MAC地址', max_length=200, blank=True)
    # 定义操作系统字段
    os = models.CharField(u'操作系统', max_length=200, blank=True)
    # 定义磁盘信息字段
    disk = models.CharField(u'磁盘', max_length=200, blank=True)
    # 定义内存信息字段
    mem = models.CharField(u'内存', max_length=200, blank=True)
    # 定义CPU信息字段
    cpu = models.CharField(u'CPU', max_length=200, blank=True)
    # 机器状态,默认都为在线状态
    status = models.CharField(max_length=10, choices=server_device_choice, default=u'下线')
    # 定义备注字段
    memo = models.CharField(u'备注', max_length=200, blank=True)

    def __unicode__(self):
        return self.name

    class Meta:
        db_table = 'server_device'


4.2.2 激活model

编写完model需告知django激活它,把app添加到setting文件(在蓝鲸开发框架中在conf文件夹下的default.py中)的已安装应用列表,可按Ctrl+shift+f 输入"INSTALLED_APPS=(" 搜索。是元组,在最后记得追加英文的逗号(,)否则识别不到。

4.2.3 生成migrations(迁移文件)

每次更改models文件后得检查model的改动并保存为一个“migration” : python manage.py makemigrations

4.2.4 执行migrations

执行迁移文件并同步到DB: python manage.py migrate
可以一步完成的动作为什么要分成两步?个人理解:version control。仓库没法直接和DB打交道、通信,把migrations提交到仓库后仓库就知道怎么同步、实施model修改的地方。

4.2.5 新建form.py

在应用名称右键新建form.py文件,本文的form.py文件代码地址。注意应该是 (forms.ModelForm)而不是(forms.Form)。

# -*- coding:utf-8 -*-
from django import forms
from .models import ServerDevice


class ServerDeviceForm(forms.ModelForm):
    class Meta:
        model = ServerDevice
        fields = ('id', 'name', 'sn', 'public_ip', 'private_ip', 'mac', 'os', 'disk', 'mem', 'cpu', 'status', 'memo')

4.3 templates

因为作者是新建的应用,所以在templates目录里也新建了相应的目录,再新建相应的HTML页面。没有新建应用的可在templates下的已有的home_application文件夹中直接新建HTML页面。可在蓝鲸MagicBox-可视化布局通过拖拽形成自己想要的前端页面,可编辑页面的字体内容,点击复制代码,复制到IDE中,在自己要获取值的框添加id。有重复的内容可抽取出来,形成base.html,在其他页面中引用。可参考视频,在右列选择第七讲的“实战开发”。若只是想看怎么生成自定义布局,直接拖到17分处即可。

4.4 url

在定义完model,编写好自己想展示的前端页面后,即可编写urls.py来定义什么URL调用什么视图函数了(也可先编写完views.py后再编写urls.py,无硬性规定,按个人习惯来)。
在项目根目录下的urls.py里添加应用的urls.py文件来指向该应用,例:”url(r’^’, include(‘cmdb.urls’)), ” 注意例子中的cmdb需替换为自己的app名字。是元组,记得在最后追加英文逗号。
然后在应用下的urls.py文件中编写URL相关。
如何进入view:在浏览器输入http://dev.paas.blueking.com:8000/,在项目根目录的urls.py配置的路由根据输入的路径(此例输入的为项目根路径,传入的为空)找到第一个匹配的,此处是cmdb.urls第一个匹配,进入此urls再次逐个匹配并返回第一个匹配到的view

4.5 view

在本文实例中表格里有涉及到分页。在应用右键新建名为templatetags文件夹,再在该文件夹里新建名为pagetag的py文件。

from django.utils.html import format_html
from django import template
register = template.Library()


@register.filter
def kong_upper(val):
    print ('val from template:',val)
    return val.upper()


@register.simple_tag
def circle_page(curr_page,loop_page):
    offset = abs(curr_page - loop_page)
    if offset < 3:
        if curr_page == loop_page:
            page_ele = '
  • %s
  • '%(loop_page,loop_page) else: page_ele = '
  • %s
  • '%(loop_page,loop_page) return format_html(page_ele) else: return ''

    5. CRUD功能

    5.1 get_list?

    5.1.1 URL

    在浏览器输入http://dev.paas.blueking.com:8000/,匹配到并调用get_list这个视图函数。
    下文的类似,不再赘述。

    5.1.2 view

    在该view中查询数据库里ServerDevice所有对象
    把查询到的data分页,每页展示10条,把一共多少条,共多少页
    把需返回给template(此例中为’server_device/index.html’)的数据以类似字典的形式传递

    @csrf_exempt
    def get_list(request):
        server_device_list = ServerDevice.objects.all()
        data = list(server_device_list.values ('id',  'name',  'sn',  'public_ip', 'private_ip', 'mac',  'os',  'disk',   'mem', 'cpu', 'status',  'memo' ) )
        paginator = Paginator(data, 10)  # Show 25 contacts per page
        page = request.GET.get('page')
        print(page)
        try:
            contacts = paginator.page(page)
        except PageNotAnInteger:
            # If page is not an integer, deliver first page.
            contacts = paginator.page(1)
        except EmptyPage:
            # If page is out of range (e.g. 9999), deliver last page of results.
            contacts = paginator.page(paginator.num_pages)
        return render_mako_context(request, 'server_device/index.html', {'data': contacts})
    

    5.1.3 前端展示

    在index.html中遍历从后端获得的data,将其展示出来

    
                                        % for item in data:
                                        
                                            
                                            ${item['id']}
                                            ${item['name']}
                                            ${item['sn']}
                                            ${item['public_ip']}
                                            ${item['private_ip']}
                                            ${item['mac']}
                                            ${item['os']}
                                            ${item['disk']}
                                            ${item['mem']}
                                            ${item['cpu']}
                                            ${item['status']}
                                            ${item['memo']}
    

    5.2 add_server_device?

    5.2.1 view

    在首页的添加右键点击检查,可以看到点击添加按钮会触发发送“add_server_device/”这个URL。在index.html中对应的代码为:查询。下文的功能与此类似,不再贴图出来。

    蓝鲸简单入门_第1张图片

    5.2.2 view

    如果传进的不是post请求(例如get),会重新new一个form,并把这个form传到/server_device/add_server_device.html这个页面里,前端则显示跳转到新增服务器设备这个页面;
    在add_server_device.html这个页面中填了信息点击保存,会再次传入add_server_device这个URL路径,这次是post请求,则会新建一个ServerDeviceForm对象,读取前端传进的值并保存到DB。再在数据库里查询所有并分页,将相关data传到index。

    @csrf_exempt
    def add_server_device(request):
        if request.method == 'POST':
            form = ServerDeviceForm(request.POST)
            print(form.is_valid())
            if form.is_valid():
                # 读取表单返回的值,返回类型为dict
                cleaned_data = form.cleaned_data
                item = ServerDevice()
                item.name = cleaned_data['name']
                item.sn = cleaned_data['sn']
                item.public_ip = cleaned_data['public_ip']
                item.private_ip = cleaned_data['private_ip']
                item.mac = cleaned_data['mac']
                item.os = cleaned_data['os']
                item.disk = cleaned_data['disk']
                item.mem = cleaned_data['mem']
                item.cpu = cleaned_data['cpu']
                item.status = cleaned_data['status']
                item.memo = cleaned_data['memo']
                item.save()
                server_devices = ServerDevice.objects.all()
                data = list(server_devices.values(
                    'id', 'name', 'sn',   'public_ip','private_ip', 'mac', 'os', 'disk', 'mem', 'cpu',  'status', 'memo'))
                paginator = Paginator(data, 10)  # Show 25 contacts per page
                page = request.GET.get('page')
                print(page)
                try:
                    contacts = paginator.page(page)
                except PageNotAnInteger:
                    # If page is not an integer, deliver first page.
                    contacts = paginator.page(1)
                except EmptyPage:
                    # If page is out of range (e.g. 9999), deliver last page of results.
                    contacts = paginator.page(paginator.num_pages)
                print(contacts)
                return render_mako_context(request, '/server_device/index.html', {'data': contacts})
        else:
            form = ServerDeviceForm()
        print (form.errors)
        return render_mako_context(request, '/server_device/add_server_device.html', {'form': form, 'error': form.errors})
    
    

    5.3 delete_server_device?

    5.3.1 新建index.js文件

    在项目static/js/下新建一个js文件,代码地址。在index.html中需引用该js文件:

             <%block name="javascript">
             
             
    

    5.3.2 触发js中的btn_del函数

    在index.html中点击删除(id为btn_del)按钮,触发index.js文件中同名js函数:

    $('#btn_del').click(function () {
        var $chkboxes = $('#tbody').find('input:checked');
        if($chkboxes.length == 0){
            alert('请至少选择一行');
            return false;
        }
        $('#delcfmModel').modal();
        return false;
    });
    

    在该函数中获得选中的行,若没有则弹出提示框:“请至少选择一行”,有的话则弹出id名为delcfmModel的页面(confirm_delete.html)

    5.3.3 弹出confirm_delete.html 确认删除页面

    在该页面中点击确认(id名为confirm_delete)触发index.js文件中同名函数:

    $('#confirm_delete').click(function () {
        var $ids = [];
        var $chkboxes = $('#tbody').find('input:checked');
        if($chkboxes.length == 0){
            alert('请至少选择一行');
            return false;
        }
        //遍历被选中的checkbox
        $($chkboxes).each(function () {
            $ids.push($(this).parent().parent().find('td').eq(1).text());
        });
        var $ids_str = $ids.join(',');
        $.post(site_url+"delete_server_device/",{"ids":$ids_str},function (result) {
            $("#btn_query").trigger("click");
        });
    });
    

    在该函数中遍历选中的id,用逗号分开,以delete_server_device/ 的URL发送异步请求把ids发送到后台,view处理完后调用id名为btn_query的js函数重新查询删除id后的页面。

    5.3.4 view

    @csrf_exempt
    def delete_server_device(request):
        """
        删除服务器设备
        """
        try:
            info = request.POST.get(u'ids')
            print (info)
            ServerDevice.objects.extra(where=['id IN (' + info + ')']).delete()
        except:
            traceback.print_exc()
            raise Http404
        return HttpResponse(json.dumps({'ID': info}), content_type='application/json')
    

    5.4 edit_server_device?

    5.4.1 获得被编辑行的值并传到新弹出的编辑框

    在index.html页面中点击编辑按钮会打开一个id名为myModal的页面(edit.html),获得点击编辑被编辑这行的值并将它们传给那个弹出的编辑页面:

    
    

    5.4.2 获得编辑后的值传到后台

    在edit.html页面中编辑完成后点击提交(id名为edit_server_device),触发js中同名函数:

    $('#edit_server_device').click(function () {
        var id = $('#myModalLabel').attr('text');
        var name = $('#name').val();
        var sn = $('#sn').val();
        var public_ip = $('#public_ip').val();
        var private_ip = $('#private_ip').val();
        var mac = $('#mac').val();
        var os = $('#os').val();
        var disk = $('#disk').val();
        var mem = $('#mem').val();
        var cpu = $('#cpu').val();
        var status = $('#status').val();
        var memo = $('#memo').val();
        var SERVER_DEVICE_INFO_LIST = id + "," + name + "," + sn + "," + public_ip+ "," + private_ip + "," + mac + "," + os + "," + disk + "," + mem + "," + cpu+ "," + status + "," + memo ;
        $.post(site_url+"edit_server_device/",{"SERVER_DEVICE_INFO_LIST":SERVER_DEVICE_INFO_LIST},function (result) {
            $("#btn_query").trigger("click");
        })
    });
    });
    

    该js函数中把刚获取到的值拼成字符串,以edit_server_device/ 的URL发送异步请求把字符串发送到后台,view处理完后把结果传回前端。调用btn_query这个js函数重新查询删除后的页面。

    5.4.3 view

    把传进的str分割,根据id查到对象后重新赋值,保存。再把Python对象调用json.dumps方法转成str以json格式传回前端

    @csrf_exempt
    def edit_server_device(request):
        try:
            info = request.POST.get(u'SERVER_DEVICE_INFO_LIST')
            id, name, sn, public_ip, private_ip, mac, os, disk, mem, cpu, status, memo = info.split(u',')
            server_device_info = ServerDevice.objects.get(id=id)
            server_device_info.name = name
            server_device_info.sn = sn
            server_device_info.public_ip = public_ip
            server_device_info.private_ip = private_ip
            server_device_info.mac = mac
            server_device_info.os = os
            server_device_info.disk = disk
            server_device_info.mem = mem
            server_device_info.cpu = cpu
            server_device_info.status = status
            server_device_info.memo = memo
            server_device_info.save()
        except:
            traceback.print_exc()
            raise Http404
        data = []
        return HttpResponse(json.dumps({'rows': data, 'total': len(data)}, ), content_type='application/json')
    

    5.5 query_server_device?

    在index.html页面中输入要查的内容(查询输入框id名分别为query_private_ip和query_mac),点击查询按钮(id名为btn_query)触发同名js函数。

    由于该函数内容较多,就不截图了,该函数地址。在该函数中获得输入的查询的值并把它们以json格式、query_server_device/ 的URL路径传递。view处理后返回的数据再显示到页面上。

    6.本地访问

    修改本地hosts(C:\Windows\System32\drivers\etc\hosts)文件,添加”127.0.0.1 dev.xxxxxx”(填你在3.1步骤配置的蓝鲸服务器地址,我的是”172.16.44.104 dev.paas.blueking.com”),保存。在pycharm点击绿色的运行按钮,浏览器访问http://dev.paas.blueking.com:8000/,即可看到运行效果。

    7. 部署

    部署前记得push最新的代码到gitlab上。
    在【开发者中心-我的应用】。点击部署、一键部署。
    蓝鲸简单入门_第2张图片
    蓝鲸简单入门_第3张图片

    8.下架应用

    在“我的应用”中选中想下架的应用点进去,在左边点“下架”,即可下架。
    蓝鲸简单入门_第4张图片

    9. 最后

    本文旨在分享作者自己用蓝鲸开发过程中做的笔记来帮助基础较薄弱的伙伴入门蓝鲸,对蓝鲸的开发有个感性上的认识,形成大概的思路,所以有些地方写得不是很详细。本文示例代码有很多没考虑到的地方(譬如判断是否非空,诸如此类),还有很大的完善空间。
    作者水平有限,如有不正之处,欢迎留言吐槽指正。

    你可能感兴趣的:(bk,蓝鲸志云笔记)