I have set everything up using the documentation for encrypted buttons on the django-paypal site. I just don't seem to be receiving any notification that the payment has happened. I know I must be missing something or doing something slightly wrong but I get no POST to any of there views unless after paying I click return to site. I need to get the notification of payment before I can move on. Thanks.
here are my views:
from django.http import HttpResponse
from django.template import RequestContext, loader
from django.shortcuts import render, HttpResponseRedirect, render_to_response
from paypal.standard.forms import PayPalEncryptedPaymentsForm
from django.core.urlresolvers import reverse
import eccomerce.settings as settings
from datetime import datetime
from paypal.standard.models import ST_PP_COMPLETED
from django.views.decorators.csrf import csrf_exempt
from paypal.standard.ipn.signals import valid_ipn_received
def show_me_the_money(sender, **kwargs):
ipn_obj = sender
if ipn_obj.payment_status == ST_PP_COMPLETED:
# Undertake some action depending upon `ipn_obj`.
payment = True
else:
payment = False
valid_ipn_received.connect(show_me_the_money)
def index(request):
# What you want the button to do.
paypal_dict = {
"business": settings.PAYPAL_RECEIVER_EMAIL,
"amount": "0.01",
"currency_code": "GBP",
"item_name": "picture01",
"invoice": "unique-%s" % (str(datetime.now())),
"notify_url": "http://127.0.0.1:8000/notify/",
"return_url": "http://127.0.0.1:8000/return/",
"cancel_return": "http://127.0.0.1:8000/cancel/",
}
valid_ipn_received.connect(show_me_the_money)
# Create the instance.
form = PayPalEncryptedPaymentsForm(initial=paypal_dict)
context = {"form": form}
return render_to_response("eccomerce_webapp/index.html", context)
#csrf_exempt
def notify(request):
valid_ipn_received.connect(show_me_the_money)
context = {}
return render_to_response("eccomerce_webapp/notify.html", context)
#csrf_exempt
def cancel(request):
valid_ipn_received.connect(show_me_the_money)
context = {}
return render_to_response("eccomerce_webapp/cancel.html", context)
#csrf_exempt
def return_view(request):
valid_ipn_received.connect(show_me_the_money)
context = {}
return render_to_response("eccomerce_webapp/return.html", context)
Here are my Urls:
from django.conf.urls import patterns, include, url
from eccomerce_webapp import views
urlpatterns = patterns('',
url(r'^notify/$', views.notify, name='notify'),
url(r'^return/$', views.return_view, name='return'),
url(r'^cancel/$', views.cancel, name='cancel'),
url(r'^$', views.index, name='index'),
(r'^something/paypal/', include('paypal.standard.ipn.urls')),
)
PayPal's IPN won't call back to your local URL: http://127.0.0.1:8000/notify/
See their docs on IPN testing.
PayPal recommends coding your own test page with a form that submits directly to your notification endpoint. This could look like (from their docs):
<form target="_new" method="post" action="{% url 'notify' %}">
<input type="hidden" name="SomePayPalVar" value="SomeValue1"/>
<input type="hidden" name="SomeOtherPPVar" value="SomeValue2"/>
<!-- code for other variables to be tested ... -->
<input type="submit"/>
</form>
Once you have your app on in a sandbox environment somewhere, you can start using the IPN Simulator to test.
Related
I am creating a registration form in Django 2.1. In the typical examples people are using same views method both for showing forms and accepting POST request from forms like following:
In urls.py:
urlpatterns = [
path('auth/register', auth.register, name='register')
]
and in the view named auth.py:
from django.shortcuts import render
from blog_admin.forms import SignUpForm
from django.contrib.auth.forms import UserCreationForm
def register(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
# do registration stuff...
else:
form = SignUpForm()
return render(request, 'blog_admin/auth/register.html', {'form': form})
but I want to use separate method for showing the form and handling registration process and also want to use identical urlpatterns one with GET and one with POST functionality, like following:
in urls.py
urlpatterns = [
# can we limit it range, so that it only works for GET request
path('auth/register', auth.show_registration_form, name='register_show'),
# can we limit it range, so that it only works for POST request
path('auth/register', auth.register, name='register')
]
and in the view named auth.py:
from django.shortcuts import render
from blog_admin.forms import SignUpForm
from django.contrib.auth.forms import UserCreationForm
def show_registration_form(request):
form = SignUpForm()
return render(request, 'blog_admin/auth/register.html', {'form': form})
def register(request):
# do registration stuff...
If need some more example from other frameworks, in php Laravel it would have been done by following:
Route::get('auth/register', ['as' => 'register_show', 'uses' => 'Auth\AuthController#show_registration_form']);
Route::post('auth/register', ['as' => 'register', 'uses' => 'Auth\AuthController#register']);
After the user logs in i want to redirect to the view ('profile:profile_view')
settings.py
LOGIN_REDIRECT_URL = 'profile:profile_view'
I tried the above code but was not getting the result that i needed because iam passing slug into the url
urls.py
url(r'^(?P<slug>[-\w\d]+)/$', ProfileView.as_view(), name='view_profile'),
from here i tried the following.
settings.py
LOGIN_REDIRECT_URL = 'login_redirect'
urls.py
#login_required
def login_redirect(request):
return redirect('profile:profile_view', pk=request.user.pk, name=request.user.username)
Now i do get the username in the terminal but how do i use the username for the following 'localhost:8000/username'
views.py
class ProfileView(DetailView):
template_name = "profile/profile_view.html"
queryset = User.objects.all()
context_object_name = 'profile'
What am i doing wrong here? is there a better way?
Your profile URL accepts only one parameter called slug but you're passing it two parameters called pk and name.
First, change your URL like so:
url(r'^(?P<username>[-\w\d]+)/$', ProfileView.as_view(), name='view_profile'),
Now, correct the login_redirect view to make it look like this:
#login_required
def login_redirect(request):
return redirect('profile:profile_view', username=request.user.username)
You can also come in login in views.py and check and after that use httpresponseredirect to redirect user:
For examplele:
In urls.py :
From . Import views
Url(r'$login/', views.login, name="login"),
Url(r'$profile/', viesm.profile, name="profile"),
In views.py:
From django.shortcuts import get_object_or_404, render
From django.http import HttpResponseRedirect
Def login(request):
*** place to check if exist in your database***
If ***exist***:
User=request.post["username"]
Request.session["username"]=user
Return httpresponseredirect("../profile")
Else:
Return httpresponseredirect("../login")
Def profile(request):
If "user" in request.session:
Return render(request," **path to your template ", { "username" : request.session["username"] })
else:
Return httpresponseredirect("../login")
It should be better i think
This is a view written for my posts app in Django. The problem is that after filling the update form and submitting it happens successfully. But it creates confusion for the user because the same HTML page is there and how can I redirect into the updated object?
def post_update(request,id=None):
instance=get_object_or_404(Post,id=id)
if instance.created_user != request.user.username :
messages.success(request, "Post owned by another user, You are having read permission only")
return render(request,"my_blog/denied.html",{})
else :
form=PostForm(request.POST or None,request.FILES or None,instance=instance)
if form.is_valid():
instance=form.save(commit=False)
instance.save()
context={ "form":form,
"instance":instance }
return render(request,"my_blog/post_create.html",context)
As already suggested by #mdegis you can use the Django redirect function to redirect to another view or url.
from django.shortcuts import redirect
def view_to_redirect_to(request):
#This could be the view that handles the display of created objects"
....
perform action here
return render(request, template, context)
def my_view(request):
....
perform form action here
return redirect(view_to_redirect_to)
Read more about redirect here and here
You can pass positional or keyword argument(s) to the redirect shortcut using the reverse() method and the named url of the view you're redirecting to.
In urls.py
from news import views
url(r'^archive/$', views.archive, name='url_to_redirect_to')
In views.py
from django.urls import reverse
def my_view(request):
....
return redirect(reverse('url_to_redirect_to', kwargs={'args_1':value}))
More about reverse Here
You can use redirect from http shortcuts.
from django.shortcuts import redirect
def my_view(request):
...
object = MyModel.objects.get(...)
return redirect(object) #or return redirect('/some/url/')
Here is the link to official docs.
To redirect from a view to another view, you need to give the conbination of the app name "myapp", colon ":" and the view name "dest_view" which is set in the path in "myapp/urls.py" as shown below. And, you don't need to modify the path in "myapp/urls.py" if you pass data with session with request.session['key'] as shown below:
# "myapp/views.py"
from django.shortcuts import render, redirect
def redirect_view(request):
# Here
request.session['person'] = {'name': 'John', 'age': 27}
# Here
return redirect("myapp:dest_view")
def destination_view(request):
return render(request, 'myapp/index.html', {})
You need to give the view name "dest_view" to path() in "myapp/urls.py" as shown below:
# "myapp/urls.py"
from django.urls import path
from . import views
app_name = "myapp"
urlpatterns = [ # This is view name
path('dest/', views.destination_view, name="dest_view")
]
Then, this is Django Template:
# "myapp/index.html"
{{ request.session.person.name }} {# John #}
{{ request.session.person.age }} {# 27 #}
from django.urls import reverse
def my_view(request):
....
return redirect(reverse('url_to_redirect_to', kwargs={'args_1':value(object.id for specific id)}))
I have successfully built a custom user registration system as one module and I have one other module named article. I want to display the user logged in from my custom user registeration module in the templates of article module.
I'm using {{if user.is_authenticated}} display {{user}} to display the username in my templates.
I am able to access it in custom user registration templates but not in the articles templates. I want to display the username on the navbar which is same for both the apps.
what should i do so that the username is accessible in the entire project, not just in the template rendered.
I'm using django 1.8 and i have also tried creating a session variable in my views.py file but it also works in the same app.
views.py of the project
from django.shortcuts import render, render_to_response, RequestContext
from django.http import HttpResponseRedirect
from django.contrib import auth
from django.core.context_processors import csrf
from custom_user.forms import CustomUserCreationForm
from django.utils import timezone
def login(request):
c = {}
c.update(csrf(request))
return render_to_response('login.html', c)
def auth_view(request):
username = request.POST.get('username', '')
password = request.POST.get('password', '')
user = auth.authenticate(username=username, password=password)
if user is not None:
auth.login(request, user)
request.session['user_id'] = user.id
request.session['user_email'] = user.email
return render(request, "loggedin.html", {},context_instance=RequestContext(request))
else:
return HttpResponseRedirect('/accounts/invalid')
def loggedin(request):
return render_to_response('loggedin.html', {})
def invalid_login(request):
return render_to_response('invalid_login.html')
template base.py
<ul class="nav navbar-nav navbar-right">
<li>Subscribe</li>
{% if user.is_authenticated %}
<li>{{user}}</li>
<li>Logout</li>
{% else %}
<li>Login</li>
{% endif %}
</ul>
views.py of article app
from django.shortcuts import render
from django.http import HttpResponse
from django.template import RequestContext
from django.template.loader import get_template
from django.shortcuts import render_to_response
from django.conf import settings
from article.models import Article, Comment, Subscribers
from forms import ArticleForm, CommentForm, SubscriptionForm, ActivateSubscriberForm
from django.http import HttpResponseRedirect
from django.core.context_processors import csrf
from django.utils import timezone
from django.core.mail import send_mail
from random import randrange
from signup.views import *
# from .forms import RegistrationForm
# Create your views here.
def articles(request):
return render_to_response('articles.html',
{'articles':Article.objects.all().order_by('-id'),'last':Article.objects.earliest('-pub_date')})
def article(request, article_id=1):
return render_to_response('article.html',
{'article':Article.objects.get(id=article_id)})
When user is authenticated then loggedin.html is rendered and there i have created a link to go to articles app which uses the same base.py template.
You will be able to access authentication data if you've got the 'django.contrib.auth.context_processors.auth' processor in TEMPLATE_CONTEXT_PROCESSORS.
However, it is present by default - perhaps you've removed it?
Finally, the documentation is very helpful on that subject: https://docs.djangoproject.com/en/1.8/topics/auth/default/#authentication-data-in-templates
You haven't actually shown any code, but the problem is almost certainly how you are rendering the template. As Marcanpilami points out, the user variable is automatically added by the template context processors; but context processors are only run if you use a RequestContext to render your template. That means, these days, ensuring that you use the render shortcut, rather than render_to_response.
(For completeness sake, you can use render_to_response as long as you pass it context_instance=RequestContext, but it's almost always easier to just use render).
I am rendering the Django form data to a template but every time when i visit to the url it shows me this error:
_wrapped_view() takes at least 1 argument (0 given)
Method in views.py:
#login_required
def subnet_network_detail(request):
if request.method == 'POST':
form = NetworkCreateForm(request.POST)
if form.is_valid():
subnet = form.data['Subnet_Address']
ip = form.data['IP_Address']
user_hosts = get_hosts(user=request.user)
hosts_list = host_subnet(user_hosts,subnet,ip)
import pdb;pdb.set_trace()
extra_context = {
'hosts_list': hosts_list
}
return direct_to_template(request, 'networks/subnet_network.html',extra_context)
and urls.py:
url(r'^network/netmask/select/$',
'subnet_network_detail', name='subnet_network_detail')
I read from the other questions about this error but didn't get any idea. How to solve it?
direct_to_template is designed to be used in your urls.py:
url(r'^network/netmask/select/$', 'direct_to_template', {'template':'networks/subnet_network.html'}, name='subnet_network_detail')
You should be using render or render_to_response from within a view.
If you are using django 1.3 or later you can use:
from django.shortcuts import render
...
return render('networks/subnet_network.html', extra_context)
Or if you are using an earlier version:
from django.shortcuts import render_to_response
from django.template import RequestContext
...
return render_to_response('networks/subnet_network.html', extra_context, RequestContext(request))