Django duplicated url request: "home/home/' - django

I have code that works perfectly on localhost, but it is giving an error when placed on the server.
The point is that when I upload a file, it returns "base.com/home/home" (home twice = 404) instead of just "base.com/home" or the destination of the redirect.
Template:
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<input type="file" name="myfile">
<button type="submit">Upload</button>
</form>
View:
def login_page(request):
if request.user.is_authenticated:
return redirect('base-home')
form = UserLoginForm(request.POST or None)
nextr = request.GET.get('next')
if form.is_valid():
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
user = authenticate(username=username, password=password)
login(request, user)
if nextr:
return redirect(nextr)
return redirect('base-home')
return render(request, 'base/login.html', {'form': form})
#login_required
def home(request):
if request.method == 'POST':
return redirect('base-temp', 1)
return render(request, 'base/home.html', {'test': 'test'})
Url:
urlpatterns = [
path('', views.login_page, name='base-login'),
path('logout/', views.logout_page, name='base-logout'),
path('home/', views.home, name='base-home'),
path('temp/<int:pk>/', views.temp, name='base-temp')
]
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Project settings:
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
All other pages, media, statics are working fine. Only the post in this view.
I tried using action with ".", "/home/" and "{% url 'base-home'%}", but they all give the same 404 for duplicating the home url.
I also tried to create a separate view to handle the upload, but the error became "home/upload" instead of "upload".
I saw some similar questions in the stackoverflow, but I didn't find an answer that would work for me.
Any suggestion?
EDIT:
It works if I change the template to:
<form method="post">
{% csrf_token %}
<textarea name="text"></textarea>
<button type="submit">Send</button>
</form>
And the view to:
def home(request):
if request.method == 'POST':
return redirect('base-temp', 2)
return render(request, 'base/home.html', {'test': 'test'})
I'm not using django's forms.py.
That's it. Nothing else. Only the imports and a simple function view/template for base-temp.
Edit 2: Added more details about the views.
SOLUTION:
In case anyone else has the same problem, I leave the solution here, based on Maxwell O. Oyaro's answer.
I changed the home route to the empty path of the app urls.py:
urlpatterns = [
path('', views.home, name='base-home'),
path('logout/', views.logout_page, name='base-logout'),
path('temp/<int:pk>/', views.temp, name='base-temp')
]
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Then, I moved login path to the project urls.py:
...
from base import views as base_views
urlpatterns = [
path('admin/', admin.site.urls),
path('login/', base_views.login_page, name='login'),
path('', include('base.urls'))
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Check if your home is defined globaly for the django project or it is for the app itself.
Putting templates globally for the project and for the app alone can be confusing. If you have a templates for the project with home and you have another home template in the app calle home, it may not give you what you expect.
Just check keenly.

Related

Setting Up Logins For Users with Django

I am trying to use Django's built in user authentication for login/allowing users to create an account and login. I think there's something wrong with my urls or where files are placed in the project. Can anyone help?
I know the login.html file is supposed to be inside a folder called 'registration.' I think the fact that my templates are then in a sub folder called 'capstone' might be causing issues. I just don't know how to point to the right file when someone clicks to login.
In urls.py under 'weather' I have the following. In two tutorials I saw it should say 'accounts/' but I'm a bit confused as to why.
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('capstone.urls')), # medium site says to do this
path('accounts/', include('django.contrib.auth.urls')),
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
This is how my files are set up in Visual Studio Code:
Now under weather, I have:
Now under urls.py under capstone, I have:
router = routers.DefaultRouter()
router.register(r'locations', views.LocationViewSet)
urlpatterns = [
path('accounts/', include('django.contrib.auth.urls')),
path('api-auth/', include('rest_framework.urls',
namespace='rest_framework')),
path("", views.home, name="home"),
path("register", views.register, name="register"),
path("login", views.login_view, name="login"),
] + static(settings.STATIC_URL,
document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.STATIC_URL,
document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT)
views.py:
def home(request):
return render(request, "capstone/home.html")
def login_view(request):
if request.method == "POST":
email = request.POST["email"]
password = request.POST["password"]
user = authenticate(request, username=email,
password=password)
# Check if authentication successful
if user is not None:
login(request, user)
return HttpResponseRedirect(reverse('home'))
else:
return render(request, "capstone/login.html", {
"message": "Invalid email and/or password."
})
else:
return render(request, "capstone/login.html")
def register(request):
if request.method == "POST":
email = request.POST["email"]
# Ensure password matches confirmation - this part works!
password = request.POST["password"]
confirmation = request.POST["confirmation"]
if password != confirmation:
return render(request, "capstone/signup.html", {
"message": "Passwords must match."
})
# Attempt to create new user
try:
User = get_user_model()
user = User.objects.create_user(email, email,
password)
user.save()
except IntegrityError as e:
print(e)
return render(request, "capstone/signup.html", {
"message": "Email address already taken."
})
login(request, user)
return HttpResponseRedirect(reverse("home"))
else:
return render(request, "capstone/signup.html")
Setting the path to accounts/ allows you to create a url such as <your_site_name>/accounts/login
https://docs.djangoproject.com/en/3.2/topics/auth/default/#module-django.contrib.auth.views
Basicaly the link shows you get the login/, logout/, and a bunch other urls/views for free. You can append names to the url making it longer if you would like...
Now Im not sure which app the url_conf is in, that calls path('accounts/', include('django.contrib.auth.urls')), but I'm guessing since you have the static_dir addition at the bottom, its the weather/settings.py urls conf.
In settings.py in the TEMPLATES settings. If APP_DIRS is True, (which is by default), Django will check the template directory which is inside app directory that the template is being called in. In your case, it will check the template directory in the weather app (which is your main app). You would need to change your directory heiarchy.
Using django.contrib.auth urls
weather
|
|--templates
|
|--registration
|
|--login.html
If you want to use the capstone app. Then you need to move the call
path('accounts/', include('django.contrib.auth.urls')) to the capstone app. At which point the URL will change to <your_site_name/capstone/accounts/login>.
=============================
Now you have a login_view instead, named login which is overriding the login view of django contrib, so your heirachy should resemble something like this.
capstone
|
|--templates
|
|--capstone
|
| -- login.html
Also FYI make sure to end your paths to the URL’s with “/“. Like “login” should be “login/“

linking to the index.html to other html page in Django

I am new to the Django project.
I have been trying to create a situation in which, when a user presses the "Call us now" button in my nav-bar, it links them to other html pages (here: contact.html). How can I adjust what I have to achieve this?
Here are my files:
index.html
code: </ul><button class="btn btn-primary" type="button">call us now!</button></div>
views.py
from django.shortcuts import render
def index(request):
return render(request, 'jobs/index.html')
def contacts(request):
return render(request, 'jobs/contact.html')
in the urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('', jobs.views.index, name='index'),
path('contact/', jobs.views.contacts, name='contact'),] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)**
Change
href="contact.html"
To :
href="{% url 'contact' %}"

django form action url 'abc' is redirect to abc twice

In django index.html, I have below code
<form class="selectedPizza" action="{% url 'cost' %}" method="POST">
<!--Do some action here-->
<form>
In my app(order) urls.py
from django.urls import
from . import views
urlpatterns = [
path("", views.index, name="index"),
path("cost/", views.cost, name="cost")
]
In main site(pizza) urls.py
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path("", include("orders.urls")),
path("cost/", include("orders.urls")),
path("admin/", admin.site.urls),
]
In views.py
def index(request):
#some action here
return render(request, 'orders/index.html', context)
def cost(request):
if (request.method == 'POST'):
#some action here
return render(request, 'orders/cost.html', context)
After submitting the form I am redirected to "http://127.0.0.1:8000/cost/cost/".
I am learning Django and not able to find a possible way to get this form to redirect to cost.html page after submitting
I don't know why you have included "orders.urls" twice in your main urls. Remove the second one. "cost" is part of the included URL, you don't need it in the main one as well.

Django LOGIN_REDIRECT_URL failing when redirecting to the users profile

I'm using django-registration-redux and have most of it working. I'm trying to redirect to the user profile after login. Currently the URL for user profile is:
url(r'^user/(\w+)/$', views.profile, name='profile'),
...and the view for the profile is:
def profile(request, username):
user = get_object_or_404(User, username=username)
products = Product.objects.filter(user=user)
if not request.user == user:
return render(request, 'no.html')
else:
return render(request, 'profile.html', {'user':user,'products': products})
I've added LOGIN_REDIRECT_URL = 'profile' to settings.py but am getting the error:
Reverse for 'profile' with no arguments not found. 1 pattern(s) tried: ['user/(\\w+)/$']
I've gone around this so many times I'm totally confused. I could simply set LOGIN_REDIRECT_URL = 'home' and be done with it, but then I wouldn't have gotten past this error. Do I need to create a different view for this?
EDIT:
If I set LOGIN_REDIRECT_URL to 'home' or 'products' or any other URL it works - just not for 'profile'. Here's my urls.py:
urlpatterns = [
url(r'^$', views.HomePage.as_view(), name='home'),
url(r'^contact/$', views.contact, name='contact'),
url(r'^designers/', views.DesignersView.as_view(), name='designers'),
url(r'^subscribe/$', views.subscribe, name='subscribe'),
url(r'^products/$', views.products, name = 'products'),
url(r'^product/$', ProductListView.as_view(), name='product_list'),
url(r'^user/(\w+)/$', views.profile, name='profile'),
url(r'post_url/', views.post_product, name='post_product'),
url(r'^([0-9]+)/$', views.detail, name = 'detail'),
url(r'^like_product/$', views.like_product, name='like_product' ),
url(r'^profile/edit/$', views.edit_profile, name='edit_profile'),
url(r'^(?P<pk>\d+)/edit/$', PostUpdateView.as_view(), name='product-edit'),
url(r'^(?P<pk>\d+)/delete/$', PostDeleteView.as_view(), name='product-delete'),
]
I'm still searching - just not finding a solution, yet.
Finally found a way to do this. I created a login view in my views.py:
from django.contrib.auth.views import LoginView
class LoginView(LoginView):
def get_success_url(self):
return reverse('profile', args=[self.request.user.username])
Also added this to my urls.py to reflect the new view:
url(r'^accounts/login/$', LoginView.as_view(), name='login'),
Removed LOGIN_REDIRECT_URL from settings.py and it worked.
Your regex url isn't correct. Change:
url(r'^user/(\w+)/$', views.profile, name='profile'),
To
url(r'^user/(?P<username>[\w\-]+)/$', views.profile, name='profile'),

Django Authentication: Getting a blank screen

I am building my first django app that uses user authentication and I'm using
some examples I found on the web for reference. My examples use a method 'direct_to_template'.
The problem is that I get a blank screen when I use this. I know that the
template is in my templates directory.
Why am I getting a blank screen at login? How can I fix this?
The examples I'm using:
Example #1: https://docs.djangoproject.com/en/dev/topics/auth/
Example #2:
http://www.nerdydork.com/django-login-form-on-every-page.html
My code is below:
-------------base.html-------------
Here is the trigger it's in the header bar.
<li>Log-In</li>
--------- views.py -----------------------
from django.template import Context, loader
from django.conf.urls import patterns, url, include
from django.views.generic.simple import direct_to_template
from django.http import HttpResponse
VER = "1a" # Global I like to print; making sure my latest code is running.
def mylogin(request):
print "mylogin called [%s] " % VER
if request.method == 'POST':
user = authenticate(username=request.POST['username'],
password=request.POST['password'])
if user is not None:
if user.is_active:
login(request, user)
# success
return HttpResponseRedirect('/')
else:
# disabled account
return direct_to_template(request, 'inactive_account.html')
else:
# invalid login
return direct_to_template(request, 'invalid_login.html')
# User just clicked login
# *** I know this is getting called and I get a blank screen here ***
print "calling: direct_to_template('login.html')"
return direct_to_template(request, 'login.html')
def mylogout(request):
print "mylogout called"
logout(request)
return direct_to_template(request, 'logged_out.html')
--------- urls.py -----------------------
from django.conf.urls import patterns, include, url
from django.views.generic.simple import direct_to_template
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
(r'^customers/$', 'jim.views.index'),
(r'^customers/(?P<customer_id>\d+)/$', 'jim.views.detail'),
(r'^media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': '/media'}),
(r'^static/(?P<path>.*)$', 'django.views.static.serve', {'document_root': '/static'}),
(r'^login/$', 'jim.views.mylogin'),
(r'^logout/$', 'jim.views.mylogout'),
(r'^site_media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': '/media'}),
url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
url(r'^admin/', include(admin.site.urls)),
)
urlpatterns += patterns('django.views.generic.simple', (r'^accounts/login/$', 'direct_to_template', {'template': 'login_required.html'}),
)
--------- templates/login.html -----------------------
{% if user.is_authenticated %}
<!-- Authenticate account menu -->
{% else %}
<h3>Login</h3>
<form action="/login/" method="post" accept-charset="utf-8">
<label for="username">Username</label><input type="text" name="username" value="" id="username" />
<label for="password">Password</label><input type="password" name="password" value="" id="password" />
<p><input type="submit" value="Login"></p>
</form>
{% endif %}
Errr if your template is such
{% if user.is_authenticated %}
<!-- Authenticate account menu -->
{% else %}
stuff
{% endif %}
it seems pretty logical that your template is blank -_-
further more.. 200 is not an HTTP error it means 200 OK: Standard response for successful HTTP requests.
I have added a comment for you question asking for more details. But without those details my wild guess is that you need a view to display your "login.html" template.
You can write a sepearate view for that and put it in the urls.py. You can use the generic direct_to_template view in urls.py. Or you can modify your current "mylogin" view, for example:
def mylogin(request):
print "mylogin called [%s] " % VER
if request.method == 'POST':
user = authenticate(username=request.POST['username'],
password=request.POST['password'])
if user is not None:
if user.is_active:
login(request, user)
# success
return HttpResponseRedirect('/')
else:
# disabled account
return direct_to_template(request, 'inactive_account.html')
else:
# display login form
return direct_to_template(request, 'login.html')
The difference is in the indendation and in the last line (no POST data, means it's a GET request to display the login form).
But as I said, there are w few ways to handle it, mine is only a suggestion and I'm not going into any of your design decisions :)