Django搭建计算资源展示系统

       计算资源展示系统是关于系统部门的对于虚拟机资源和物理机资源展示的一个系统,虚拟机的统计数据是使用Vcenter中导出的数据进行跑脚本计算后得出的数据,在将Excel上传后,在前端页面进行展示。

      系统介绍:

      首先对接了公司的ldap,使用django自带模块对接ldap来进行认证,这里面使用了中间件,上传功能使用了chunk先把文件写入内存中,然后在从内存写入磁盘之中。下载使用了StreamingHttpResponse来进行文件的下载。对于上传的Excel表展示方面目前使用xlrd这个模块来读取然后使用html的table来进行展示,在项目上线的时候,使用了uwsgi来进行启动,然后使用nginx进行反向代理。

      功能介绍:

      这是首页的页面

       

       这是我做的首页,有点丑,不过毕竟第一个自己做的小系统凑合的看,上面展示的是我上传Excel时的名字,旁边按钮是用来进行下载的,做了一个登陆界面,对接是公司的ldap的服务器。

     

       电子表格的部分是使用xlrd读取Excel,使用html的table来呈现的

       

这个我使用脚本跑Vcenter导出的表,计算出各部门的虚拟机使用比例,前面部门没有进行了截取。下面还有一部分物理机的使用详情表,是按部门来分配的的,由于有一些敏感信息,那张详细的表我就不贴出了。这里注意的是Excel表对于合并单元格的读取时,需要进行merge,才能知道这个合并单元格详细的信息。

        下载功能:

        

    这是下载Excel表格的展示。

    项目的不足的地方:对于上传的表没有删除的功能,对于上传Excel表格有明确的格式规定,其他格式的Excel表格无法读取,所以准备找一些读取Excel的插件来进行实现。

    代码总结:

    在代码的方面,对于ldap中间件那部分的代码不是很熟悉,在对接的过程中总是不断的出错,在大神同事帮我debug后才进行了调通,特此感谢。下面是代码的自我解析:

    上传文件代码:

    views.py中: 

def upload_excel(request):
    if request.method == "GET":
        return render(request,'create_article.html')
    elif request.method == "POST":
        bbs_generater=utils.ArticleGen(request) #这里调用ArticleGen这个方法来进行数据的整理
        res =bbs_generater.create()
        return  HttpResponseRedirect('/etable')
class ArticleGen(object):
    def __init__(self,request):
        self.request = request

      def parse_data(self):
        print self.request.POST.get('target'),'---->'
        form_data={
        'excel_name':self.request.POST.get('excel_name'),
        'target':self.request.POST.get('target'),
        'excel_file':''}


        return  form_data
    def create(self):
        self.data = self.parse_data()
        bbs_obj=models.Excel(**self.data)
        bbs_obj.save()
        filename =handle_upload_file(self.request, self.request.FILES['excel_file'])
        bbs_obj.excel_file = 'excel/%s' % filename
        bbs_obj.file_name = filename
        bbs_obj.save()
        return bbs_obj
def handle_upload_file(request,file_obj):   #上传文件时,先把文件写入内存,然后在从内存写入文件
    upload_dir = '%s/%s/excel/' %(settings.BASE_DIR,settings.FileUploadDir)
    #if not os.path.isdir(upload_dir):
    #    os.mkdir(upload_dir)
    print '-->',dir(file_obj)
    with open('%s/%s' %(upload_dir,file_obj.name),'wb') as destination :
        for chunk in file_obj.chunks():
            destination.write(chunk)
    return   file_obj.name
由于这个项目是根据我之前练习的bbs项目来的,所以有些命名是使用bbs的。

    信息的展示:

      在首页是使用循环打印django的标签来进行表的全部的展示

       views.py

      

def index(request):

    excels = models.Excel.objects.all()

    return render(request,'index.html',{
        'excels':excels
    })
这是index.html
    <div class="col-lg-8">
                {% block content-left %}
             {% for excel in excels %}
                <div class="blog-box row" >
                    <div class="excel_file col-md-8">
                      <a href="{% url 'excel' excel.id %}" target="_blank"> {{ excel.excel_name}}</a>
                      <a href="{% url 'download' excel.id %}"><i class="fa fa-download "></i></a>
                    </div>
                   </div>
            {% endfor %}
            {% endblock %}
        </div>
     单个表的展示:

views.py中

def excel(request,excel_id):
    excel_obj=models.Excel.objects.get(id=excel_id)
    if excel_obj.target == "detail":

        try:
            excel_obj = models.Excel.objects.get(id=excel_id)#这里是我手撸的根据特定表写的excel表的读取,代码有些丑
            print excel_obj.excel_file
            excel_name=excel_obj.excel_name
            file_name=excel_obj.excel_file
            workbook=xlrd.open_workbook(r'{}/{}'.format(settings.FileUploadDir, file_name))
            print excel_obj.target
            sheet2 = workbook.sheet_by_index(1)
            merge_list=sheet2.merged_cells   #这里是读取合并的单元格,部门下有许多物理机,所以这个合并单元格特别的长
            data_list=list()
            for i in merge_list[::-1]:   #单元格的list,Excel先把部门做出来,一个合并单元格由四个元组组成(row,row + 长,col,col + 长)
                bumen=sheet2.cell_value(i[0],i[2])
                row_end=i[1] - 1
                span = row_end -i[0]+1
                print span,'span'
                for p in range(i[0],i[1]):
                    row_data = sheet2.row_values(p)
                    data_list.append({'location':p,
                               'row_data':row_data,
                               'row_start':i[0],
                               'span':span,
                               'row_end':row_end,
                               'bumen':bumen,})
            sheet1 = workbook.sheet_by_index(0)
            row_number=sheet1.nrows
            row_list=range(row_number)
            row_list.pop(0)
            sum_list=list()
            for d in row_list:
                row_data=sheet1.row_values(d)
                sum_list.append({
                         'row_data':row_data })


        except ObjectDoesNotExist,e:
            err_msg = str(e)
        return render(request,'article.html',{
                      'data_list':data_list,
                      'excel_name':excel_name,
                      'sum_list':sum_list,
                      'sheet1_name': sheet1.name,
                      'sheet2_name': sheet2.name})

  下载功能的代码:

   

def download(request,excel_id=id):


    excel_obj = models.Excel.objects.get(id=excel_id)
    file_name=excel_obj.excel_file #文件的路径和名称
    def file_iterator(file_name,chunk_size=512):
        with open('{}/{}'.format(settings.FileUploadDir, file_name)) as f:
            while True:
                c = f.read(chunk_size)
                if c:
                    yield c
                else:
                    break

    the_file_name = "{}".format(file_name)
    reponse = StreamingHttpResponse(file_iterator(the_file_name))
    reponse['Content-Type']='application/octet-stream'
    reponse['Content-Disposition']='attachment;filename="{}"'.format(the_file_name)

    return reponse
    
   好像忘记贴models.py 的代码了,里面有些参数大家不太懂
   class Excel(models.Model):
    id = models.AutoField(primary_key=True)
    excel_name=models.CharField(max_length=200)
    excel_file=models.FileField(upload_to="statics/excel")
    target = models.CharField(max_length=200)

下面开始最麻烦的ldap认证的方面的代码:

单独在一个app下面,写一个django的middlewares.py的文件

from django.conf import settings
from django.contrib.auth import REDIRECT_FIELD_NAME
from django.http import HttpResponseRedirect

class LoginRequiredMiddleware(object):
    """Middleware to redirect to the login page if the user isn't authenticated

    After successful authentication the user is redirected back to the page he
    initially wanted to access.
    """
    def process_request(self, request):
        # allow access to the login url
        # if request.path == settings.LOGIN_URL:
        #     return
        if request.path in (settings.LOGIN_URL, '/etable'): #/etable是我的根
            print 'setting',settings.LOGIN_URL
            return

        if '/etable/static' in request.path:
            print request.path
            return

        # redirect to the login url if the user isn't authenticated
        if not request.user.is_authenticated():

            if request.path not in (settings.LOGIN_URL,
                                    settings.LOGIN_REDIRECT_URL):
                return HttpResponseRedirect('%s?%s=%s' % (settings.LOGIN_URL,
                                                          REDIRECT_FIELD_NAME,
                                                          request.path))
            else:
                return HttpResponseRedirect(settings.LOGIN_URL)
 然后在settings.py中还要进行一下配置,下面是配置文件:

 

from django_auth_ldap.config import LDAPSearch, GroupOfNamesType, GroupOfUniqueNamesType,LDAPSearchUnion #这里要进行包的引入
reload(sys)
sys.setdefaultencoding('utf8')

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
STATIC_URL = '/etable/static/'
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, "statics"),
)
STATIC_ROOT ='/statics/'
FileUploadDir =  os.path.join(BASE_DIR, 'statics')


LOGIN_REDIRECT_URL = '/etable'
LOGIN_URL = '/etable/accounts/login/'
AUTHENTICATION_BACKENDS = (
'django_auth_ldap.backend.LDAPBackend',
'django.contrib.auth.backends.ModelBackend',
)

AUTH_LDAP_SERVER_URI = "ldap服务器的地址"

AUTH_LDAP_BIND_DN = "CN=gitlab-ldap01,OU=Service Account,DC=creditease,DC=corp"
AUTH_LDAP_BIND_PASSWORD = " "
OU = unicode('OU=宜信公司,OU=HABROOT,DC=creditease,DC=corp', 'utf8')
AUTH_LDAP_USER_SEARCH = LDAPSearch(OU, ldap.SCOPE_SUBTREE, "(&(objectClass=user)(userPrincipalName=%(user)s))")
#将账号的姓、名、邮件地址保存到django的auth_user表中,在admin后台可以看到
AUTH_LDAP_USER_ATTR_MAP = {
"first_name": "givenName",
"last_name": "sn",
"email": "mail"
}
TH_LDAP_ALWAYS_UPDATE_USER = True #是否同步LDAP修改
MIDDLEWARE_CLASSES = (
    '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',
    'django.middleware.security.SecurityMiddleware',
    'bbs.middlewares.LoginRequiredMiddleware',#这里一定要记住bbs.middlewares.LoginRequiredMiddleware一定要放到最后,之前我把这个放在最前面session中一直
                                                                                没有显示连接。
LOGIN_REDIRECT_URL = '/etable'
LOGIN_URL = '/etable/accounts/login/'

这里还要使用yum安装ldap,还有pip安django-auth-ldap才可以使用。

项目的部署:

    项目部署这里我确实是个小白,这里使用uwsgi+nginx的反向代理来完成的,nginx以前还学过奈何忘的快,只记住了一个大概,确实一点都不会配了。下面讲一下我的配置吧:

     先使用pip安装uwsgi然后写配置文件,uwsgi.ini

[uwsgi]
#uid = nginx  
#gid = nginx 
chdir = /opt/showexcel  #你的项目的目录
virtualenv = env

wsgi-file = /opt/showexcel/s10day12bbs/s10day12bbs/wsgi.py  #项目的wsgi文件
#module = s10day12bbs.wsgi 
#master = true  
#processes = 10 
workers = 20
listen = 128
uwsgi-socket = 127.0.0.1:9001  #启动的端口
#socket = /tmp/rasperry.sock 
pidfile = /var/run/uwsgi.pid
vacuum = true
enable-threads = true
buffer-size = 32768

reload-mercy = 8
max-requests = 5000
#limit-as = 256  
harakiri = 60
debug = true
plugin = python  #这里得注意一下,让uwsgi使用python
daemonize = /var/log/rasp_uwsgi.log

对于nginx的配置:
    location /etable {
           uwsgi_pass uwsgi://etable;
           include uwsgi_params;
           uwsgi_param SCRIPT_NAME "";
       }                                
     

        到此,我这个项目已经介绍完了,这也是我第一个自己设计,独自完成的项目,其中学到了不少东西,从前端的table展示,到后端的代码的实现,都让我明白了,当自己做一件事情和练习一个项目的时候时,这两个还是不一样的,考虑的方面不一样,最后难免我的文章中会有错误,理解有误的地方,欢迎指出。

      




        

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值