meeb/django-distill

Using django contrib's Redirects

Closed this issue · 7 comments

Hi there! Awesome project, I am a big fan!

However I would either like to know how I can contribute to support django's contrib Redirects in distill, or how to properly implement a redirect in a project.

I have tried a few options, but I still seem to get stuck and can't quite figure out where I'm going wrong:

Using a view function like so:

def provider_redirect_view(request, new_url):
    html = f'<html><head><meta http-equiv="refresh" content="0;url={new_url}" /></head><body></body></html>'
    return HttpResponse(html)

And then looping over all the redirects:

for redirect in Redirect.objects.all():
    print(f"Generating pattern for: {redirect.old_path}")
    unique_name = f"redirect_{redirect.id}"

    # Each tuple should match the arguments expected by the view
    def x_distill_func(new_url=redirect.new_path):
        return [(new_url,)]

    urlpatterns.append(
        distill_path(
            redirect.old_path.lstrip('/'),
            provider_redirect_view,
            name=unique_name,
            distill_func=x_distill_func
        )
    )

Any help is much appreciated, or any hints as to how I can proceed. All I'm really trying to do is have distill generate a small html file for each redirect with a refresh code to another url (following the django contrib redirect model old_path and new_path variables).

meeb commented

Hi. I don't see anything wrong with the concept of your implementation but I've never tried to use contrib redirects with distill myself. The best way if you wanted to contribute would probably be to fork the repo then add a test case that verifies your implementation (adds some redirects, runs a distill and verifies the output files contain the expected content). The only thing I can think of from your code above is your usage of urlpatterns isn't modifying the correct global urlpatterns maybe?

I would suggest directly dropping in your distill_path(...) into the normal urls.py urlpatterns (with a dummy from/to path) and check that works as expected first, then expand on it from there.

You've not specifically stated what doesn't work. Does the filename.html with the meta redirect in it just not get generated?

Hey @meeb

Thanks for your response! Right now I've solved it with the following management command and using this in a makefile to generate my entire site, however I think it should be possible to create something within Distill, but I'm a bit time-constrained right now. I'd love to contribute, and will create something as soon as I can.

For anyone reading along / running into the same issue, here is my (temporary) solution:
./management/commands/generate_redirects.py

from django.core.management.base import BaseCommand
from django.contrib.redirects.models import Redirect
from django.conf import settings
import os

class Command(BaseCommand):
    help = 'Generates static HTML files for redirects'

    def handle(self, *args, **kwargs):
        abspath = os.path.abspath(os.path.join(settings.DISTILL_DIR))
        print(f"Creating redirects in {abspath}")
        redirects = Redirect.objects.all()
        for redirect in redirects:
            redirect_path = redirect.old_path.lstrip('/')
            redirect_file = os.path.join(settings.DISTILL_DIR, redirect_path, 'index.html')
            os.makedirs(os.path.dirname(redirect_file), exist_ok=True)
            with open(redirect_file, 'w') as file:
                file.write(f'<html><head><meta http-equiv="refresh" content="0;url={redirect.new_path}" /></head><body></body></html>')
            self.stdout.write(self.style.SUCCESS(f'Successfully created redirect for {redirect.old_path}'))
meeb commented

Thanks, if that works for you I can port it into distill easily enough. Cheers!

Hi, for redirections, I have created a custom template with the following code:

<html>
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="refresh" content="0;URL=https://yoururl.com/new" />
        <meta name="robots" content="noindex" />
    </head>
    <body></body>
</html>

This works well. However, for SEO purposes, it's necessary to use a 301 status code. It's better to implement this within the nginx, .htaccess, or in the Cloudflare settings, for example.

@meeb let me know if this gets ported into the main branch/release! I'd love to update, specially with the better template from @icedogas

meeb commented

The above commit has added redirect support as a --generate-redirects additional flag to ./manage.py distill-local. This should do what you want. This writes the template as detailed here:

https://github.com/meeb/django-distill/blob/master/django_distill/renderer.py#L443

and has accompanying tests. I'll bundle this into the next release.

Woah! that's awesome! Thank you! <3