How do I add user data to url in Django? - python

I've got a function based view in Django called userView
#login_required(login_url='/login/')
def userView(request):
user = None
if request.user.is_authenticated():
user = request.user
user_id = user.pk
return render(request, "user_view.html", {'user': user})
and here's my URL for it
urlpatterns = [
url(r'^user/', userView, name='user'),
]
After my user has logged in, I'd like him to see his pk number in the URL. I.e., if the user's PK is 3 and the user directs their browser to www.myapp.com/user, the URL in the address bar should change to www.myapp.com/user/3/. How do I make that happen? I'm aware I need to edit the RegEx for the URL into
url(r'^user/(?P<user_id>[0-9]+)/$', userView, name='user')
but how do I pass the PK number to the URL?

I am not a Django expert but my guess is you want to redirect the user to his 'home page' after he is logged in. That can be done using the redirect() method
#login_required(login_url='/login/')
def userLoginView(request):
if request.user.is_authenticated():
return redirect("/user/{0}".format(request.user.pk), user=request.user)
And then define a second view that will render the home page
def userView(request, user_id=None, user=None):
return render(request, "user_view.html", {'user': user})
Also your url patterns should be as follows
urlpatterns = [
url(r'^user/', userLoginView, name='userlogin'),
url(r'^user/(?P<user_id>[0-9]+)/$', userView, name='user')
]

Related

How to order URLs in Django? I am getting `Page Not Found` error because of misplaced urls?

I am getting below error when I want to add a project or go to project_create URL.
Page not found (404)
Request Method: GET
Request URL: http://localhost:8000/project/add/
Raised by: projects.views.project_detail_view
the URL says /project/add/ that according to the view it must open project_create_view but the error is raised by detail view projects.views.project_detail_view.
This is the URL:
path('project/<slug:project_slug>/delete/',
project_delete_view, name='project_delete'),
path('project/<slug:project_slug>/update/',
project_update_view, name='project_update'),
path('project/<slug:project_slug>/',
project_detail_view, name='project_detail'),
path('projects/list/', all_projects_view, name='all_projects'),
path('project/add/', project_create_view, name='project_create'),
path('administration/', administration, name='administration'),
path("", home, name='home'),
if I comment this line path('project/<slug:project_slug>/',project_detail_view, name='project_detail'), then project_create URL goes to right view and right template. Why is this happening? I used different name, url and view name. Why is this happening?
Edit: I added both views
#login_required
def project_create_view(request):
if not request.user.is_superuser:
raise PermissionDenied
if request.method == 'POST':
form = ProjectForm(request.POST, request.FILES)
if form.is_valid():
title = form.instance.title
form.save()
project = get_object_or_404(Project, title=title)
messages.success(request, 'Project created successfully.')
return redirect(project.get_absolute_url())
form = ProjectForm()
return render(request, 'projects/project_create.html', {'form': form})
def project_detail_view(request, project_slug):
project = get_object_or_404(Project, slug=project_slug)
session_key = 'project_views{}'.format(project.slug)
if not request.session.get(session_key, False):
Project.objects.filter(id=project.pk).update(
visit_count=F('visit_count') + 1
)
request.session[session_key] = True
context = {
'project': project
}
return render(request, 'projects/project_detail.html', context)
Dynamic URLs must be on the bottom of the list,
urlpatterns = [
# Fixed URLs
path("", home, name='home'),
path('administration/', administration, name='administration'),
path('project/add/', project_create_view, name='project_create'),
path('projects/list/', all_projects_view, name='all_projects'),
# Dynamic URLs
path('project/<slug:project_slug>/',
project_detail_view, name='project_detail'),
path('project/<slug:project_slug>/delete/',
project_delete_view, name='project_delete'),
path('project/<slug:project_slug>/update/',
project_update_view, name='project_update'),
]
Ref: Django URL routing
You can order it by app, or by path, for example if you have more than one that starts with project you may group them in a different url pattern list.
projecturls =[
# your project path urls
]
urlpatterns =[
path('project/', include(projecturls)),
# ...
]

How do i set the current logged in user as default in Django view when no url parameters are given

i want the /profile/ route to be accessible without having to pass any url argument
This is my profile View:
#login_required
def profile(request, username):
ctx = {"username" : username}
return render(request, "raynet/profile.html",ctx)
This is my url pattern:
urlpatterns = [
path('', views.landing),
path('home/', views.home),
path('profile/', views.profile),
path('profile/<username>', views.profile),
path('apps/', views.apps),
path('signin/', views.signin),
path('signup/', views.signup),
path('testing/', views.testing),
path('signout/', views.signout),
]
It works fine if i specify a username in the url, but it doesnt work if i just go to /profile/
I want to get the current logged in user as default when no url variable is specified.
Try like this:
#login_required
def profile(request, username=None):
ctx = {"username" : username if username else request.user.username}
return render(request, "raynet/profile.html",ctx)
Here I am writing username parameter as keyword argument, so that username default value is None. Then using if else logic, I am assigning username value from argument or from request.user.username.

Restricting logged in user to access the front page of login and registration without log out

Like in facebook. after logging in users are prompted to user homepage. but it prevents the logged in users to going back to login page unless users logout. so how to prevent the logged in users from going back after loggin in
def register(request):
form = self.register_form(request.POST)
if request.method=='POST':
if form.is_valid():
user = form.save(commit=False)
firstName=form.cleaned_data.get('firstName')
lastName=form.cleaned_data.get('lastName')
username=form.cleaned_data.get('username')
email=form.cleaned_data.get('email')
password=form.cleaned_data.get('password1')
user.set_password(password)
user.save()
messages.success(request, f'Account successfully created!')
return redirect('login')
else:
form = UserRegisterForm()
return render(request, 'registration/register.html', {'form': form})
path('login/', auth_views.LoginView.as_view(template_name='registration/login.html',redirect_authenticated_user=True), name='login'),
# path('logout/', auth_views.LogoutView.as_view(template_name='registration/logout.html'), name='logout'),
path('register/', views.register, name='register'),
LOGIN_REDIRECT_URL = 'home:index'
LOGIN_URL = 'login'
LOGOUT_REDIRECT_URL = 'index'
Below are some option. try reading django doc https://docs.djangoproject.com/en/2.1/topics/auth/
Option 1
This can be one of the way. You check if the user is logged in and return suitable html page.
views.py
def home(request):
if not request.user.is_anonymous:
return render("home.html")
else:
return render("login.html")
Option 2
Check if the user is logged in , if so redirect to home page endpoint
from django.shortcuts import render, HttpResponseRedirect
from django.contrib.auth import login_required
def login(request):
if not request.user.is_anonymous:
return HttpResponseRedirect('/home')
#login_required
def home(request):
# Render you home page response
What you can do is redirect the user to the home page even if the user clicks the login/signup link.
For this you can do something in the login and signup views:
def login(request):
# if the user is already logged in, redirect to user home page
if request.user.is_authenticated:
# redirect to the home page
else:
# do something like defining get or post method request conditions
def signup(request):
# if the user is already logged in, redirect to user home page
if request.user.is_authenticated:
# redirect to the home page
else:
# do something like defining get or post method request conditions
This is one way to redirect the logged in user to the home page even if the user clicks the login/signup link or tries going back to the login page.

Django: redirect to view with parameters

I am using Django authentication. Whenever a user logs in, I want to redirect him to /profile/user_id, being user_id a number. I can get the value of user_id by request.user.profile.id. In settings.py I have LOGIN_REDIRECT_URL = 'app_1:index'
app_1/urls.py:
url(r'^profile/$', views.index, name='index'),
# ex: /profile/5/
url(r'^profile/(?P<user_id>[0-9]+)/$', views.profile, name='profile'),
app_1/views.py (things I've also tried are commented):
def index(request):
userid = request.user.profile.id
#return render(request, 'app_1/index.html', context)
#return profile(request, request.user.profile.id)
#return render(request, 'app_1/user_prof.html', {'user': request.user.profile.id})
#return redirect(profile, user_id= request.user.profile.id)
return redirect('profile', user_id=userid)
def profile(request, user_id):
user = get_object_or_404(Profile, pk=user_id)
return render(request, 'app_1/user_prof.html', {'user': user})
I must be missing something because this should be easy but I'm stuck on it. Thanks in advance.
EDIT: The error I'm getting is Reverse for 'profile' not found. 'profile' is not a valid view function or pattern name.: http://dpaste.com/270YRJ9
Try using this instead
from django.urls import reverse
return redirect(reverse('profile', kwargs={"user_id": userid}))
Or this:
return redirect('app_1:profile', user_id=userid)

DJANGO - Redirect to different page from POST with data

I am trying to have a simple form that once filled, will direct to a different webpage or remain on the same page if invalid. The page should have a text box and submit form and once a user enters anything it should direct you to a separate page.
My directory structure is as follows:
appName/
app/
forms.py
urls.py
views.py
templates/
app/
goodbye.html
name.html
library.html
thanks.html
appName/
settings.py
urls.py
My app/urls.py is as follows:
from django.conf.urls import url
from . import views
app_name = 'app'
urlpatterns = [
url(r'^$', views.index2, name = 'index'),
url(r'^hello/$', views.hello, name = 'hello'),
url(r'^goodbye/$', views.goodbye, name = 'goodbye'),
#url(r'^library$', views.library, name = 'library'),
url(r'^library/$', views.library, name = 'library'),
url(r'^library/(?P<book_id>[0-9]+)/$', views.book, name = 'book'),
url(r'^getname/$', views.get_name, name = 'get_name'),
url(r'^your-name/$',views.get_name, name='get_name'),
url(r'^thanks/$',views.say_thanks,name='thanks'),
#url(r'^thanks/(?P<name_id>[a-zA-Z]+)/$', views.say_thanks,name='thanks'),
]
My forms.py is :
from django import forms
class NameForm(forms.Form):
your_name = forms.CharField(label = 'Your name', max_length=100)
My app/views.py is:
from django.http import HttpResponse
from django.template import loader
from django.shortcuts import render
from django.http import HttpResponseRedirect
#forms
from .forms import NameForm
# Create your views here.
def index2(request):
return HttpResponse("hello world")
def hello(request):
text = """<h1>Welcome to my app! </h1>"""
return HttpResponse(text)
def goodbye(request):
template = loader.get_template("app/goodbye.html")
context = {
'output' : 'This is output from goodby views.py request handler'
}
return HttpResponse(template.render(context,request))
def library(request):
template = loader.get_template("app/library.html")
context = {
'output' : 'Welcome to the libary!!'
}
return HttpResponse(template.render(context, request))
def book(request, book_id):
return HttpResponse("You're looking at book %s. " % book_id)
def get_name(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = NameForm(request.POST)
# check whether it's valid:
if form.is_valid():
#process the data in form.cleaned_data as required
locationGo = "/thanks/"
template = loader.get_template("app/thanks.html")
return HttpResponse(template.render({'name':'name'},request))
else:
form = NameForm()
template = loader.get_template("app/name.html")
context = {'form': form}
return HttpResponse(template.render(context, request))
def say_thanks(request):
template = loader.get_template("app/thanks.html")
return HttpResponse(template.render({'name': 'name'},request))
My templates include:
name.html :
<form action = "/getname/" method = "post">
{% csrf_token %}
{{ form }}
<input type = "submit" value = "Submit" />
</form>
goodbye.html
<h1>Goodbye to Template Romance</h1>
Go Back
thanks.html
Thanks {{name}}!
What I would like is for:
A user to visit to : website.com/getname/ to show the name.html file (which it does)
If a user hits submit to stay on the same page (website.com/getname/) (which it doesn't - it gives: ValueError at /getname/ ->The view app.views.get_name didn't return an HttpResponse object. It returned None instead.
If a user enters in the submit field, to be redirected to website.com/thanks/ (which it sort of does. It currently loads the thanks.html template, but the URL stays on website.com/getname/)
Inside the get_name(request): function, the POST and GET if...else doesn't seem to be firing based on the Submit button, and it doesn't seem to be loading the correct page, OR change the current URL address once it gets processed. I have tried using HttpRedirect() which works, however, I would also like to pass the forms data (which is another issue).
Any suggestions would be a big help!
Your first problem is that you are not returning a response when the request method is post and the form is invalid. You can fix that by changing the indentation of your view, so that you always return a response at the end of your view.
def get_name(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
...
else:
form = NameForm()
template = loader.get_template("app/name.html")
context = {'form': form}
return HttpResponse(template.render(context, request))
If you want to redirect to the /thanks/ view, then you can use the redirect shortcut.
if form.is_valid():
return redirect('thanks')
Note that it isn't possible to redirect and pass the form data (see this question for an explanation). You should do any processing you want with the data before redirecting. You could use the messages framework to create a message 'Thanks <name>' before redirecting.
This works because you have name='thanks' in your url pattern.
You can simplify your views by using the render shortcut. Instead of
template = loader.get_template("app/name.html")
context = {'form': form}
return HttpResponse(template.render(context, request))
you can simply do:
return render(request, "app/name.html", context)
Remember to add the imports for the shortcuts:
from django.shortcuts import redirect, render

Categories