Django view that redirects to another domain - python

How to redirect to another domain with python django and pass additional informations?
For example i want to redirect to https://ssl.dotpay.pl/test_payment/ and give additional informations so url will look like this
https://ssl.dotpay.pl/test_payment/?id=123456&amount=123.00&description=Test
but I don't want to generate url in my view, just pass the data in json or something like that.
What is the way to do this?

this is generated url by what i meant 'ssl.dotpay.pl/test_payment/?id=123456&amount={}&description={}'.format(123.00, 'Test')
Be sure to put a protocol before your url (or at least two slashes).
This way, Django will see it as an absolute path.
From your comment it seems you redirect to ssl.dotpay.pl what will be seen as a local path rather than another domain.
This is what I came across. (See question I put on stackoverflow and answer)
So in your case, you can use the following:
class MyView(View):
def get(self, request, *args, **kwargs):
url = 'https://ssl.dotpay.pl/test_payment/'
'?id=123456&amount={}&description={}'.format(123.00, 'Test')
return HttpResponseRedirect(url)
You could also use redirect from django.shortcuts instead of HttpResponseRedirect

Assuming you are using a functional view, you could probably do something like this in your view:
from django.http import HttpResponseRedirect
def theview(request):
# your logic here
return HttpResponseRedirect(<theURL>)

Related

Django 1.5 url redirect with regex?

I'm trying to do something like this:
(r'^$', RedirectView.as_view(url='^(?P<username>\w+)/$')),
but it doesn't seem to parse the regex part to the actual username...
I've done research but I can only find examples that redirect to exact urls or other regex examples that work but only in Django 1.1
Anyone have any idea how to do this in Django 1.5+?
Subclass RedirectView, and override the get_redirect_view method.
from django.core.urlresolvers import reverse
class UserRedirectView(RedirectView):
permanent = False
def get_redirect_url(self, pk):
# it would be better to use reverse here
return '/myapp/%s/' % self.request.user.username
You would include your UserRedirectView in your myapp.urls.py module as follows:
url(r'^$', UserRedirectView.as_view(), name='myapp_index'),
It would be better to reverse the url instead of hardcoding /myapp/ in the url above. As an example, if you were redirecting to a url pattern like the following
url(r'^(?P<username>\w+)/$', 'myapp.view_user', name='myapp_view_user'),
Then you could change the get_redirect_url view to:
def get_redirect_url(self, pk):
return reverse('myapp_view_user', args=(self.request.user.username,))
I think you need something like this
(r'^(?P<username>\w+)/$', 'your_view'),
where your_view is
def page(request, username):
pass
If you need redirection with parameters, you can use
('^(?P<username>\w+)/$', 'django.views.generic.simple.redirect_to',
{'url': '/bar/%(username)s/'}),
More info here:
https://docs.djangoproject.com/en/1.2/ref/generic-views/#django-views-generic-simple-redirect-to
and here:
https://docs.djangoproject.com/en/1.4/topics/http/urls/#notes-on-capturing-text-in-urls
You can try this package https://github.com/maykinmedia/django-regex-redirects. It is used in some of our projects

How to use current logged in user as PK for Django DetailView?

When defining URL patterns, I am supposed to use a regular expression to acquire a PK from the URL.
What if I want a URL that has no PK, and if it's not provided, it will use the currently logged in user? Examples:
visiting /user will get a DetailView of the currently logged in user
/user/edit will show an UpdateView for the currently logged in user
I tried hard-coding the pk= in the Detail.as_view() call but it reports invalid keyword.
How do I specify that in the URL conf?
My sample code that shows PK required error when visiting /user URL:
urlpatterns = patterns('',
url(r'user/$',
DetailView.as_view(
model=Account,
template_name='user/detail.html')),
)`
An alternative approach would be overriding the get_object method of the DetailView subclass, something along the line of:
class CurrentUserDetailView(UserDetailView):
def get_object(self):
return self.request.user
Much cleaner, simpler and more in the spirit of the class-based views than the mixin approach.
EDIT: To clarify, I believe that two different URL patterns (i.e. one with a pk and the other without) should be defined separately in the urlconf. Therefore they could be served by two different views as well, especially as this makes the code cleaner. In this case the urlconf might look something like:
urlpatterns = patterns('',
url(r"^users/(?P<pk>\d+)/$", UserDetailView.as_view(), name="user_detail"),
url(r"^users/current/$", CurrentUserDetailView.as_view(), name="current_user_detail"),
url(r"^users/$", UserListView.as_view(), name="user_list"),
)
And I've updated my example above to note that it inherits the UserDetailView, which makes it even cleaner, and makes it clear what it really is: a special case of the parent view.
As far as I know, you can't define that on the URL definition, since you don't have access to that information.
However, what you can do is create your own mixin and use it to build views that behave like you want.
Your mixin would look something like this:
class CurrentUserMixin(object):
model = Account
def get_object(self, *args, **kwargs):
try:
obj = super(CurrentUserMixin, self).get_object(*args, **kwargs)
except AttributeError:
# SingleObjectMixin throws an AttributeError when no pk or slug
# is present on the url. In those cases, we use the current user
obj = self.request.user.account
return obj
and then, make your custom views:
class UserDetailView(CurrentUserMixin, DetailView):
pass
class UserUpdateView(CurrentUserMixin, UpdateView):
pass
Generic views uses always RequestContext. And this paragraph in the Django Documentation says that when using RequestContext with auth app, the template gets passed an user variable that represents current user logged in. So, go ahead, and feel free to reference user in your templates.
You can get the details of the current user from the request object. If you'd like to see a different user's details, you can pass the url as parameter. The url would be encoded like:
url(r'user/(?P<user_id>.*)$', 'views.user_details', name='user-details'),
views.user_details 2nd parameter would be user_id which is a string (you can change the regex in the url to restrict integer values, but the parameter would still of type string). Here's a list of other examples for url patterns from the Django documentation.

regular expression in django for urls

What I am trying to do is as follows
I have urls like this /blog/1/sdc/?c=119 or /forum/83/ksnd/?c=100 What I want to do is to redirect these to a view, so that I can change the url to /blog/1/sdc/#c119
One way would be to do this is to make provision in views of each of the app, where such a url maybe generated, but that is not scalable. What I want to do is to catch any url that has ?c=<some_digit> at the end and redirect to my custom view.
Can anybody help, I am not good with regex.
You can't do this in your urlconf, it doesn't match anything in the query string. What you'll need to do is write a middleware along the lines of this:
class RedirectMiddleware:
def process_request(self, request):
if 'c' in request.GET:
# return a HttpResponseRedirect here
See https://docs.djangoproject.com/en/dev/topics/http/middleware/ for more details.

Django:How can I ensure that a view can only be directed from another view

I have two views
def view1(request):
do something
return HttpResponseRedirect(reverse(view2), args1)
Now I need view2 to only work if it's referred by view1. How do I do that? I did read it somewhere, not able to recollect
#somefilter
def view2(request):
do something
#view2 will only be referred from view1, else Http404
I think you should check for the HTTP_REFERER HTTP header. See the documentation. Here is a Django snippet that gives you a decorator to check for referrers.

How to redirect with post data (Django)

When processing a POST request in the Django views.py file, I sometimes need to redirect it to another url. This url I'm redirecting to is handled by another function in the same Django views.py file. Is there a way of doing this and maintaining the original POST data?
UPDATE: More explanation of why I want to do this.
I have two web apps (let's call them AppA and AppB) which accept data entered into a text field by the user. When the the user clicks submit, the data is processed and detailed results are displayed. AppA and AppB expect different types of data. Sometimes a user mistakenly posts AppB type data to AppA. When this happens I want to redirect them to AppB and show the AppB results or at least have it populated with the data they entered into AppA.
Also:
The client wants two separate apps rather than combining them into just one.
I can't show the code as it belongs to a client.
UPDATE 2:
I've decided that KISS is the best principle here. I have combined the two apps into one which makes things simpler and more robust; I should be able to convince the client it's the best way to go too. Thanks for all the great feedback. If I was going to maintain two apps as described then I think sessions would be the way to do this - thanks to Matthew J Morrison for suggesting that. Thanks to Dzida as his comments got me thinking about the design and simplification.
If you faced such problem there's a slight chance that you might need to revise your designs.
This is a restriction of HTTP that POST data cannot go with redirects.
Can you describe what are you trying to accomplish and maybe then we can think about some neat solution.
If you do not want use sessions as Matthew suggested you can pass POST params in GET to the new page (consider some limitations such as security and max length of GET params in query string).
UPDATE to your update:)
It sounds strange to me that you have 2 web apps and those apps use one views.py (am I right?). Anyway consider passing your data from POST in GET to the proper view (in case data is not sensitive of course).
I think how I would probably handle this situation would be to save the post data in session, then remove it when I no longer need it. That way I can access the original post data after a redirect even though that post is gone.
Will that work for what you're trying to do?
Here is a code sample of what I'm suggesting: (keep in mind this is untested code)
def some_view(request):
#do some stuff
request.session['_old_post'] = request.POST
return HttpResponseRedirect('next_view')
def next_view(request):
old_post = request.session.get('_old_post')
#do some stuff using old_post
One other thing to keep in mind... if you're doing this and also uploading files, i would not do it this way.
You need to use a HTTP 1.1 Temporary Redirect (307).
Unfortunately, Django redirect() and HTTPResponseRedirect
(permanent) return only a 301 or 302. You have to implement it yourself:
from django.http import HttpResponse, iri_to_uri
class HttpResponseTemporaryRedirect(HttpResponse):
status_code = 307
def __init__(self, redirect_to):
HttpResponse.__init__(self)
self['Location'] = iri_to_uri(redirect_to)
See also the django.http module.
Edit:
on recent Django versions, change iri_to_uri import to:
from django.utils.encoding import iri_to_uri
use requests package.Its very easy to implement
pip install requests
then you can call any urls with any method and transfer data
in your views import requests
import requests
to post data, follow the format
r = requests.post('http://yourdomain/path/', data = {'key':'value'})
to get the absolute url in django view, use
request.build_absolute_uri(reverse('view_name'))
Thus the django view code looks like
r = requests.post(
request.build_absolute_uri(reverse('view_name')),
data = {'key':'value'}
)
where r is the response object with status_code and content attribute.
r.status_code gives the status code(on success it will be 200) and r.content gives the body of response. There is a json method(r.json()) that will convert response to json format
requests
requests.post
Just call your new view from your old view using the same request object.
Of course it won't result in a redirect as such, but if all you care about is 'transferring' data from one view to the other, then it should work.
I tested the following snippet and it works.
from django.views.generic import View
class MyOldView(View):
def post(self, request):
return MyNewView().post(request)
class MyNewView(View):
def post(self, request):
my_data = request.body
print "look Ma; my data made it over here:", my_data
You can use render and context with with it:
Render(request,"your template path", {'vad name' : var value}
You can recive vars in template :
{% If var name %}
{{ var name }}
{% endif %}
I faced a similar issue recently.
Basically I had a form A, upon submitting it another form B would show up, which contains some results + a form. Upon submitting B, i wanted to display some alert to user and keep user on B only.
The way I solved this, is by displaying the results in a <output> field, in B.
<output name="xyz" value="xyz">{{xyz}}</output>
And I used the same view for A->B and B->B. Now I just had to distinguish if the request is coming from A or B and render accordingly.
def view1(request):
if "xyz" in request.POST:
# request from B
# do some processing
return render(request, 'page.html', {"xyz":request.POST["xyz"]})
else:
# request from A
res = foo() # some random function
return render(request, 'page.html', {"xyz":res})
But this only works if form B is small and not that dynamic.
If you are using a redirect after processing the POST to AppB, you can actually get away with calling the AppB method from the AppA method.
An Example:
def is_appa_request(request):
## do some magic.
return False or True
is_appb_request = is_appa_request
def AppA(request):
if is_appb_request(request):
return AppB(request)
## Process AppA.
return HttpResponseRedirect('/appa/thank_you/')
def AppB(request):
if is_appa_request(request):
return AppA(request)
## Process AppB.
return HttpResponseRedirect('/appb/thank_you/')
This should yield a transparent experience for the end-user, and the client who hired you will likely never know the difference.
If you're not redirecting after the POST, aren't you worried about duplicate data due to the user refreshing the page?
You can redirect with session using request.session["key"] as shown below:
# "views.py"
from django.shortcuts import redirect
def my_view(request):
# Here
request.session["message"] = "success"
return redirect("https://example.com")
# "index.html"
{{ request.session.message }} {# success #}

Categories

Resources