I'm building a Django website, but my logout is not working. The site consists in two apps, the main app that is public and the student app that is private. In my student app i've put the #login_required decorator in every method, except the logout method. But when i click the logout link in the student app, my page is not redirected to the main app, it goes to another view inside the student app, and when i reload the page, the content is still available although i've put the #login_required decorator. Here is my code:
website/urls.py
from main_app import urls as main_urls
from student_app import urls as std_urls
urlpatterns = [
url(r'^index/', include(main_urls)),
url(r'^student-area/', include(std_urls))]
website/settings.py
LOGIN_URL = '/index/login/'
LOGIN_REDIRECT_URL = '/student-area/'
main_app/urls.py
...
urlpatterns = [
url(r'^$', views.index, name='index'),
...]
student_app/urls.py
...
urlpatterns = [
url(r'^$', views.std_videos_view, name='student_area'),
url(r'^(?P<video_key>[a-zA-Z0-9\_\.]+)/$', views.std_video_detail_view, name='video_detail'),
url(r'^materials-std/$', views.std_material_view, name='materials_std_view'),
url(r'^download-material/(?P<material_key>[a-zA-Z0-9\_\.]+)/$', views.std_material_download, name='download_material'),
url(r'^sims/$', views.std_sim_view, name='sims_view'),
url(r'^download-sim/(?P<sim_key>[a-zA-Z0-9\_\.]+)/$', views.std_sim_download, name='download_sim'),
url(r'^contact/$', views.std_contact_view, name='std_contact'),
url(r'^logout/$', views.user_logout, name='user_logout')
]
student_app/views.py
from django.contrib.auth import logout
from django.shortcuts import redirect
...
def user_logout(request):
logout(request)
return redirect('index')
student_app/templates/student_area.html
...
Logout
...
I am lost in this problem, thank you in advance.
Your video_detail URL pattern matches /logout/. Django stops as soon as it finds a match, so requests for /logout/ will be handled by the std_video_detail_view view instead of the user_logout view.
You can fix this by either changing the regex for the video_detail URL so that it doesn't clash (for example you could use ^videos/(?P<video_key>[a-zA-Z0-9\_\.]+)/$), or by moving the logout URL pattern above the video detail pattern.
Related
My main application is called lpbsmain, and I have another app called dashboard.
lpbsmain/urls.py includes path('main/', include('dashboard.urls')) in the urlpatterns variable.
dashboard/urls.py looks like...
from django.contrib import admin
from django.urls import path, include
from . import views
urlpatterns = [
#path('', views.dashboard, name='dashboard'),
path('<str:useremail>/', views.dashboard, name='main'),
path('base_dash/', views.base_dashboard, name='baseDash')
]
dashboard/views.py has two view functions, dashboard() and base_dashboard()
import requests, json
from django.shortcuts import render, redirect, HttpResponse
from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required
from django.contrib.auth import logout
def base_dashboard(request):
print("base dashboard view func print statement")
return render(request, "base-main-dashboard.html")
#login_required(login_url='/login')
def dashboard(request, useremail):
if request.user.is_authenticated:
# removed code in this conditional because it's not relevant
return render(request, "index.html", {'Past30Dates':json.dumps(past_30_dates), 'Past30Values':json.dumps(past_30_values), 'Past60Dates':json.dumps(past_60_dates), 'Past60Values':json.dumps(past_60_values), 'fullEmail':useremail, 'shortenedEmail':shortenedEmail})
else:
redirect("login")
The problem: So if you try to go to the url /main/base_dash, my intent is to see base-main-dashboard.html. Instead, I actually see index.html. From adding print statements, I see that whenever I go to the url /main/base_dash/, the view function dashboard(useremail) is actually being executed, not base_dashboard(). Normally, dashboard(useremail) gets executed from the url main/<useremail> as expected. But now it's also executing at that url and main/base_dash.
The only way this stops is if I remove path('<str:useremail>/', views.dashboard, name='main'), from dashboard/urls.py. Then, if I go to main/base_dash then only base_dashboard() gets executed.
If these view functions are mapped to two different urls, I don't get why going to one url is triggering the other. So are they mapped correctly or did I do something wrong?
Why would the existence of one url affect the other in this case?
I'm running django locally on a development server.
The order of urls, when django scans the url patterns it gives more importance to the 1st one
https://docs.djangoproject.com/en/3.1/topics/http/urls/#how-django-processes-a-request
-> In this case any url ( /main/base_dash ) will be matched against < str:useremail > and it checks out ( base_dash can be parsed as string )
Either refactor the url pattern ( which i recommend to be more good approach )
urlpatterns = [
#path('', views.dashboard, name='dashboard'),
path('base_dash/', views.base_dashboard, name='baseDash'),
path('email/<str:useremail>/', views.dashboard, name='main'),
]
or just try changing the order as follows.
urlpatterns = [
#path('', views.dashboard, name='dashboard'),
path('base_dash/', views.base_dashboard, name='baseDash'),
path('<str:useremail>/', views.dashboard, name='main'),
]
The problem is that you make a call to the link via the include and then add the extension again, and this does not work
try this
path('', include('dashboard.urls'))
res:
enter link description here
I hope someone could maybe help me, please :
I am quite new to Django and currently trying to implement a simple login/logout for a test page.
However, for some reasons, the Django does not generate the name of application in the href (so where it should be xxxx/main/register, it is only xxx/register).
But when I put the app name manually in the href in Pycharm, it generates it two times (so it becomes xxx/main/main/register).
So for this:
Logout
I got this url:
http://127.0.0.1:8000/logout/
If I write this:
Logout
I got this url:
http://127.0.0.1:8000/main/main/logout/
But I need to get this:
http://127.0.0.1:8000/main/logout/
It worked before, but from one minute to another, it suddenly stopped directing to the good path. And django does the same thing with every links in my site.
main/urls.py:
from django.urls import path
from . import views
app_name = 'main' # here for namespacing of urls.
urlpatterns = [
path("", views.homepage, name="homepage"),
path("register/", views.register, name="register" ),
path("logout/", views.logout_request, name="logout"),
]
main/views.py:
from django.shortcuts import render, redirect
from django.http import HttpResponse
from .models import Tutorial
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
from django.contrib.auth import logout, authenticate, login
from django.contrib import messages
def homepage(request):
return render(request = request,
template_name='main/home.html',
context = {"tutorials":Tutorial.objects.all})
def register(request):
if request.method == "POST":
form = UserCreationForm(request.POST)
if form.is_valid():
user = form.save()
username = form.cleaned_data.get('username')
messages.success(request, f"New account created: {username}")
login(request, user)
return redirect("main:homepage")
else:
for msg in form.error_messages:
messages.error(request, f"{msg}: {form.error_messages[msg]}")
else:
form = UserCreationForm
return render(request = request,
template_name='main/register.html',
context={"form":form})
def logout_request(request):
logout(request)
messages.info(request, "Logged out successfully!")
return redirect("main:homepage")
mysite/urls.py:
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path('polls/', include('polls.urls')),
path('main/', include('main.urls')),
path('admin/', admin.site.urls),
path('tinymce/', include('tinymce.urls')),
]
The behaviour you observe has nothing to do with Django, it's a basic html feature: in the first case you're using an absolute path (=> starting with a slash) for your href, in the second one you're using a relative path (NOT starting with a slash) so it's resolved relatively to the current url path whatever it is. You'd have the very same issue with plain static HTML.
This being said, in Django, you should never hardcode urls, but use the {% url <name> %} template tag (or the django.utils.reverse() function in Python code) instead, so you can change your urls in the urls.py files without breaking anything.
<a href="{% url 'logout' %}">
Use the name in href tag that will work.
You should use the url name in the template. It should solve the problem. Like this:
Logout
Or with namespacing:
Logout
i am a beginner to Django and i am unable to properly handle redirects from one app to another. I have 2 apps Accounts, Dashboard. Accounts Handles login and registration of AuthUser. Dashboard handles other functionality like Fileupload
So far, I have successfully using reverse() method have redirected from /accounts/login to my upload page but it redirects from /accounts/login to /accounts/upload instead of /dashboard/upload .
Project URLS
urlpatterns = [
path('dashboard/', include('Dashboard.urls')),
path('accounts/', include('Accounts.urls')),
path('admin/', admin.site.urls),
]
Account urls.py
urlpatterns = [
url('upload',DashboardViews.upload, name='upload'),
path('login', views.login, name='Login'),
path('register', views.register, name='Register'),
path('logout', views.logout, name='logout')
]
Account views.py
def login(request):
if request.method == 'GET':
return render(request, 'login.html')
if request.method == 'POST':
user_name = request.POST.get("username")
password = request.POST.get("password")
user = auth.authenticate(username=user_name,password=password)
if user is not None:
auth.login(request,user)
return redirect(reverse('upload'))
else:
print('Failed')
return render(request,'login')
My intention is whenever user (login/register), web page should redirect from /account/login to /dashboard/upload.
This is because you have the upload url defined in the urlpatterns of your Accounts app.
You should place it in the urls.py file from the Dashboard app if you want the full path to be /dashboard/upload, instead of /accounts/upload.
To explain it a bit more, when you define a path with the include function, like this:
path("accounts/", include("Accounts.urls")
All the urls from the Accounts app will have "accounts/" appended at the beginning.
Note: If you add the name parameter to a path, you can use it in all your apps with the reverse function. The path doesn't have to be declared in the same app where you want to call the reverse function.
A good practice to avoid having url conflicts is to add the name of the app to the url. So you should maybe name the upload path as dashboard_upload.
I faced the same problem, but below technique worked for me.
In your urls.py file of Dashboard app, use app_name = "Dashboard". then in your redirect() function use appName:Path structure. For example, use redirect('Dashboard:upload')
I have two apps in my django project. After loging the user in through "visit" app I redirect to "mainapp". However, my url patter becomes something like this : mysite/accounts/profile/
If I try specifying in urls.py I get redirected to "visit" app. How do I reset my url
visit/views.py
def profile(request):
return HttpResponseRedirect(reverse("main:home"))
main/urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'accounts/profile', views.home, name='home'),
]
main/views.py
def home(request):
return render(request, 'main/home.html')
You could try specifying redirect url in your settings.py file. Just include LOGIN_REDIRECT_URL = /mainapp/accounts/profile/ in that file and it should work. LOGOUT_REDIRECT_URL is also something you can list in your settings file to specify where to redirect after user logout.
I have created a page where a user can add a new item (notes in this case) and I am making use of CBV which I have recently started learning.
This is my model form
class NoteForm(forms.ModelForm):
class Meta:
model = Note
fields = ('title', 'note', 'tags')
This is the view in views.py
class NoteCreate(CreateView):
model = Note
form_class = NoteForm
template_name = "add_note.html"
Then this is the url as I used in the urls.py of the app
from django.conf.urls import patterns, url
from . import views
from madNotes.views import NoteCreate, NoteIndex,
urlpatterns = patterns(
'',
url(r'^notes/add/$', NoteCreate.as_view(), name="new_note"),
url(r'^$', NoteIndex.as_view()),
url(r'^(?P<slug>\S+)/$', views.NoteDetail.as_view(), name="entry_detail"),
)
NB: I used the same url as the main page at 127.0.0.1:8000 in the projects urls.py file and it worked.
I have seen several tutorials and even the docs and can't seem to find what I am doing wrong. Will I also need to add a function in order for it to be saved in the db or the CBV will do it all?
EDit: The error I get is this
Page not found (404)
Request Method: GET
Request URL: http://127.0.0.1:8000/notes/add/
Here is the project's urls.py
from django.conf.urls import patterns, include, url
from django.contrib import admin
from MadNotez import settings
from registration.backends.default.views import RegistrationView
from madNotes.forms import ExRegistrationForm
if settings.DEBUG:
import debug_toolbar
urlpatterns = patterns('',
url(r'^__debug__/', include(debug_toolbar.urls)),
url(r'accounts/register/$', RegistrationView.as_view(form_class = ExRegistrationForm), name='registration_register'),
url(r'^accounts/', include('registration.backends.simple.urls')),
url(r'^admin/', include(admin.site.urls)),
url('^markdown/', include('django_markdown.urls')),
url('^notes/', include('madNotes.urls')),
#url(r'^$', views.NoteCreate.as_view(), name="new note"), when I used it here it worked
)
you say that is the urls.py of the app, which means it is included by the project's urls.py.
As you show now, all the app's URIs go under the notes prefix:
url('^notes/', include('madNotes.urls')),
so as things stand at present the correct URI for the page is
http://127.0.0.1:8000/notes/notes/add/
In order to clean things up a bit, I'd suggest to modify the app's urls.py to
url(r'^add/$', NoteCreate.as_view(), name="new_note"),
so that the page can be reached at
http://127.0.0.1:8000/notes/add/
This way all the app's pages/services are available under the notes prefix and with a simple name that is consistent with their action (i.e. add, delete, etc)