Redirects in Django: Types, Uses, and How to Maintain Your SEO When Changing URLs
Content Index
- What is an HTTP redirect and why does it matter in Django?
- What it means to redirect a view in Django
- When to use 301 and when to use 302: a quick guide for SEO
- Methods for making redirects in Django
- Using redirect() in views (the most direct method)
- HttpResponseRedirect and HttpResponsePermanentRedirect
- Redirects with reverse() and dynamic parameters
- Redirects to external URLs or on other domains
- Django return redirect() with parameters
- Practical cases I use in my projects
- Testing and verifying your redirects
- Frequent errors and how to solve them
- NoReverseMatch and poorly defined namespaces
- Login/logout redirects that don't work
- Frequently asked questions about redirects in Django
- Conclusion
When we develop any web project, and Django is NO exception, besides having named routes, we have to use redirects; redirects are one of those tools we use almost without thinking, but they play a key role in both the user experience and technical SEO.
Using redirects well is what makes the difference between an organized app and a chaos of broken links.
Redirects in Django are the mechanism we have to send from one page to another configured in our Django app; redirects are nothing more than the behavior of sending a client or user to another page, whether in our application or another application; for SEO, the 302 code is usually used for this type of operation; a common example of redirects is when we have a post or publication where we change the title and thus the slug, but we don't want to lose the positioning of the original post, in these cases, we can make a 302 type redirect to the new link.
What is an HTTP redirect and why does it matter in Django?
An HTTP redirect is simply an instruction that tells the browser: "don't stay here, go to another URL."
In Django, this behavior is implemented with specific functions that return a 3xx type HTTP response.
What it means to redirect a view in Django
When a view processes a form or an action, often it doesn't have an associated template. In those cases, the ideal is to redirect the user to another page.
In my projects, for example, when a user creates a record, I send them directly to the detail page or the general list, depending on the business logic.
Most used status codes (301, 302, and 307)
- 301 (Permanent): indicates that the URL has changed permanently. Ideal for SEO and slug changes.
- 302 (Temporary): used when the redirect is momentary (for example, while testing a view).
- 307: a stricter version of 302; maintains the original method (POST/GET).
When to use 301 and when to use 302: a quick guide for SEO
When I changed the slug of a post on my blog, I used a 301 redirect to avoid losing traffic or backlinks.
In contrast, for internal redirects after submitting forms, I usually use 302, as they are transient.
Methods for making redirects in Django
Redirects are a common behavior that when—for example—we send a request to create a record, this function might not have an associated template, due to its purpose; therefore, what we do are redirects:
- If the data is correct, we redirect to the list, creation, or update form.
- If the data has validation problems, we send them to the creation page.
So, for the following routes:
app_name="gestion"
urlpatterns = [
path('',views.index, name="index"),
path('detail/<int:pk>',views.show, name="show"),
path('create',views.create, name="create"),
path('update/<int:pk>',views.update, name="update"),
path('delete/<int:pk>',views.delete, name="delete")
]Django offers several ways to redirect, depending on the context.
Using redirect() in views (the most direct method)
And if we want to make a redirect:
from django.shortcuts import redirect
return redirect('gestion:index')A little more complete:
from django.shortcuts import redirect
def create(request):
form = ProductForm(request.POST or None)
if form.is_valid():
product = Product()
product.title = form.cleaned_data['title']
***
product.save()
return redirect('gestion:update', pk=product.id)
return redirect('gestion:create')The pattern is as follows:
- If everything goes well, I redirect to the edit form.
- If something fails, I return to the creation view.
HttpResponseRedirect and HttpResponsePermanentRedirect
These classes allow you to explicitly control the type of redirect:
from django.shortcuts import redirect
def create(request):
form = ProductForm(request.POST or None)
if form.is_valid():
product = Product()
product.title = form.cleaned_data['title']
***
product.save()
return redirect('gestion:update', pk=product.id)
return redirect('gestion:create')Useful when you want fine control over the status code.
Redirects with reverse() and dynamic parameters
Django allows building the URL from the route name and its parameters:
from django.urls import reverse
return redirect(reverse('gestion:show', kwargs={'pk': 15}))It is a safe practice, especially if you change your routes in urls.py.
Redirects to external URLs or on other domains
If you need to redirect outside your application, simply pass the complete URL:
return redirect('https://www.google.com')We redirect by indicating the name of the app, followed by a colon, followed by the name of the route.
Django return redirect() with parameters
It is also possible to redirect with parameters:
return redirect('update', pk=15)Practical cases I use in my projects
- Redirecting after creating or updating a record
- In my usual flow, after saving a product, I redirect to the detail or the list.
This improves the UX and prevents the user from accidentally reloading the form.
- In my usual flow, after saving a product, I redirect to the detail or the list.
- Form handling: validate, save, and redirect correctly
- If the data is not valid, I always redirect to the original form showing the errors.
It's a small gesture that avoids confusion and keeps the app fluid.
- If the data is not valid, I always redirect to the original form showing the errors.
- Changing a post's slug and redirecting with 301 to avoid losing traffic
- Once, when updating article titles, the old slugs became obsolete.
I implemented a 301 redirect in urls.py to the new route. Result: I maintained my organic traffic without losing positioning.
- Once, when updating article titles, the old slugs became obsolete.
- How to avoid infinite loops and common errors
- A typical error is redirecting to the same view that causes the redirect.
- To avoid this, always check the conditions before returning the response:
if request.path != reverse('home'): return redirect('home')
Testing and verifying your redirects
How to test redirects with Django's Client()
You can automate tests to ensure your views redirect correctly:
from django.test import Client
client = Client()
response = client.post('/crear/', {'title': 'Nuevo'})
assert response.status_code == 302Using assertRedirects in automated tests
Even more elegant:
self.assertRedirects(response, '/listado/')Checking your redirects with curl or SEO tools
In the terminal, run:
$ curl -I https://tusitio.com/old-url/This verifies if the code is 301 or 302.
You can also check redirects in Google Search Console or Screaming Frog.
Frequent errors and how to solve them
NoReverseMatch and poorly defined namespaces
Occurs when the URL name does not match. Review your app_name and path():
app_name = 'gestion' path('detalle/<int:pk>', views.show, name='show')Calling redirect('gestion:show', pk=1) will solve the error.
Login/logout redirects that don't work
If you use generic views like LoginView, define next or success_url correctly:
class CustomLoginView(LoginView): success_url = reverse_lazy('dashboard')Lost parameters or incorrect routes
Make sure to pass complete args or kwargs; otherwise, Django won't know how to build the URL.
Frequently asked questions about redirects in Django
What is the difference between redirect() and HttpResponseRedirect?
redirect() is a shortcut that automatically decides the response type; HttpResponseRedirect always returns a 302.
Can I redirect with parameters?
Yes, using kwargs or reverse() to build the URL with dynamic arguments.
What happens to SEO if I change a URL's slug?
If you don't do a 301 redirect, you lose traffic. In my case, it was the difference between maintaining positions or disappearing from Google.
How do I test my redirects before production?
With curl -I or in the Search Console panel you can check the status code and final destination.
Conclusion
Redirects in Django are not only a technical tool but an ally of SEO and user experience.
In my projects, correctly applying 301 and 302 has allowed me to maintain traffic, avoid errors, and have clearer flows.
If you plan your routes, validate your forms, and test your redirects, you'll avoid many headaches.
The next step is to continue with our CRUD and learn how to delete records.
I agree to receive announcements of interest about this Blog.
Redirects in Django are the mechanism we have to send from one page to another that we have configured in our Django app.