django view redirect to url

The Ultimate Guide to Django Redirects

Watch Now This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding: Django Redirects

When you build a Python web application with the Django framework, you’ll at some point have to redirect the user from one URL to another.

In this guide, you’ll learn everything you need to know about HTTP redirects and how to deal with them in Django. At the end of this tutorial, you’ll:

This tutorial assumes that you’re familiar with the basic building blocks of a Django application, like views and URL patterns.

Django Redirects: A Super Simple Example

Just call redirect() with a URL in your view. It will return a HttpResponseRedirect class, which you then return from your view.

This article could end here, but then it could hardly be called “The Ultimate Guide to Django Redirects.” We will take a closer look at the redirect() function in a minute and also get into the nitty-gritty details of HTTP status codes and different HttpRedirectResponse classes, but let’s take a step back and start with a fundamental question.

Why Redirect

You might wonder why you’d ever want to redirect a user to a different URL in the first place. To get an idea where redirects make sense, have a look at how Django itself incorporates redirects into features that the framework provides by default:

What would an alternative implementation without redirects look like? If a user has to log in to view a page, you could simply display a page that says something like “Click here to log in.” This would work, but it would be inconvenient for the user.

URL shorteners like http://bit.ly are another example of where redirects come in handy: you type a short URL into the address bar of your browser and are then redirected to a page with a long, unwieldy URL.

In other cases, redirects are not just a matter of convenience. Redirects are an essential instrument to guide the user through a web application. After performing some kind of operation with side effects, like creating or deleting an object, it’s a best practice to redirect to another URL to prevent accidentally performing the operation twice.

One example of this use of redirects is form handling, where a user is redirected to another URL after successfully submitting a form. Here’s a code sample that illustrates how you’d typically handle a form:

The purpose of this view is to display and handle a contact form that allows the user to send a message. Let’s follow it step by step:

First the view looks at the request method. When the user visits the URL connected to this view, the browser performs a GET request.

If the view is called with a POST request, the POST data is used to instantiate a ContactForm object.

If the view receives a GET request (or, to be precise, any kind of request that is not a POST request), it creates an instance of ContactForm and uses django.shortcuts.render() to render the contact_form.html template.

If the user now hits reload, only the /success/ URL is reloaded. Without the redirect, reloading the page would re-submit the form and send another message.

Behind the Scenes: How an HTTP Redirect Works

Now you know why redirects make sense, but how do they work? Let’s have a quick recap of what happens when you enter a URL in the address bar of your web browser.

A Quick Primer on HTTP

As you can see, an HTTP response starts with a status line that contains a status code and a status message. The status line is followed by an arbitrary number of HTTP headers. An empty line indicates the end of the headers and the start of the response body, which contains the actual data the server wants to send.

HTTP Redirects Status Codes

The two responses might look similar, but there are some key differences. The redirect:

The primary differentiator is the status code. The specification of the HTTP standard says the following:

The 302 (Found) status code indicates that the target resource resides temporarily under a different URI. Since the redirection might be altered on occasion, the client ought to continue to use the effective request URI for future requests. The server SHOULD generate a Location header field in the response containing a URI reference for the different URI. The user agent MAY use the Location field value for automatic redirection. (Source)

A key phrase in the specification is “MAY use the Location field value for automatic redirection.” It means that you can’t force the client to load another URL. The client can choose to wait for user confirmation or decide not to load the URL at all.

Now you know that a redirect is just an HTTP response with a 3xx status code and a Location header. The key takeaway here is that an HTTP redirect is like any old HTTP response, but with an empty body, 3xx status code, and a Location header.

That’s it. We’ll tie this back into Django momentarily, but first let’s take a look at two types of redirects in that 3xx status code range and see why they matter when it comes to web development.

Temporary vs. Permanent Redirects

A status code 302 Found indicates a temporary redirect. A temporary redirect says, “At the moment, the thing you’re looking for can be found at this other address.” Think of it like a store sign that reads, “Our store is currently closed for renovation. Please go to our other store around the corner.” As this is only temporary, you’d check the original address the next time you go shopping.

As the name implies, permanent redirects are supposed to be permanent. A permanent redirect tells the browser, “The thing you’re looking for is no longer at this address. It’s now at this new address, and it will never be at the old address again.”

A permanent redirect is like a store sign that reads, “We moved. Our new store is just around the corner.” This change is permanent, so the next time you want to go to the store, you’d go straight to the new address.

Note: Permanent redirects can have unintended consequences. Finish this guide before using a permanent redirect or jump straight to the section “Permanent redirects are permanent.”

Browsers behave similarly when handling redirects: when a URL returns a permanent redirect response, this response is cached. The next time the browser encounters the old URL, it remembers the redirect and directly requests the new address.

Caching a redirect saves an unnecessary request and makes for a better and faster user experience.

Furthermore, the distinction between temporary and permanent redirects is relevant for Search Engine Optimization.

Redirects in Django

Now you know that a redirect is just an HTTP response with a 3xx status code and a Location header.

You could build such a response yourself from a regular HttpResponse object:

This solution is technically correct, but it involves quite a bit of typing.

The HTTPResponseRedirect Class

You can play with the HttpResponseRedirect class in the Python shell to see what you’re getting:

Note: In the examples above, the redirect URLs are hard-coded. Hard-coding URLs is bad practice: if the URL ever changes, you have to search through all your code and change any occurrences. Let’s fix that!

You could use django.urls.reverse() to build a URL, but there is a more convenient way as you will see in the next section.

The redirect() Function

You can call this function with:

Here are three examples to illustrate the different use cases:

Passing a URL name and arguments:

redirect() will try to use its given arguments to reverse a URL. This example assumes your URL patterns contain a pattern like this:

The RedirectView Class-Based View

You can tailor RedirectView to your needs through various attributes.

Instead of subclassing RedirectView to overwrite the url attribute, you can also pass the keyword argument url to as_view() in your urlpatterns :

You can also overwrite get_redirect_url() to get a completely custom behavior:

django.views.generic.base.RedirectView offers a few more hooks for customization. Here is the complete list:

If this attribute is set, it should be the name of a URL pattern to redirect to. Any positional and keyword arguments passed to the view are used to reverse the URL pattern.

You can change that behavior in any way you want by overwriting this method. Just make sure it returns a string containing a URL.

Note: Class-based views are a powerful concept but can be a bit difficult to wrap your head around. Unlike regular function-based views, where it’s relatively straightforward to follow the flow of the code, class-based views are made up of a complex hierarchy of mixins and base classes.

A great tool to make sense of a class-based view class is the website Classy Class-Based Views.

You could implement the functionality of RandomAnimalView from the example above with this simple function-based view:

Advanced Usage

Passing Parameters with Redirects

Sometimes, you want to pass some parameters to the view you’re redirecting to. Your best option is to pass the data in the query string of your redirect URL, which means redirecting to a URL like this:

The code in this example is quite dense, so let’s follow it step by step:

Next, you have to build the query string. That’s the part after the question mark. It’s advisable to use urllib.urlparse.urlencode() for that, as it will take care of properly encoding any special characters.

Now you have to join base_url and query_string with a question mark. A format string works fine for that.

Finally, you pass url to django.shortcuts.redirect() or to a redirect response class.

Note: Make sure to validate any data you read from query strings. It might seem like this data is under your control because you created the redirect URL.

In reality, the redirect could be manipulated by the user and must not be trusted, like any other user input. Without proper validation, an attacker might be able gain unauthorized access.

Special Redirect Codes

Alternatively, you can use the django.shortcuts.redirect() method to create a response object and change the return value. This approach makes sense when you have the name of a view or URL or a model you want to redirect to:

One could argue that 304 Not Modified response redirects to the cached version of a URL, but that’s a bit of a stretch. Consequently, it is no longer listed in the “Redirection 3xx” section of the HTTP standard.

Pitfalls

Redirects That Just Won’t Redirect

The simplicity of django.shortcuts.redirect() can be deceiving. The function itself doesn’t perform a redirect: it just returns a redirect response object. You must return this response object from your view (or in a middleware). Otherwise, no redirect will happen.

But even if you know that just calling redirect() is not enough, it’s easy to introduce this bug into a working application through a simple refactoring. Here’s an example to illustrate that.

Let’s assume you are building a shop and have a view that is responsible for displaying a product. If the product does not exist, you redirect to the homepage:

Now you want to add a second view to display customer reviews for a product. It should also redirect to the homepage for non-existing products, so as a first step, you extract this functionality from product_view() into a helper function get_product_or_redirect() :

Unfortunately, after the refactoring, the redirect does not work anymore.

Can you spot the error? Show/Hide

Depending on how you use the product variable in the product_detail.html template, this might not result in an error message and just display empty values.

Redirects That Just Won’t Stop Redirecting

When dealing with redirects, you might accidentally create a redirect loop, by having URL A return a redirect that points to URL B which returns a redirect to URL A, and so on. Most HTTP clients detect this kind of redirect loop and will display an error message after a number of requests.

Unfortunately, this kind of bug can be tricky to spot because everything looks fine on the server side. Unless your users complain about the issue, the only indication that something might be wrong is that you’ve got a number of requests from one client that all result in a redirect response in quick succession, but no response with a 200 OK status.

Here’s a simple example of a redirect loop:

This example illustrates the principle, but it’s overly simplistic. The redirect loops you’ll encounter in real-life are probably going to be harder to spot. Let’s look at a more elaborate example:

The product_view looks familiar from the previous section, but it has two minor differences:

There is no bullet-proof way to prevent this kind of bug, but a good starting point is to check if the view you are redirecting to uses redirects itself.

Permanent Redirects Are Permanent

Permanent redirects can be like bad tattoos: they might seem like a good idea at the time, but once you realize they were a mistake, it can be quite hard to get rid of them.

When a browser receives a permanent redirect response for a URL, it caches this response indefinitely. Any time you request the old URL in the future, the browser doesn’t bother loading it and directly loads the new URL.

It can be quite tricky to convince a browser to load a URL that once returned a permanent redirect. Google Chrome is especially aggressive when it comes to caching redirects.

Why can this be a problem?

As it turns out, you’re not only a great developer, but also a talented writer. Your blog becomes popular, and your launch mailing list grows. After a couple of months, your app is ready. It now has a shiny homepage, and you finally remove the redirect.

You send out an announcement email with a special discount code to your sizeable launch mailing list. You lean back and wait for the sign-up notifications to roll in.

To your horror, your mailbox fills with messages from confused visitors who want to visit your app but are always being redirected to your blog.

What has happened? Your blog readers had visited https://myawesomedjangowebapp.com/ when the redirect to https://myawesomedjangowebapp.com/blog/ was still active. Because it was a permanent redirect, it was cached in their browsers.

When they clicked on the link in your launch announcement mail, their browsers never bothered to check your new homepage and went straight to your blog. Instead of celebrating your successful launch, you’re busy instructing your users how to fiddle with chrome://net-internals to reset the cache of their browsers.

The permanent nature of permanent redirects can also bite you while developing on your local machine. Let’s rewind to the moment when you implemented that fateful permanent redirect for myawesomedjangowebapp.com.

You return with a full belly, ready to tackle some client work. The client wants some simple changes to their homepage, so you load the client’s project and start the development server.

The takeaway from this story is that you should only use permanent redirects on URLs that you’ve no intention of ever using again. There is a place for permanent redirects, but you must be aware of their consequences.

Even if you’re confident that you really need a permanent redirect, it’s a good idea to implement a temporary redirect first and only switch to its permanent cousin once you’re 100% sure everything works as intended.

Unvalidated Redirects Can Compromise Security

From a security perspective, redirects are a relatively safe technique. An attacker cannot hack a website with a redirect. After all, a redirect just redirects to a URL that an attacker could just type in the address bar of their browser.

However, if you use some kind of user input, like a URL parameter, without proper validation as a redirect URL, this could be abused by an attacker for a phishing attack. This kind of redirect is called an open or unvalidated redirect.

There are legitimate use cases for redirecting to URL that is read from user input. A prime example is Django’s login view. It accepts a URL parameter next that contains the URL of the page the user is redirected to after login. To redirect the user to their profile after login, the URL might look like this:

Django does validate the next parameter, but let’s assume for a second that it doesn’t.

Without validation, an attacker could craft a URL that redirects the user to a website under their control, for example:

The website myawesomedjangowebapp.co might then display an error message and trick the user into entering their credentials again.

The best way to avoid open redirects is to not use any user input when building a redirect URL.

If you cannot be sure that a URL is safe for redirection, you can use the function django.utils.http.is_safe_url() to validate it. The docstring explains its usage quite well:

is_safe_url(url, host=None, allowed_hosts=None, require_https=False)

Let’s look at some examples.

A relative URL is considered safe:

A URL pointing to another host is generally not considered safe:

A URL pointing to another host is considered safe if its host is provided in allowed_hosts :

Источник

Перенаправление страниц Django

django view redirect to url

Перенаправление страниц необходимо по многим причинам в веб-приложениях. Возможно, вы захотите перенаправить пользователя на другую страницу, когда происходит определенное действие, или в основном в случае ошибки. Например, когда пользователь входит на ваш сайт, его часто перенаправляют либо на главную домашнюю страницу, либо на его личную панель инструментов. В Django перенаправление выполняется методом redirect.

Метод redirect принимает в качестве аргумента URL-адрес, на который вы хотите быть перенаправлены, представляющий собой строку.

Файл myapp/views.py пока выглядит следующим образом:

Давайте изменим представление hello для перенаправления на djangoproject.com, а viewArticle для перенаправления на наш внутренний адрес /myapp/article. Файл myapp/view.py изменится и станет выглядеть следующим образом:

В приведенном выше примере сначала мы импортировали функцию для перенаправления из django.shortcuts. Для перенаправления на официальный сайт Django мы просто передали полный URL-адрес методу redirect в виде строки, а для второго примера (представление viewArticle) метод перенаправления принимает имя представления и его параметры в качестве аргументов.

Получив доступ к /myapp/hello, вы увидите следующее:

django view redirect to url

А доступ к /myapp/article/42, даст вам следующий результат:

django view redirect to url

Также можно указать, является ли перенаправление временным или постоянным, добавив параметр constant = True. Пользователь не увидит никакой разницы, но это детали, которые поисковые системы учитывают при ранжировании вашего сайта.

Также помните, что мы определили параметр name в нашем urls.py при сопоставлении URL-адреса:

Это имя (в данном случае articles) может использоваться в качестве аргумента для метода redirect, тогда наше перенаправление viewArticle может быть изменено с:

Источник

Documentation

Django shortcut functions¶

The package django.shortcuts collects helper functions and classes that “span” multiple levels of MVC. In other words, these functions/classes introduce controlled coupling for convenience’s sake.

render() ¶

Combines a given template with a given context dictionary and returns an HttpResponse object with that rendered text.

Required arguments¶

Optional arguments¶

Example¶

The following example renders the template myapp/index.html with the MIME type application/xhtml+xml:

This example is equivalent to:

redirect() ¶

Returns an HttpResponseRedirect to the appropriate URL for the arguments passed.

The arguments could be:

By default issues a temporary redirect; pass permanent=True to issue a permanent redirect.

Examples¶

You can use the redirect() function in a number of ways.

By passing some object; that object’s get_absolute_url() method will be called to figure out the redirect URL:

By passing the name of a view and optionally some positional or keyword arguments; the URL will be reverse resolved using the reverse() method:

By passing a hardcoded URL to redirect to:

This also works with full URLs:

By default, redirect() returns a temporary redirect. All of the above forms accept a permanent argument; if set to True a permanent redirect will be returned:

get_object_or_404() ¶

Calls get() on a given model manager, but it raises Http404 instead of the model’s DoesNotExist exception.

Required arguments¶

Example¶

The following example gets the object with the primary key of 1 from MyModel :

This example is equivalent to:

The above example is a bit contrived since it’s equivalent to doing:

but it can be useful if you are passed the queryset variable from somewhere else.

get_list_or_404() ¶

Returns the result of filter() on a given model manager cast to a list, raising Http404 if the resulting list is empty.

Required arguments¶

Example¶

The following example gets all published objects from MyModel :

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *