Prepare for bulk destinations redirect

This commit is contained in:
grisel-davy 2021-01-02 03:40:58 +01:00
parent 48e034a8e9
commit 6a8f1e1032
8 changed files with 119 additions and 47 deletions

View file

@ -1,8 +1,7 @@
# litl # litl
The world: Here is a free open source full-featured self-hosted URL shortener. The World: Here is a free open source full-featured self-hosted URL shortener.
Grizzly: I can do better!
Grizzly: *choke on PHP* I can do better!
## Description ## Description

View file

@ -9,13 +9,14 @@ from crispy_forms.helper import FormHelper
from crispy_forms.layout import Submit from crispy_forms.layout import Submit
from .models import Slug from .models import Slug
class SlugAddForm(forms.ModelForm): class SlugAddForm(forms.Form):
class Meta:
model = Slug destination = forms.CharField(label="Destination", max_length=300,required=True)
fields = ('destination','slug') slug = forms.CharField(label="Slug", max_length=20,required=False)
bulk = forms.BooleanField(label="Bulk", required=False)
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args,**kwargs) super(SlugAddForm, self).__init__(*args, **kwargs)
self.helper = FormHelper() self.helper = FormHelper()
self.helper.form_method = 'post' self.helper.add_input(Submit('submit', 'Shorten', css_class='btn-primary'))
self.helper.add_input(Submit('submit','Shorten')) self.helper.form_method = 'POST'

View file

@ -0,0 +1,31 @@
# Generated by Django 3.1.4 on 2021-01-01 22:27
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('litl', '0003_auto_20210101_1203'),
]
operations = [
migrations.RemoveField(
model_name='slug',
name='destination',
),
migrations.AddField(
model_name='slug',
name='bulk',
field=models.BooleanField(default=False, help_text='Generate a short URL leading to multiple destinations'),
),
migrations.CreateModel(
name='Destination',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('destination', models.CharField(help_text='The destination URL, limited to 300 characters.', max_length=300)),
('slug', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='litl.slug')),
],
),
]

View file

@ -7,17 +7,21 @@
from django.db import models from django.db import models
class Slug(models.Model): class Slug(models.Model):
"""Model of a slug. The slug represent the URL that leads to litl.*.*/slug
A slug has one user and can have from one to many destination.
"""
slug = models.SlugField( slug = models.SlugField(
max_length=20, max_length=20,
null=False, null=False,
blank=True, blank=True,
help_text="Slug of the new URL. Up to 20 caracters including letters, number, underscores and hyphens.", ) help_text="Slug of the new URL. Up to 20 caracters including letters, number, underscores and hyphens.", )
destination = models.CharField(
max_length=300, bulk = models.BooleanField(
null=False, default=False,
blank=False, help_text="Generate a short URL leading to multiple destinations",
help_text="The destination URL, limited to 300 characters.",) )
uid = models.CharField( uid = models.CharField(
max_length=100, max_length=100,
null=True,) null=True,)
@ -25,6 +29,17 @@ class Slug(models.Model):
auto_now=True,) auto_now=True,)
def __str__(self): def __str__(self):
return '{} -> {:.15}...'.format(self.slug,self.destination) return '{} -> ?'.format(self.slug)
class Destination(models.Model):
"""Model of a destination. A destination is the end URL wanted by the user.
One Slug can have multiple destinations.
"""
slug = models.ForeignKey(Slug, on_delete=models.CASCADE)
destination = models.CharField(
max_length=300,
null=False,
blank=False,
help_text="The destination URL, limited to 300 characters.",)

View file

@ -3,5 +3,19 @@
{% load crispy_forms_tags %} {% load crispy_forms_tags %}
{% block content %} {% block content %}
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endfor %}
{% for error in form.non_field_errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endif %}
{% crispy form %} {% crispy form %}
{% endblock %} {% endblock %}

View file

@ -93,7 +93,7 @@ Code</a>
</div> </div>
</div> </div>
</body> </body>
</script>
</html> </html>

View file

@ -3,7 +3,7 @@
{% block content %} {% block content %}
<div class="container text-center"> <div class="container text-center">
<div class="container"> <div class="container">
<h2>{{slug.destination}}</h2> <h2>{{destinations.first.destination}}</h2>
</div> </div>
<h2><p class="fa fa-arrow-down" style="color:grey;"></p></h2> <h2><p class="fa fa-arrow-down" style="color:grey;"></p></h2>

View file

@ -9,7 +9,7 @@ from django.http import HttpResponseRedirect, HttpResponsePermanentRedirect
from django.contrib import messages from django.contrib import messages
from .settings import TEMPLATES, RANDOM_SLUG_LEN, UID_LEN from .settings import TEMPLATES, RANDOM_SLUG_LEN, UID_LEN
from .models import Slug from .models import Slug, Destination
from .forms import SlugAddForm from .forms import SlugAddForm
import random, string import random, string
@ -25,8 +25,9 @@ def index(request):
def AddSlug(request): def AddSlug(request):
"""Display the form for creating a new slug. """Display the form for creating a new slug.
""" """
form = SlugAddForm(request.POST or None) if request.method == 'POST':
if request.method == 'POST' and form.is_valid(): form = SlugAddForm(request.POST)
if form.is_valid():
# Add slug if needed # Add slug if needed
if form.cleaned_data['slug'] == '': if form.cleaned_data['slug'] == '':
rand_slug = ''.join(random.choice(ensemble) for _ in range(RANDOM_SLUG_LEN)) rand_slug = ''.join(random.choice(ensemble) for _ in range(RANDOM_SLUG_LEN))
@ -44,20 +45,30 @@ def AddSlug(request):
while Slug.objects.filter(uid = rand_uid).exists(): while Slug.objects.filter(uid = rand_uid).exists():
rand_uid = ''.join(random.choice(ensemble) for _ in range(UID_LEN)) rand_uid = ''.join(random.choice(ensemble) for _ in range(UID_LEN))
slug = form.save(commit=False) slug = Slug(slug = form.cleaned_data['slug'],
slug.uid = rand_uid uid = rand_uid,
bulk = form.cleaned_data['bulk'],)
slug.save() slug.save()
destination = Destination(slug = slug,
destination = form.cleaned_data['destination'],)
destination.save()
return HttpResponseRedirect('display/{}'.format(slug.slug)) return HttpResponseRedirect('display/{}'.format(slug.slug))
else:
form = SlugAddForm()
# First call, return empty form # First call, return empty form
return render(request,'add_slug.html',{'form':form}) return render(request,'add_slug.html',{'form':form})
def display(request, slug_got): def display(request, slug_got):
slug = Slug.objects.filter(slug = slug_got).all() slug = Slug.objects.filter(slug = slug_got).all()
if slug.count()!=1: if slug.count()!=1:
return render(request,'unknown.html',{'slug':slug_got}) return render(request,'unknown.html',{'slug':slug_got})
else: else:
context = {'slug':slug.get(), 'request': request} destinations = Destination.objects.filter(slug=slug.get()).all()
context = {'slug':slug.get(), 'destinations':destinations, 'request': request}
return render(request,'display.html',context) return render(request,'display.html',context)
def redirect(request,slug_got): def redirect(request,slug_got):
@ -66,5 +77,6 @@ def redirect(request,slug_got):
context = {'slug':slug_got,'request': request} context = {'slug':slug_got,'request': request}
return render(request,'unknown.html',context) return render(request,'unknown.html',context)
else: else:
return HttpResponsePermanentRedirect(slug.get().destination) destinations = Destination.objects.filter(slug=slug.get()).all()
return HttpResponsePermanentRedirect(destinations.first().destination)