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).
Related
I have a view for creating blog posts which redirects the user to a form to fill the blog post content like this:
from django.views import View
from app.models import BlogPost
class CreateBlogPost(View):
def post():
new_post = BlogPost.objects.create()
return redirect(reverse('post_edit'), args=[new_post.id])
class EditBlogPost(View):
...
And my urls are the following:
from django.urls import path
from app.views import CreateBlogPost
urlpatterns = [
path('post', CreateBlogPost.as_view(), name='post_create'),
path('post/<int:pk>/edit', EditBlogPost.as_view(), name='post_edit')
]
I would like to: test the CreateBlogPost by asserting that it redirects to post/<some_id>/edit.
I've tried: using the method assertRedirects from django's SimpleTestCase, but couldn't find a way to make this work.
I'm also using pytest-django, in case that's relevant.
my django-background-task does nothing, even if I just ask it to do something simple like printing a string.
I dont know what I am doing wrong though.
views.py:
from django.http import HttpResponse
from django.shortcuts import render, redirect
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.contrib.auth.forms import PasswordChangeForm
from django.contrib.auth import update_session_auth_hash
from .forms import UserRegistrationForm
from .models import Player, PlayerStats, TotalLevels
from django.core import management
from background_task import background
import random
# background task
#background(schedule=5)
def play_run():
print('it works!')
# management.call_command('runscript', 'runnerscript')
def random_logo():
logo = random.randint(1, 5)
logo_file = 'logo-nav'+str(logo)+'.png'
return logo_file
# Main website views
def home(request):
return render(request, template_name='main/home.html')
# bloxors website specific views
def homepage(request):
logo_file = random_logo()
return render(request, template_name='bloxors/homepage.html', context={'logo':logo_file})
# view in which background task is called
#login_required
def play_redirect(request):
play_run()
return HttpResponse('Please wait while we redirect you...')
Can someone help me by telling what is going wrong?
As always, I appreciate any and all answers!
While the server is running, open another terminal or command prompt with your virtual environment activated then run python manage.py process_tasks
https://django-background-tasks.readthedocs.io/en/latest/
I want the user not to navigate back once he is logged out. I used login_required(login_url = "/login/") before my definition of logout view in my views.py. I am still able to navigate back after logging out. How can I ask the user to log in again? Also, If I type URL for my home page (say localhost:8000/home) directly in the browser, I am able to access the page without login. How can I correct this issue?
I have cleared browser cache too and still, no use.
my views.py:
from django.shortcuts import render
from django.http import HttpResponseRedirect
from django.contrib import auth
from django.views.decorators import csrf
from django.contrib.auth.decorators import login_required
def login(request):
c={}
# c.update(csrf(request))
return render(request,'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)
return HttpResponseRedirect('/home')
#login_required(login_url='/login/')
def logout(request):
request.session.flush()
auth.logout(request)
return render(request,'logout.html')
If you want to protect your home page or other pages with login, you should decorate them with login_required decorator. For example,
#login_required(login_url='/login/')
def home(request):
# Your code goes here
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 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.