django简单实现短url
一、短url的原理
什么是短url:
简单讲就是把普通正常访问的网址,转换成比较短的网址,例如:https://www.cnblogs.com/angelyan/articles/10667354.html#_label0 转成https://dwz.cn/p8VGVkMt
作用优点:短,字符少,美观,便于发布,传播,突破某些平台限制
原理步骤:
1.浏览器解析DNS,获取域名对应的ip
2.获取ip,发送http请求,获取p8VGVkMt对应的长链接地址
3.http通过301重定向,转到对应的长链接页面
算法原理:
利用数据库自增id,每一次短url获取一个数据库id,将id进行62进制转换,获得一个短码,这样的短码最长8位,最短1位。
二、代码部分
#url路由部分 from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^$', views.index), url(r'^addShortUrl/$', views.addShortUrl), url(r'^restoreUrl/$', views.restoreUrl), url(r'^([A-Za-z0-9]+)/', views.url), ]
#模型表部分 from django.db import models # Create your models here. # 短url表 class ShortUrl(models.Model): id=models.AutoField(primary_key=True) # 短url short_url=models.CharField(max_length=255) # 原始url ori_url = models.TextField() # 短url有效期 period=models.DateTimeField() def __str__(self): return self.short_url
#视图view部分 from django.shortcuts import render,redirect from django.http import HttpResponse,JsonResponse # Create your views here. import re,datetime,time from app01 import models baseList = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' # 10进制转62进制 def changeBase(n,b): # 返回一个包含商和余数的元组(n // b, n % b) x,y = divmod(n,b) print(x,y) if x>0: return changeBase(x,b) + baseList[y] else: return baseList[y] # 利用mysql数据库的自增id生成n,然后转成62进制,再将62进制应对的长url存进mysql,下次访问时查询62进制的短url对应的长url, # 最后重定向301到长url上 def index(request): if request.method=="GET": return render(request, "index.html") def url(request,url): if request.method=="GET": res = models.ShortUrl.objects.filter(short_url=url).first() if not res or not res.ori_url: return HttpResponse("没有此短网址") if time.time()-int(time.mktime(res.period.timetuple()))>0: return HttpResponse("短网址已失效") return redirect(res.ori_url) if request.method=="POST": return HttpResponse("Request error") def addShortUrl(request): if request.is_ajax(): response = {"status": 100, "msg": None} long = request.POST.get('long') period = request.POST.get('period') print(long,period) res=re.search("^(http|https|ftp)\://([a-zA-Z0-9\.\-]+(\:[a-zA-Z0-9\.&%\$\-]+)*@)?" "((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\." "(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\." "(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\." "(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])|" "([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+\.[a-zA-Z]{2,4})(\:[0-9]+)?" "(/[^/][a-zA-Z0-9\.\,\?\'\\/\+&%\$#\=~_\-@]*)*$",long) if not res: response["msg"]="网址错误" response["status"]=101 elif period !="一年期" and period !="长期": response["msg"] = "有效期格式错误" response["status"] = 102 else: date=datetime.datetime.now() if period=="一年期": date = datetime.datetime.now() + datetime.timedelta(days=365) if period=="长期": date = datetime.datetime.now() + datetime.timedelta(days=365*5) res = models.ShortUrl.objects.create(period=date) print(res.id) n=res.id short_url=changeBase(n,62) if short_url=="admin" or short_url=="addShortUrl" or short_url=="restoreUrl": response["msg"] = "请求再转换一次试试" response["status"] = 103 else: models.ShortUrl.objects.filter(id=n).update(short_url=short_url,ori_url=long) response["msg"] = short_url return JsonResponse(response) if request.method == "GET": return HttpResponse("No get method") def restoreUrl(request): if request.is_ajax(): response = {"status": 100, "msg": None} short = request.POST.get('short') res = re.search("^(http|https|ftp)\://([a-zA-Z0-9\.\-]+(\:[a-zA-Z0-9\.&%\$\-]+)*@)?" "((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\." "(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\." "(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\." "(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])|" "([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+\.[a-zA-Z]{2,4})(\:[0-9]+)?" "(/[^/][a-zA-Z0-9\.\,\?\'\\/\+&%\$#\=~_\-@]*)*$", short) if not res or "/" not in short: response["msg"] = "网址错误" response["status"] = 101 else: short_url=short.split("/")[-1] res=models.ShortUrl.objects.filter(short_url=short_url).first() print(res) if not res: response["msg"] = "没有该短网址" response["status"] = 102 else: response["msg"] = res.ori_url return JsonResponse(response)
#模板部分 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.css"> <title>短url</title> </head> <body> <div class="row"> <div class="col-md-6 col-md-offset-3"> <form action="" method="post" id="form"> {% csrf_token %} <h1 style="text-align: center">短url</h1> <hr> <div class="span12"> <div class="tabbable" id="tabs-149852"> <ul class="nav nav-tabs"> <li class="active"> <a href="#panel-24341" data-toggle="tab">缩短网址</a> </li> <li> <a href="#panel-186783" data-toggle="tab">还原网址</a> </li> </ul> <div class="tab-content"> <div class="tab-pane active" id="panel-24341"> <br> <div class="form-group"> <label for="long" class="sr-only">缩短网址</label> <input type="text" class="form-control" id="long" placeholder="缩短网址"> <br> <button type="button" class="btn btn-primary" id="but_add">缩短网址</button> </div> <div class="form-inline"> <p class="form-control-static">有效期:</p> <select class="form-control" id="period"> <option value="一年期">一年期</option> <option value="长期">长期</option> </select> </div> </div> <div class="tab-pane" id="panel-186783"> <br> <form class="form-inline"> <label for="short" class="sr-only">还原网址</label> <input type="text" class="form-control" id="short" placeholder="还原网址"> <br> <button type="button" class="btn btn-primary" id="but_restore">还原网址</button> </form> </div> </div> </div> </div> </form> </div> </div> </body> <script src="/static/js/jquery-3.3.1.js"></script> <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.js"></script> <script> $("#but_add").click(function () { var formdata={"long":$("#long").val(),"period":$("#period").val(),"csrfmiddlewaretoken":"{{ csrf_token }}"} console.log(formdata); $.ajax({ url: "/addShortUrl/", type: "post", data: formdata, success: function (data) { if (data.status == 100) { var a = document.createElement('a'); a.href = location.href+data.msg; alert(a) } else { alert(data.msg); } } }) }); $("#but_restore").click(function () { var formdata={"short":$("#short").val(),"csrfmiddlewaretoken":"{{ csrf_token }}"}; console.log(formdata); $.ajax({ url: "/restoreUrl/", type: "post", data: formdata, success: function (data) { if (data.status == 100) { alert(data.msg); } else { alert(data.msg); } } }) }) </script> </html>
三、效果图