首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何根据URL id使用Django创建URL-Shortener?

如何根据URL id使用Django创建URL-Shortener?
EN

Stack Overflow用户
提问于 2021-08-28 20:04:33
回答 1查看 262关注 0票数 0

我正在和Django一起工作,我还只是个初学者。现在我正在尝试用Base62做一个网址缩写程序,所以我在models.py中创建了一个类,它的名字是URLGenerator。下面是它的代码:

代码语言:javascript
复制
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))

上面的类有两个重要的方法。第一个是可以将整数转换为唯一字符串的generate_unique_key,第二个是可以将字符串转换为整数的get_id。例如,类似这样的内容:

代码语言:javascript
复制
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,我想在将其保存到数据库时使用它。然后,如果用户编写了http://127.0.0.1:8000/GW,他必须被重定向到主URL,即http://127.0.0.1:8000/1024

我还有一个只有一个字段的类:

代码语言:javascript
复制
class Url(models.Model):
   url_id = models.AutoField(primary_key=True)

   def save(self , *args , **kwargs):
      pass

但是现在我不知道如何在我的URL类中调用URLGenerator的方法,然后在views.py中使用POST编写一个简单的函数来查看结果。

我已经阅读了StackOverflow中的一些帖子,也阅读了一些教程,但不幸的是,我无法解决这个问题。我将非常感谢您的帮助和建议。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-08-30 17:44:43

首先,最好将另一个字段添加到Url模型中,如下所示:

代码语言:javascript
复制
url_id = models.AutoField(primary_key=True)

为什么我们要保存它呢?因为在这个问题中,我们将根据数据库中每条记录的id创建一个简短的URL。然后,我用forms.py创建了一个简单的表单。下面是它的代码:

代码语言:javascript
复制
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方法,并编写了一个简单的查询来将数据保存到数据库中:

代码语言:javascript
复制
# 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)

第二个函数做了我在问题中说过的事情:

代码语言:javascript
复制
# 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文件:

代码语言:javascript
复制
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。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68967770

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档