Django: How can i get the url of a template by giving the namespace? - django

While i'm rendering a template i would like to retrieve the url of the template by giving the namespace value and not the path. For example instead of this:
return render(request, 'base/index.html', {'user':name})
i would like to be able to do the following:
from django.shortcuts import render
from django.core.urlresolvers import reverse
return render(request, reverse('base:index'), {'user':name})
but the above produces an error. How can i do it? Is there any way to give the namespace to a function and get the actual path?
Extended example:
- urls.py
from django.conf.urls.defaults import patterns, include, url
urlpatterns = patterns('',
url(r'^', include('base.urls', namespace='base')),
)
- app base: urls.py
from django.conf.urls.defaults import patterns, url
urlpatterns = patterns('base.views',
url(r'^/?$', 'index', name='index'),
)
- app base: views.py
from django.shortcuts import render
from django.core.urlresolvers import reverse
def homepage(request):
'''
Here instead of 'base_templates/index.html' i would like to pass
something that can give me the same path but by giving the namespace
'''
return render(request, 'base_templates/index.html', {'username':'a_name'})
Thanks in advance.

Template names are hard coded within the view. What you can also do is that you can pass the template name from the url pattern, for more details see here:
from django.conf.urls.defaults import patterns, url
urlpatterns = patterns('base.views',
url(r'^/?$', 'index',
{'template_name': 'base_templates/index.html'},
name='index'),
)
Then in view get the template name:
def index(request, **kwargs):
template_name = kwargs['template_name']

Related

onw of my two app is not working in django

Below is my code. In my hello_world project there is two app pages. one is home page and another is profile page. home page is working fine, but profile page is showing error.
hello_world urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('',include('home_page.urls',)),
path('profile_page',include('profile_page.urls',))
]
home page urls.py
from django.contrib import admin
from django.urls import path
from . import views
urlpatterns = [
path('admin/', admin.site.urls),
path('',views.home,name='home page'),
]
home page views.py
from django.http import HttpResponse
def home(request):
return HttpResponse('home page')
profile page urls.py
from django.contrib import admin
from django.urls import path
from . import views
urlpatterns = [
path('admin/', admin.site.urls),
path('profile_page',views.profile,name='profile page'),
]
profile page views.py
from django.http import HttpResponse
def profile(request):
return HttpResponse('profile page')
You need to use redirect method and include view name space as an argument..
Find the updated code:
from django.http import HttpResponse
def profile(request):
return redirect('profile page')
Don't forgot to import redirect...
The first argument of the path() function, i.e. the 'route' argument, must end with a forward slash.
path('profile_page/',include('profile_page.urls',))
Notice the forward slash at the end of the first argument, 'profile_page/'.
Your URLconf is not matching the expected pattern because of the missing slash.

Pass a file path as a URL parameter in Django

I'm using Django to create a webapp. When a user press on a certain button, it needs to pass a file path as parameter and a string parameter to one of my views. I can't simply use the parameter in the URL since the path contains several '/'. The way I have it setup right now is as follows:
parameters.py
class FilePathConverter:
regex = '^[/]'
def to_python(self, value):
value=str(value)
return value.replace("?", "/")
def to_url(self, value):
value=str(value)
return value.replace("/", "?")
urls.py
from django.urls import path
from . import views
from django.contrib import admin
from django.views import generic
from django.urls import path, register_converter
from . import converters, views
register_converter(converters.FilePathConverter, 'filepath')
urlpatterns = [
path('', views.index, name='webpanel-index'),
path('controlserver/<filepath:server_path>/<str:control>', views.index, name='controlserver'),
]
views.py
from django.shortcuts import render
from django.http import HttpResponse
from .models import Server
from django.contrib.auth.decorators import login_required
import subprocess
def controlserver(request, server_path, control):
if request.POST:
subprocess.call(['bash', server_path, control])
return render(request, 'index.html')
However, with this method, I get this error:
Reverse for 'controlserver' with keyword arguments '{'server_path': 'rien/', 'control': 'start'}' not found. 1 pattern(s) tried: ['controlserver/(?P<server_path>[^/]+)/(?P<control>[^/]+)$']
you can use Slug to resolve this patterns by :
from django.utils.text import slugify
path('controlserver/use slug .....', views.index, name='controlserver'),
but you need to put slug at views and templates So check this list of slug and pk :
https://github.com/salah-cpu/migration/blob/master/PATH_slug_pk

Django 1.10: Redirect to another view or url not working. django.urls.exceptions.NoReverseMatch

In Django 1.10, My redirect to other view via url or the viewname is not working.
The main urls.py file is as below:
urlpatterns = [
url(r'^', include('app1.urls')),
]
The urls.py file inside app1 is:
from django.conf.urls import url
from . import views
app_name = 'app1'
urlpatterns = [
url(r'^$', views.home, name='home'),
url(r'^details/$', views.details, name='details'),
]
The views.py for app1 is as below:
from django.shortcuts import render, redirect
from django.utils.timezone import now
import datetime
from django.http import HttpResponse, HttpResponseRedirect
from django.urls import reverse
def home(request):
if request.method == 'POST':
print("redirected from home..................")
url = reverse('details')
return HttpResponseRedirect(url)
# return redirect('app1:details')
# return redirect('/details/')
# return redirect('details')
print("Not redirected..................")
return render(request, "app1/index.html", {})
def details(request):
print("Redirect OK inside details")
today = datetime.date.today()
return render(request, "app1/details.html", {
'today': today,
'now': now(),
'email_text': request.POST.get('email_item', 'bla bla'),
})
I tried all the options in the home view with the commented code like using both HttpResponseRedirect and redirect but not able to redirect to the details view.
I get the error:
django.urls.exceptions.NoReverseMatch: Reverse for 'details' with
arguments '()' and keyword arguments '{'request': <HttpRequest>}' not found. 0 pattern(s) tried: []
Any suggestions would help:
I'm sure you found a solution long ago, but I've struggled with this problem before and I came up with a simple solution that doesn't require you to create a view that exists solely to redirect you to another view. Hopefully it helps some people out who need this question answered still. In general, it goes like this:
from django.shortcuts import redirect
urlpatterns = [
url(r'^$', lambda request: redirect('my_redirect_url_name')),
url(r'^my_redirect_url/$', views.redirect_view, name='my_redirect_url_name'))
]
I'm not sure why, but this does not work if you only pass redirect(); it must be contained within a function such as a lambda function.
If you want to do something as simple as redirect them to the login page you can use the login_required decorator or another a custom login lambda function:
from django.shortcuts import redirect
from django.contrib.auth.decorators import login_required
urlpatterns = [
url(
r'^$',
login_required(lambda request: redirect('my_redirect_url_name'),
redirect_field_name='my_login_url_name')
),
# this custom redirect function will behave like login_required()
url(
r'^$',
lambda request: redirect('my_redirect_url_name') if request.user and \
request.user.is_authenticated() else redirect('my_login_url_name')
),
url(r'^my_redirect_url/$', views.redirect_view, name='my_redirect_url_name')),
url(r'^my_login_url/$', views.login_view, name='my_login_url_name'))
]
Specifically in answer to your question, I think this will give the redirect you want. This in urls:
from django.shortcuts import redirect
urlpatterns = [
url(
r'^$',
lambda request: redirect('index') if request.method == 'POST' else \
redirect('details'),
name='home'
),
url(r'^details/$', views.details, name='details'),
url(r'^index/$', views.index, name='index'),
]
With this added to views:
def index(request):
return render(request, "app1/index.html", {})
Just FYI, I have not tested this with a redirect using if request.method == 'POST', but I think it will work.
Note the working example within your own code.
By specifying the app name you need to use namespacing with reverse.
reverse('details')
should read
reverse('app1:details')
See the documentation over here:
https://docs.djangoproject.com/en/1.10/ref/urlresolvers/

Django reverse causing url circular import, why?

I get this error:
The included urlconf 'fouraxis.urls' does not appear to have any
patterns in it. If you see valid patterns in the file then the issue
is probably caused by a circular import.
I know the url pattern has something in it, it looks like this:
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r'^perfil/', include('clientes.urls'), namespace="cliente"),
url(r'^admin/', include(admin.site.urls))
]
clientes.urls:
from django.conf.urls import url
from django.contrib.auth import views as auth_views
from clientes import views
urlpatterns = [
# login
url(r'^login/$', auth_views.login, {'template_name': 'perfiles/login.html'}, name="login"),
url(r'^logout/$', auth_views.logout, {'template_name': 'perfiles/logged_out.html'}, name="login"),
url(r'^mi_perfil/$', views.mi_perfil, name="mi_perfil"),
url(r'^registro_usuario/$', views.RegistroUsuario.as_view(), name="registro_usuario")
]
The RegistroUsuario view looks like this:
class RegistroUsuario(FormView):
template_name = "perfiles/registro_usuario.html"
form_class = UserCreationForm
success_url = reverse("cliente:mi_perfil") # THIS REVERSE
def form_valid(self, form):
return redirect("cliente:mi_perfil")
context = {'form': UserCreationForm}
I understand I can replace the reverse with a plain-text url like this perfil/mi_perfil. But, I want to know why is this happening with reverse, I can't find the explanation on de docs. Also, using reverse is better cause it is dynamic (if anytime I change the url, it still works as long as it keeps its name).
The reverse() call is made when the view is imported, which is probably when the urlconf is first loaded. You need to use reverse_lazy() instead:
from django.core.urlresolvers import reverse_lazy
class RegistroUsuario(FormView):
template_name = "perfiles/registro_usuario.html"
form_class = UserCreationForm
success_url = reverse_lazy("cliente:mi_perfil") # THIS REVERSE
def form_valid(self, form):
return redirect("cliente:mi_perfil")
context = {'form': UserCreationForm}

Django RequestContext and media doesnt work

I'm beginner, but I've been looking everywhere for solution. I can't see uploaded images (404).
Error from image link (for example:http://192.168.1.1:8000/media/portfolio/icon.png/ -> by the way, this proper url ) :
No SuperPages matches the given query.
SuperPages is my model which contains url object.
I configured everything for media files like here: http://www.muhuk.com/2009/05/serving-static-media-in-django-development-server/. And to be clear, when I'm using generic views only, it works great. But with views, I can't see images (links to images are fine). Static files works great. So this is my code:
urls.py
from mysite.cms.views import superpages
urlpatterns = patterns('',
(r'^(?P<url>.*)$', superpages),)
views.py
from django.template import loader, RequestContext
from mysite.cms.models import SuperPages
from django.shortcuts import get_object_or_404
from django.http import HttpResponse, HttpResponseRedirect
DEFAULT_TEMPLATE = 'default.html'
def superpages(request, url):
if not url.endswith('/') and settings.APPEND_SLASH:
return HttpResponseRedirect("%s/" % request.path)
if not url.startswith('/'):
url = "/" + url
f = get_object_or_404(SuperPages, url__exact = url)
t = loader.get_template(DEFAULT_TEMPLATE)
c = RequestContext(request, {
'superpages': f,
})
return HttpResponse(t.render(c))
There's something wrong with your urls.py. I suppose you have defined your patterns like this:
urlpatterns = patterns('',
(r'^(?P<url>.*)$', superpages),
(r'^media/(?P<path>.*)$',
'django.views.static.serve',
{'document_root': settings.MEDIA_ROOT}),
)
A URL such as http://192.168.1.1:8000/media/portfolio/icon.png/ matches the first pattern so your superpages view is called and raises a 404. What you need to do is put your catch-all superpages pattern at the very end of your urlpatterns. Or you can choose a different approach with a middleware, see what django.contrib.flatpage does for an example.