django項目實現應用系統的自動更新


需求:有多個應用系統部署在不同的WINDOWS機器上,應用通過IIS對外發布,並且同一個應用都有在多台機器上面實現負載均衡,每次應用發布更新手工處理不僅效率低,還存在一定的誤操作的風險,為提高工作效率,使用DJANGO發布的站點對各個應用實現自動更新

1、應用系統信息的表結構

models.py

class systeminfo(models.Model):
    id = models.IntegerField(primary_key=True)
    dnsname = models.CharField(max_length=50)
    systemurl = models.CharField(max_length=100)

#用於保存應用系統的域名和應用的UNC路徑(相對於部署DJANGO服務器的UNC),兩個鍵最好聯合唯一,避免重復更新

 

后台數據庫為SQLITE3,SETTINGS.PY的部份配置如下:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}
 

更新數據庫

python manage.py makemigrations

python manage.py migrate

 

2、為了實現系統的自動更新,必須先錄入應用系統的基礎的UNC信息到數據庫

urls.py加入:

url(r'^addsysteminfo/$',views.addsysteminfo,name='addsysteminfo'),

 

views.py寫入addsysteminfo

def addsysteminfo(request):
    if request.method=="POST":
        dnss=request.POST.get("dnsnames")
        urls=request.POST.get("systemurls")

        try:

            addlist=models.systeminfo(dnsname=dnss,systemurl=urls)
            addlist.save()
            return render(request,"addsysteminfo.html",{"login_err":"okay"})
        except Exception:
             return render(request,"addsysteminfo.html",{"login_err":"fail"})
    else:
        return render(request,"addsysteminfo.html",{"login_err":"noset"})

 

前端的addsysteminfo.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form id="loginForm" action="{% url 'addsysteminfo' %}" method="POST"> {% csrf_token %}
系統域名<input type="text" class="form-control" name="dnsnames" placeholder="系統域名"></br>
系統URL<input type="text" class="form-control" name="systemurls" placeholder="系統URL"></br>

<button class="btn btn-success btn-block" type="submit">
                            <b>提交</b>
                        </button>

<h4 ><b>{{ login_err }}</b></h4>
    </form>
</body>
</html>

 

錄入系統信息的界面如下:

應用系統做有負載均衡,多個UNC則錄入多條記錄

 

 

3、實現應用系統自動更新的功能

urls.py添加

url(r'^uploads/$',views.uploads,name='uploads'),

 

views.py寫入該方法,目前只接受上傳.ZIP的更新包

def uploads(request):
    if request.method == "POST":
        dnss=request.POST.get("dns")
        request.encoding="utf-8"
        myFile =request.FILES.get("myfile", None)
        
        if not myFile:
            # returnHttpResponse("no files for upload!")
            return render(request,"uploads.html",{"login_err":"no files"})
        destination = open(os.path.join(".\uploads",myFile.name),'wb+')
        for chunk in myFile.chunks():
            destination.write(chunk)
        destination.close()
        filepath=".\\uploads\\"+myFile.name

        try:
            sourcefiles=dbs2.openfiles(filepath,dnss)
        except Exception:
            return HttpResponse("UPFILE IS OK!,BUT CAN'T UPDATE"+filepath+dnss)


        try:
            #infolist=models.systeminfo.objects.get(dnsname=dnss)
            infolists=models.systeminfo.objects.all().values('systemurl').filter(dnsname=dnss)
            if not len(infolists):
                return HttpResponse("not exists the system "+dnss)
            for dicts in infolists:
                targetfile=dicts['systemurl']
                try:
                    dbs2.copyfiles(str(sourcefiles),str(targetfile))
                except Exception:
                    return HttpResponse("copy files fail")


        except Exception:
            return HttpResponse("not exists the system "+dnss)


        return HttpResponse("OKAY!")
        # return render(request,"uploads.html",{"login_err":"okay"})
    else:
        return render(request,"uploads.html",{"login_err":"noset"})
 

調用了dbs2.py的兩個方法:

openfiles方法解壓文件到指定的目錄,並返回路徑,相當於更新當中源文件夾的路徑

def openfiles(files,dnss):
    nowtime=time.strftime('%Y-%m-%d-%H-%M-%S',time.localtime(time.time()))+""
    z=zipfile.ZipFile(files,'r')
    #dnss=dnss+str(nowtime)
    dnss=str(dnss)+str(nowtime)
    paths="d:\\uploads\\"+dnss
    z.extractall(path=paths)
    #z.extractall(path='.\\uploads\\'+dnss)
    #return dnss
    return paths

 

copyfiles方法:更新應用系統,更新前先備份被更新的文件到指定的目錄

 

def copyfiles(sourceDir, targetDir):
    if sourceDir.find(".svn") > 0:
        return
    for file in os.listdir(sourceDir):
        sourceFile = os.path.join(sourceDir, file)
        targetFile = os.path.join(targetDir, file)
        if os.path.isfile(sourceFile):
            if os.path.exists(targetDir):
                #if os.path.exists(targetFile) and (os.path.getsize(targetFile) != os.path.getsize(sourceFile)):
                if os.path.exists(targetFile):           #如果更新是替換現有的舊文件,則准備備份,並建立好對應的目錄結構,以備還原
                    #nowtime=time.strftime('%Y-%m-%d-%H-%M-%S',time.localtime(time.time()))+""
                    nowtime=time.strftime('%Y-%m-%d-%H-%M',time.localtime(time.time()))+""       

                                                                       #時間精確到分鍾,一次更新如果在幾分鍾內完成,可能備份文件在幾個文件夾內
                    #bak=sourceDir+"bak\\bak"
                    p1=os.path.dirname(sourceFile)        
                    p1=p1[11:]                                           #因為文件解壓在D:\uploads\下,此處減掉前面D:\uploads\路徑的11個字符
                    bak="D:\\appbak\\"+nowtime+"\\"+p1
                    if not os.path.exists(bak):
                        os.makedirs(bak)

                    bakfile=os.path.join(bak,file)
                    # print bakfile
                    open(bakfile,"wb").write(open(targetFile,"rb").read())         #先備份文件
                    open(targetFile, "wb").write(open(sourceFile, "rb").read())
                else:
                    open(targetFile, "wb").write(open(sourceFile, "rb").read())
            if not os.path.exists(targetDir):
                os.makedirs(targetDir)
                if not os.path.exists(targetFile):
                    open(targetFile, "wb").write(open(sourceFile, "rb").read())
        if os.path.isdir(sourceFile):
            First_Directory = False
            copyfiles(sourceFile, targetFile)

 

前端的uploads.html

<!DOCTYPE html>
<html lang="UTF-8">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form enctype="multipart/form-data" action="/uploads/" method="post">
    {% csrf_token %}
   <input type="file" name="myfile" />請上傳.ZIP格式的更新包,目錄結構為雙擊點開.ZIP即為應用的頂級目錄
   <br/>
   <input type="submit" value="更新應用" />
    </br>
    應用域名<input type="text" class="form-control" name="dns" placeholder="應用域名">
    </br>
    <h4 ><b>{{ login_err }}</b></h4><br/><br/>
ZIP范例</br>
<img src="http://www.test.com/zip.jpg"/>
</form>
</body>
</html>

 

此時用戶只需要上傳更新包,並錄入應用的域名,即可完成應用系統的更新

注意:如果目標應用服務器即拷貝文件的目的路徑,如果為LINUX系統,應用服務器可使用SAMBA服務發布共享,比如操作系帳號root,對應新建samba帳號,smbpasswd  -a  roo,密碼可以設置為與操作一致。

另外如果部署DJANGO的服務器為WINDOWS服務器,可在WINDOWS服務器上面建立同名同密碼的root帳號,再用root帳號啟動對應的程序程。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM