如何根据 URL id 使用 Django 创建 URL-Shortener?
How can I create a URL-Shortener using Django based on the URL id?
我正在使用 Django,我只是一个初学者。现在我正在尝试用 Base 62 制作一个 URL 缩短器,所以我在 models.py
中创建了一个 class,它的名字是 URLGenerator
。这是它的代码:
class URLGenerator:
BASE = 62
UPPERCASE_OFFSET = 55
LOWERCASE_OFFSET = 61
DIGIT_OFFSET = 48
def generate_unique_key(self, integer):
"""
Turn an integer [integer] into a base [BASE] number
in string representation
"""
# we won't step into the while if integer is 0
# so we just solve for that case here
if integer == 0:
return '0'
string = ""
remainder: int = 0
while integer > 0:
remainder = integer % self.BASE
string = self._true_chr(remainder) + string
integer = int(integer / self.BASE)
return string
def get_id(self, key):
"""
Turn the base [BASE] number [key] into an integer
"""
int_sum = 0
reversed_key = key[::-1]
for idx, char in enumerate(reversed_key):
int_sum += self._true_ord(char) * int(math.pow(self.BASE, idx))
return int_sum
def _true_ord(self, char):
"""
Turns a digit [char] in character representation
from the number system with base [BASE] into an integer.
"""
if char.isdigit():
return ord(char) - self.DIGIT_OFFSET
elif 'A' <= char <= 'Z':
return ord(char) - self.UPPERCASE_OFFSET
elif 'a' <= char <= 'z':
return ord(char) - self.LOWERCASE_OFFSET
else:
raise ValueError("%s is not a valid character" % char)
def _true_chr(self, integer):
"""
Turns an integer [integer] into digit in base [BASE]
as a character representation.
"""
if integer < 10:
return chr(integer + self.DIGIT_OFFSET)
elif 10 <= integer <= 35:
return chr(integer + self.UPPERCASE_OFFSET)
elif 36 <= integer < 62:
return chr(integer + self.LOWERCASE_OFFSET)
else:
raise ValueError(
"%d is not a valid integer in the range of base %d" % (integer, BASE))
上面class有两个方法很重要。第一个是 generate_unique_key
可以将整数转换为唯一字符串,第二个是 get_id
可以将字符串转换为 int。例如:
id = 1024
generator = URLGenerator()
key = generator.generate_unique_key(id) # key = GW
idx = generator.get_id(key) # idx = 1024
# so the final url should look like this:
# http://localhost:8000/GW
在上面的例子中,实际上 id
是数据库中一条记录的 id
,我想在数据库中保存 URL 时使用它。那么如果用户写 http://127.0.0.1:8000/GW he must be redirected to the main URL which is http://127.0.0.1:8000/1024.
我还有另一个 class,它只有一个字段:
class Url(models.Model):
url_id = models.AutoField(primary_key=True)
def save(self , *args , **kwargs):
pass
但现在我不知道如何在我的URL
class中调用URLGenerator
的方法,然后在[=24]中使用POST
写一个简单的函数=] 查看结果。
我看了一些Whosebug的帖子,也看了一些教程,但是很遗憾,我没能解决这个问题。我将感谢您的帮助和建议。
首先,最好在 Url
模型中添加另一个字段,如下所示:
url_id = models.AutoField(primary_key=True)
为什么我们要保存它?因为在这个问题中,我们将根据数据库中每条记录的 ID 做一个简短的 URL。然后我在 forms.py
中创建一个简单的表单。这是它的代码:
from django.forms import ModelForm, fields
from .models import Url
class URLForm(ModelForm):
class Meta:
model = Url
fields = ['link']
labels = {
'link' : 'Enter link'
}
最后,我的 views.py
中有两个函数。在第一个中,我使用了 POST
方法并编写了一个简单的查询来将数据保存在数据库中:
# Redirect short URL to its original URL, if it's valid
def redirector_view(request):
form = URLForm()
if request.method == "POST":
form = URLForm(request.POST)
if form.is_valid():
link = form.cleaned_data['link']
if("http://" not in link) and ("https://" not in link):
link = "http://" + link
# uid =
new_url_obj = Url(link=link)
new_url_obj.save()
id = new_url_obj.pk
url_generator_obj = URLGenerator()
sh_url = url_generator_obj.generate_unique_key(id)
new_url = f"http://127.0.0.1:8000/url/final/{sh_url}"
json_object = {
"final_url" : new_url
}
return JsonResponse(json_object)
context = {
"form" : form
}
return HttpResponse(context)
第二个函数做的正是我在问题中所说的:
# id = 1024
# generator = URLGenerator()
# key = generator.generate_unique_key(id) # key = GW
# idx = generator.get_id(key)
def final(request , sh_url):
url_generator_obj = URLGenerator()
id = url_generator_obj.get_id(sh_url)
url_details = Url.objects.get(url_id=id)
return redirect(url_details.link)
并且不要忘记在应用程序中添加 urls.py
文件:
from django.urls import path
from . import views
urlpatterns = [
path('', views.redirector_view, name="urlshortner"),
path('final/<str:sh_url>' , views.final , name="final"),
]
现在,如果我向我的数据库添加一个简单的记录,其中只包含一个 URL,它的 pk 将为 1(因为它是我们的第一个对象),然后将 1 添加到此 URL:
http://127.0.0.1:8000/url/final/
您将被重定向到主 URL.
我正在使用 Django,我只是一个初学者。现在我正在尝试用 Base 62 制作一个 URL 缩短器,所以我在 models.py
中创建了一个 class,它的名字是 URLGenerator
。这是它的代码:
class URLGenerator:
BASE = 62
UPPERCASE_OFFSET = 55
LOWERCASE_OFFSET = 61
DIGIT_OFFSET = 48
def generate_unique_key(self, integer):
"""
Turn an integer [integer] into a base [BASE] number
in string representation
"""
# we won't step into the while if integer is 0
# so we just solve for that case here
if integer == 0:
return '0'
string = ""
remainder: int = 0
while integer > 0:
remainder = integer % self.BASE
string = self._true_chr(remainder) + string
integer = int(integer / self.BASE)
return string
def get_id(self, key):
"""
Turn the base [BASE] number [key] into an integer
"""
int_sum = 0
reversed_key = key[::-1]
for idx, char in enumerate(reversed_key):
int_sum += self._true_ord(char) * int(math.pow(self.BASE, idx))
return int_sum
def _true_ord(self, char):
"""
Turns a digit [char] in character representation
from the number system with base [BASE] into an integer.
"""
if char.isdigit():
return ord(char) - self.DIGIT_OFFSET
elif 'A' <= char <= 'Z':
return ord(char) - self.UPPERCASE_OFFSET
elif 'a' <= char <= 'z':
return ord(char) - self.LOWERCASE_OFFSET
else:
raise ValueError("%s is not a valid character" % char)
def _true_chr(self, integer):
"""
Turns an integer [integer] into digit in base [BASE]
as a character representation.
"""
if integer < 10:
return chr(integer + self.DIGIT_OFFSET)
elif 10 <= integer <= 35:
return chr(integer + self.UPPERCASE_OFFSET)
elif 36 <= integer < 62:
return chr(integer + self.LOWERCASE_OFFSET)
else:
raise ValueError(
"%d is not a valid integer in the range of base %d" % (integer, BASE))
上面class有两个方法很重要。第一个是 generate_unique_key
可以将整数转换为唯一字符串,第二个是 get_id
可以将字符串转换为 int。例如:
id = 1024
generator = URLGenerator()
key = generator.generate_unique_key(id) # key = GW
idx = generator.get_id(key) # idx = 1024
# so the final url should look like this:
# http://localhost:8000/GW
在上面的例子中,实际上 id
是数据库中一条记录的 id
,我想在数据库中保存 URL 时使用它。那么如果用户写 http://127.0.0.1:8000/GW he must be redirected to the main URL which is http://127.0.0.1:8000/1024.
我还有另一个 class,它只有一个字段:
class Url(models.Model):
url_id = models.AutoField(primary_key=True)
def save(self , *args , **kwargs):
pass
但现在我不知道如何在我的URL
class中调用URLGenerator
的方法,然后在[=24]中使用POST
写一个简单的函数=] 查看结果。
我看了一些Whosebug的帖子,也看了一些教程,但是很遗憾,我没能解决这个问题。我将感谢您的帮助和建议。
首先,最好在 Url
模型中添加另一个字段,如下所示:
url_id = models.AutoField(primary_key=True)
为什么我们要保存它?因为在这个问题中,我们将根据数据库中每条记录的 ID 做一个简短的 URL。然后我在 forms.py
中创建一个简单的表单。这是它的代码:
from django.forms import ModelForm, fields
from .models import Url
class URLForm(ModelForm):
class Meta:
model = Url
fields = ['link']
labels = {
'link' : 'Enter link'
}
最后,我的 views.py
中有两个函数。在第一个中,我使用了 POST
方法并编写了一个简单的查询来将数据保存在数据库中:
# Redirect short URL to its original URL, if it's valid
def redirector_view(request):
form = URLForm()
if request.method == "POST":
form = URLForm(request.POST)
if form.is_valid():
link = form.cleaned_data['link']
if("http://" not in link) and ("https://" not in link):
link = "http://" + link
# uid =
new_url_obj = Url(link=link)
new_url_obj.save()
id = new_url_obj.pk
url_generator_obj = URLGenerator()
sh_url = url_generator_obj.generate_unique_key(id)
new_url = f"http://127.0.0.1:8000/url/final/{sh_url}"
json_object = {
"final_url" : new_url
}
return JsonResponse(json_object)
context = {
"form" : form
}
return HttpResponse(context)
第二个函数做的正是我在问题中所说的:
# id = 1024
# generator = URLGenerator()
# key = generator.generate_unique_key(id) # key = GW
# idx = generator.get_id(key)
def final(request , sh_url):
url_generator_obj = URLGenerator()
id = url_generator_obj.get_id(sh_url)
url_details = Url.objects.get(url_id=id)
return redirect(url_details.link)
并且不要忘记在应用程序中添加 urls.py
文件:
from django.urls import path
from . import views
urlpatterns = [
path('', views.redirector_view, name="urlshortner"),
path('final/<str:sh_url>' , views.final , name="final"),
]
现在,如果我向我的数据库添加一个简单的记录,其中只包含一个 URL,它的 pk 将为 1(因为它是我们的第一个对象),然后将 1 添加到此 URL: http://127.0.0.1:8000/url/final/ 您将被重定向到主 URL.