I have an app which is called sitepages which have three models I wanna pass their objects to a html page called listing.html which is inside templates/sitepages
the sitepages urls.py contains:
from django.views.generic import TemplateView
from django.urls import include
from django.urls import path
from sitepages import views
app_name = "sitepages"
urlpatterns = [
path("news-events-listing/", views.view, name='listing'),
]
the sitepages/views.py:
from .models import Listing, Details1, Details2
from django.template.response import TemplateResponse
def view(request):
return TemplateResponse(request, 'sitepages/listing.html', {
'first_pages': Details1.objects.all(),
'seconde_pages': Details1.objects.all(),
'listing_page': Listing.objects.first(),
})
in the root urls.py I added:
path("", include("sitepages.urls", namespace='sitepages'))
when I put in any template the following:
Listing
it redirects me to the url /news-events-listing but no page is found and it gives me 404 error...what am I doing wrong? why the template is not returned? I should mention that I'm using wagtail for the whole site (I don't know if it's related)
In your root urls.py, make sure your new line
path("", include("sitepages.urls", namespace='sitepages'))
appears before the path("", include(wagtail_urls)) line. The wagtail_urls pattern matches any URL path and passes it to Wagtail to be handled as a Wagtail page, so any patterns after it will never be reached.
I'm very very new to Python 3 and Django and I get to the following problem: I use a standard Template and now how to set it up when there is 1 view. But I don't get the code right for multiple views. I currently run the page locally
At the moment I have tried to change different orders within urlpatterns, and they do work when only 1 url in in there, but I can't get the second one in
views.py
from django.shortcuts import render, render_to_response
# Create your views here.
def index(request):
return render_to_response('index.html')
def store(request):
return render_to_response('store.html')
urls.py
from django.conf.urls import include, url
from django.contrib import admin
from myapp import views as views
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^store/$', views.store, name='store'),
url(r'^admin/', admin.site.urls)
]
urlpatterns += staticfiles_urlpatterns()
I would like the url pattern that lets me go to the index view and the store view
EDIT:
Full code is shared via: https://github.com/lotwij/DjangoTemplate
The error in the comments shows you are going to http:/127.0.0.1:8000/store.html, but your URL pattern url(r'^store/$', ...) does not include the .html, so you should go to http:/127.0.0.1:8000/store/.
The Django URL system uncouples the URL from the name of the template (sometimes the view doesn't even render a template!). You could change the regex to r'^store.html$ if you really want .html in the URL, but I find the URL without the extension is cleaner.
I was working with 2 applications that are within a DJango project: "customer" and "vendors". Each application has a HTML file named "testindex.html".
Whenever I typed:
http://myhost/customer/basic_info
the correct page would show up
If I typed
http://myhost/vendors/basic_info
the page from http://myhost/customer/basic_info would show up
I found out that it was due to caching (since both applications use "testindex.html"). So again, "testindex.html" is caching.
How can one get around this problem?
TIA
Details are listed below. I have the following views defined:
urls.py for the project
urlpatterns = [
... snip ...
url(r'^customer/', include('libmstr.customer.urls')),
url(r'^vendors/', include('libmstr.vendors.urls')),
]
views.py for customer
from django.shortcuts import render
def basic_info(request):
return render(request, 'testindex.html', {})
views.py for vendors
from django.shortcuts import render
def basic_info(request):
return render(request, 'testindex.html', {})
urls.py for customers
from django.conf.urls import url
from . import views
# list of templates
app_name = 'customer'
urlpatterns = [
url(r'^basic_info/$', views.basic_info, name='basic_info'),
]
urls.py for vendors
from django.conf.urls import url
from . import views
# list of templates
app_name = 'vendors'
urlpatterns = [
url(r'^basic_info/$', views.basic_info, name='basic_info'),
]
It sounds like you have two templates, customers/templates/testindex.html and vendors/templates/testindex.html.
When you call render(request, 'testindex.html', {}), the app directories template loader searches the templates directory for each app in INSTALLED_APPS, and stops the first time it finds a match. If customers is above vendors in INSTALLED_APPS, then it will always use the customers template.
For this reason, Django recommends that you name your templates customers/templates/customers/testindex.html and vendors/templates/vendors/testindex.html, and change your views to use customers/testindex.html and vendors/testindex.html. This way you avoid clashes.
I created a view for my model, with the corresponding urls and template files. Then, in the admin panel, I have created a Rich text page, specifying the same URL (ingredients) defined in urlpatterns. Mezzanine ignores the view, displays the template but does not pass the context.
How can I solve it?
These are the codes:
models.py
from django.db import models
from mezzanine.pages.models import Page
from django.utils.translation import ugettext_lazy as _
class Ingredient(Page):
name = models.CharField(max_length=60)
information = models.TextField(null=True, blank=True, verbose_name=_("Description"))
views.py
from django.template.response import TemplateResponse
from .models import Ingredient
def ingredients(request):
ingredients = Ingredient.objects.all().order_by('name')
templates = ["pages/ingredients.html"]
return TemplateResponse(request, templates, {'ingredients':ingredients})
urls.py
from django.conf.urls import url
from .views import ingredients
urlpatterns = [
url("^$", ingredients, name="ingredients"),
]
TemplateResponse does not expect the request in its arguments. See the docs.
return TemplateResponse(templates, {'ingredients':ingredients})
However I expect you meant to use the standard render function there:
return render(request, "pages/ingredients.html", {'ingredients':ingredients})
Ok, the solution has been define my app urls before any other definition in my project urls.py file.
project_name/project_name/urls.py
# Add the urlpatterns for any custom Django applications here.
# You can also change the ``home`` view to add your own functionality
# to the project's homepage.
urlpatterns = [
url(r'^ingredients/', include("apps.ingredients.urls")),
]
urlpatterns += i18n_patterns(
# Change the admin prefix here to use an alternate URL for the
# admin interface, which would be marginally more secure.
url("^admin/", include(admin.site.urls)),
)
I created my own view for login. However if a user goes directly to /admin it brings them to the admin login page and doesn't use my custom view. How can I make it redirect to the login view used for everything not /admin?
From http://djangosnippets.org/snippets/2127/—wrap the admin login page with login_required. For example, in urls.py:
from django.contrib.auth.decorators import login_required
from django.contrib import admin
admin.autodiscover()
admin.site.login = login_required(admin.site.login)
You probably already have the middle two lines and maybe even the first line; adding that fourth line will cause anything that would have hit the admin.site.login function to redirect to your LOGIN_URL with the appropriate next parameter.
While #Isaac's solution should reject majority of malicious bots, it doesn't provide protection for professional penetrating. As a logged in user gets the following message when trying to login to admin:
We should instead use the admin decorator to reject all non-privileged users:
from django.contrib.admin.views.decorators import staff_member_required
from django.contrib import admin
[ ... ]
admin.site.login = staff_member_required(admin.site.login, login_url=settings.LOGIN_URL)
To the best of my knowledge, the decorator was added in 1.9.
I found that the answer above does not respect the "next" query parameter correctly.
An easy way to solve this problem is to use a simple redirect. In your site's urls file, immediately before including the admin urls, put a line like this:
url(r'^admin/login$', RedirectView.as_view(pattern_name='my_login_page', permanent=True, query_string=True))
Holá
I found a very simple solution.
Just tell django that the url for admin login is handle by your own login view
You just need to modify the urls.py fle of the project (note, not the application one)
In your PROJECT folder locate the file urls.py.
Add this line to the imports section
from your_app_name import views
Locate this line
url(r'^admin/', include(admin.site.urls))
Add above that line the following
url(r'^admin/login/', views.your_login_view),
This is an example
from django.conf.urls import include, url
from django.contrib import admin
from your_app import views
urlpatterns = [
url(r'^your_app_start/', include('your_app.urls',namespace="your_app_name")),
url(r'^admin/login/', views.your_app_login),
url(r'^admin/', include(admin.site.urls)),
]
http://blog.montylounge.com/2009/07/5/customizing-django-admin-branding/
(web archive)
I'm trying to solve exactly this problem and I found the solution at this guys blog. Basically, override the admin template and use your own template. In short, just make a file called login.html in /path-to-project/templates/admin/ and it will replace the admin login page. You can copy the original (django/contrib/admin/templates/login.html) and modify a line or two. If you want to scrap the default login page entirely you can do something like this:
{% extends "my-login-page.html" %}
There it is. One line in one file. Django is amazing.
I had the same issue, tried to use the accepted answer, but has the same issue as pointed in the comment above.
Then I've did something bit different, pasting here if this would be helpful to someone.
def staff_or_404(u):
if u.is_active:
if u.is_staff:
return True
raise Http404()
return False
admin.site.login = user_passes_test(
staff_or_404,
)(admin.site.login)
The idea is that if the user is login, and tried to access the admin, then he gets 404. Otherwise, it will force you to the normal login page (unless you are already logged in)
In your ROOT_URLCONF file (by default, it's urls.py in the project's root folder), is there a line like this:
urlpatterns = patterns('',
...
(r'^admin/', include(admin.site.urls)),
...
)
If so, you'd want to replace include(admin.site.urls) with the custom view you created:
(r'^admin/', 'myapp.views.myloginview'),
or if your app has its own urls.py, you could include it like this:
(r'^admin/', include(myapp.urls)),
This is my solution with custom AdminSite class:
class AdminSite(admin.AdminSite):
def _is_login_redirect(self, response):
if isinstance(response, HttpResponseRedirect):
login_url = reverse('admin:login', current_app=self.name)
response_url = urllib.parse.urlparse(response.url).path
return login_url == response_url
else:
return False
def admin_view(self, view, cacheable=False):
inner = super().admin_view(view, cacheable)
def wrapper(request, *args, **kwargs):
response = inner(request, *args, **kwargs)
if self._is_login_redirect(response):
if request.user.is_authenticated():
return HttpResponseRedirect(settings.LOGIN_REDIRECT_URL)
else:
return redirect_to_login(request.get_full_path(), reverse('accounts_login'))
else:
return response
return wrapper
You can redirect admin login url to the auth login view :
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('', include('your_app.urls')),
path('accounts/', include('django.contrib.auth.urls')),
path('admin/login/', RedirectView.as_view(url='/accounts/login/?next=/admin/', permanent=True)),
path('admin/', admin.site.urls),
]
As of August 2020, django.contrib.admin.sites.AdminSite has a login_template attribute. So you can just subclass AdminSite and specify a custom template i.e.,
class MyAdminSite(AdminSite):
login_template = 'my_login_template.html'
my_admin_site = MyAdminSite()
Then just use my_admin_site everywhere instead of admin.site.