So I have a django project and there is one view(home view) which displays the posts of the followed users and that requires a user to be authenticated, if there is no user loged in, then the code returns a 'AnonimousUser' is not iterable error and I will like my code to redirect the anonymous user to the login page if the person is on the home view. After some investigation I realized that this can be done with a custom middleware but I dont know how to do it so currently that middleware just prints if a user is logged in or if it is anonymous. What can I do to Complete this middleware and get rid of that Anoniomus User error?
middleware.py
class LoginRequiredMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
return response
def process_view(self, request, view_func, view_args, view_kwargs):
if(request.user.is_authenticated):
print(Authenticated")
else:
print("Anonimous user")
views.py
def home(request):
user = Following.objects.get(user=request.user)
followed_users = [i for i in user.followed.all()]
followed_users.append(request.user)
contents = Post.objects.filter(user__in = followed_users)
context = {
"contents": contents,
}
print("nice")
return render(request, 'home.html', context)
urls.py
urlpatterns = [
path('', views.home, name='home'),
path('login', views.login, name='login'),
path('register', views.register, name='register'),
path('logout', views.logout, name='logout'),
path('<username>/', views.profile, name='profile'),
]
If you have any questions or need to see more code please let me know;)
There is no required to writing a custom middleware.
You can restrict the anonymous user in your view like this
def home(request):
if not request.user.is_authenticated:
return redirect ('your_login_url')
user = Following.objects.get(user=request.user)
followed_users = [i for i in user.followed.all()]
followed_users.append(request.user)
OR you can user login_required decorator
from django.contrib.auth.decorators import login_required
#login_required(login_url='your_login_url')
def home(request):
user = Following.objects.get(user=request.user)
followed_users = [i for i in user.followed.all()]
followed_users.append(request.user)
Well, the above answer contains the two solutions to your problem, you could also use django.contrib.auth.mixins, they are used for Class-based view. The links for documentation are
1.https://docs.djangoproject.com/en/3.0/topics/class-based-views/mixins/
2.https://docs.djangoproject.com/en/3.0/topics/auth/default/
One of the possible issue might be that you have set the action of login template form to redirect to some page e.g.
So, it never validates the login VIEW to proceed the authentication. If so, try to set action="" of login form and write the login view which renders the login.html template.
Related
I'm trying to redirect users who are already authenticated to the home page, so they can't access the login page while they are logged in.
This was easily doable for my registration page as its leveraging a function in views.py, but seems to be harder to do for the login page as its leveraging django.contrib.auth.urls (so without a function in views.py).
So my question is: how can I redirect users to a specific page without going through a view function? In this case, the mydomain.com/login/ page should redirect to mydomain.com when a users is already logged in.
urlpatterns = [
path('admin/', admin.site.urls),
path('', homepage),
path('registration/', registration),
path('', include('django.contrib.auth.urls')),
]
Inside your views.py
from django.contrib.auth.decorators import login_required
#login_required
def myview(request):
return render(request,'mypage.html')
and if you want to redirect user on home page if they are authenticated than do this
create a file named decorators.py
inside that create a view which will handle authenticated users
def unauthenticated_user(view_func):
def wrapper_func(request, *args, **kwargs):
if not request.user.is_authenticated:
return view_func(request, *args, **kwargs)
else:
return redirect('/')
return wrapper_func
it will check that if user is not authenticated it will call function which is passed as parameter else it will redirect user to home page
not you have to import decorators it in your views.py
from decorators import unauthenticated_user
and call it on your login function like this
#unauthenticated_user
def login(request):
return render(request,"login.html")
I'd like my login page to redirect a user to an instance of a page. Such an instance will be denoted as follows:
www.example.com/adminpage/username
This is what I have in my settings.py
LOGIN_REDIRECT_URL = 'leicunnadmin'
LOGOUT_REDIRECT_URL = 'login'
In the urls.py:
urlpatterns = [
path('', views.index, name='index'),
path('leicunnadmin/<str:user>', views.leicunnAdmin, name='leicunnadmin'),
]
The following is the code from the views.py script. My aim here was to check that the user is authenticated, get their username and append that to the URL. (The code)
#login_required
def leicunnAdmin(request, user):
username = None
User = get_user_model()
if request.user.is_authenticated:
username = request.user.username
get_logged_user = User.objects.get(username=user)
print('get_logged_user: '+username)
return render(request, 'leicunnadmin.html')
else:
return render(request, 'login')
Instead what I get when I log in is www.example.com/adminpage. When I type in the logged in username (www.example.com/adminpage/manuallytypedusername), it then redirects to the right page. Is there no way to automate this?
I am receiving this error:
TypeError at /auth/
authenticate() missing 1 required positional argument: 'request'
I am using Django and also Django Rest Framework.
The HTTP POST looks like this:
{
"username": "HelloUser",
"password": "Hello123"
}
VIEW
#csrf_exempt
#api_view(['POST'])
def authenticate(self, request):
print(request.data)
user = authenticate(username=request.data['username'], password=request.data['password'])
if user is not None:
return Response({'Status': 'Authenticated'})
else:
return Response({'Status': 'Unauthenticated'})
URLS
urlpatterns = [
url(r'^', include(router.urls)),
url(r'create/', views.create),
url(r'retrieve/', views.retrieve),
url(r'auth/', views.authenticate),
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]
Firstly you should not use the name of the view as authenticate as it is getting mixed with Django auth's authenticate
And second, you don't need self parameter in authentication view i.e. def authenticate_user(request)
Update your code like this:
VIEW
from django.contrib.auth import authenticate
#csrf_exempt
#api_view(['POST'])
def authenticate_user(request):
print(request.data)
user = authenticate(username=request.data['username'], password=request.data['password'])
if user is not None:
return Response({'Status': 'Authenticated'})
else:
return Response({'Status': 'Unauthenticated'})
And your urls.py will be updated as per the view's name:
URLS
urlpatterns = [
url(r'^', include(router.urls)),
url(r'create/', views.create),
url(r'retrieve/', views.retrieve),
url(r'auth/', views.authenticate_user),
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]
I'm using django's auth module to handle the user login, logout and registration in my website.
The problem is that when I register a new user, I new to redirect to another url, and then, since the model is created but doesn't automatically log in, I need to navigate to /login/ and log in manually.
I would like my site to do this automatically. By that I mean that:
You click on the register button in home.html. You fill in the form and submit it.
The website AUTOMATICALLY creates the new user model, logs you in and redirects you to home.html with the user logged in.
Urls.py looks like this:
from django.conf.urls import include, url, patterns
from django.contrib import admin
from django.conf import settings
from django.conf.urls.static import static
from django.contrib.auth import views as auth_views
from django.contrib.auth.forms import UserCreationForm
from browse.views import UserCreate
urlpatterns = patterns('',
url(r'',include('browse.urls')),
url(r'^$', 'browse.views.home_page', name='home'),
url(r'^admin/', include(admin.site.urls)),
url(r'^login/$', auth_views.login, {'template_name': 'browse/login.html'}),
url(r'^register/$', UserCreate.as_view(
template_name='browse/register.html',
form_class=UserCreationForm,
success_url='/register/'
)),
url(r'^logout/$', 'browse.views.logout_view', name='logout'),
url(r'^', include('django.contrib.auth.urls')),
) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
and views.py looks like this:
from django.shortcuts import render, redirect
from django.views.generic.edit import CreateView
from browse.models import Pattern
from django.contrib.auth.models import User
from django.contrib.auth import logout, login
class PatternCreate(CreateView):
model = Pattern
fields = ['name','description','license', 'xcheme', 'pictures', 'video']
class UserCreate(CreateView):
model = User
def post(self, request):
return login(request, User.objects.get(username=request.POST['username']))
def home_page(request):
return render(request, 'browse/home.html')
def pattern_detail(request, pk):
pattern = Pattern.objects.get(pk=pk)
return render(request, 'browse/pattern_detail.html', {'pattern': pattern})
def logout_view(request):
logout(request)
return redirect('/')
As you can see, when you GET /register/ the register form is rendered. When I POST to /register/, I want to execute the view as normally AND then add:
def post(self, request):
return login(request, User.objects.get(username=request.POST['username']))
But It looks like I'm overriding the default view instead of adding to it, because the model doesn't get saved, since I get this error:
Exception Value:
User matching query does not exist.
How can I fix it?
Thank you so much beforehand.
Okay, it was a really dumb question. Luckily, I could figure it out:
def post(self, request):
super(UserCreate, self).post(request)
login_username = request.POST['username']
login_password = request.POST['password1']
created_user = authenticate(username=login_username, password=login_password)
login(request, created_user)
return redirect('/')
All I had to do is call super() and the parent function is executed. Then, my code executes.
I am quite new in django.I would like to authenticate a user. But I am unable to do it using authenticate function. I have looked over authenticate function in django. and there it's always showing TypeError. I have used both unicode and string in separate time but always it's showing the TypeError.
Please any help will be appreciated.
I am attching my code below:
def loginTest(request):
if request.method == 'POST':
user = authenticate(username=request.POST['username'], password=request.POST['password'])
if user is not None:
login(request,user)
return HomePage(request)
else:
return HttpResponseRedirect('/login/')
def login(request):
return render_to_response('login.html', {}, context_instance=RequestContext(request))
#login_required(login_url='/login/')
def HomePage(req):
templ = get_template('HomePage.html')
variables = Context({})
output = templ.render(variables)
return HttpResponse(output)
First off, you're defining a "login" view yourself, so when you try to call login(request, user) (what I assume is Django's built in "login" function which sets the user session), it is instead calling your function:
def login(request):
return render_to_response('login.html',{},context_instance=RequestContext(request))
Second, where did the TypeError occur? I assume since you know the nature of the error you've gotten to the Django traceback error page, if you could post the "copy-and-paste view" of the traceback itself, that would be enormously helpful.
You're also doing some funky things with your views that can be easily cleaned up by some shortcut functions. :)
However, since the nature of your question is how to do authentication in Django, here is the base you need to implement a manual login process, mostly just taken from the relevant documentation:
views.py
from django.contrib.auth import authenticate, login
from django.contrib.auth.decorators import login_required
from django.shortcuts import render
def loginTest(request):
username = request.POST["username"]
password = request.POST["password"]
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
HttpResponseRedirect("/")
else:
HttpResponseRedirect("/login/")
#login_required(login_url="/login/")
def HomePage(request):
return render(request, "HomePage.html")
urls.py
from django.conf.urls import patterns, include, url
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
# Examples:
# url(r'^$', 'authtest.views.home', name='home'),
# url(r'^blog/', include('blog.urls')),
url(r'^admin/', include(admin.site.urls)),
url(r'^login/', 'django.contrib.auth.views.login'),
url(r'^', 'custom.views.HomePage'),
)
Also, for future reference, it would be helpful for you to post your entire script so we can see what you have imported at the top.