django template internal url concatenation - django

In my django project, I have URL patterns like below.
urls.py in project root:
urlpatterns = [
path('', include('blog.urls')),
]
urls.py in app(blog) root:
urlpatterns = [
path('', views.index, name='index'),
path(
'category/<str:category_id>',
views.category_view,
name='category_view',
),
]
What I want to do is making hyperlink for each category with django template. Something like below.
{% for category in categories %} .
<a href="{{ {% url 'index' %}|add: {% url 'category_view' category %} }} " class="nav">
{{category}}
</a>
{% endfor %}
However, it doesn't work. There are too many categories that I can't hard code any of them, but have to make url "(domain root)/category/(category name)" with django template. How can I concatinate two url in a template (as django does with
path(A, include(B))
)

You can define a get_absolute_url method in your Category model, it is a much cleaner solution: https://docs.djangoproject.com/en/2.1/ref/models/instances/#get-absolute-url
Implementation example:
from django.urls import reverse_lazy
# for django < 1.10 from django.core.urlresolvers import reverse_lazy
class Category(models.Model):
...
def get_absolute_url(self):
return reverse_lazy('category_view', category_id=self.id)
and in your template:
{% for category in categories %} .
<a href="{{ category.get_absolute_url }}" class="nav">
{{category}}
</a>
{% endfor %}

Related

Django: custom button in admin change form return bad url for custom view function

I have problems to link my custom button from change_form.html to my view function.
pic : admin change form custom button
change_form.html
{% extends "admin/change_form.html" %}
{% load i18n %}
{% block title %} Send Email {% endblock %}
{% block content %}
{% if request.resolver_match.url_name == 'requests_requests_change' %}
<div class="submit-row">
{% csrf_token %}
<a href="{% url 'requests:send-email' original.pk %}"
class="button" style="background-color: #F08000;float: left">Request Subscription
</a>
</div>
{% endif %}
{{ block.super }}
{% endblock %}
views.py
from django.shortcuts import render, redirect
def send_email(request, requests_id):
return redirect('') # or whatever to test the url
urls.py
from django.urls import path
from . import views
app_name = 'requests'
urlpatterns = [
path('<int:pk>/send-email/', views.send_email, name='send-email'),
]
main project urls.py
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('', admin.site.urls), # admin site administration
path('requests/', include('requests.urls')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
pic: error message
Any help would be great! Thanks!
I have found the solution on my own.
The issue was the url inside the template.
Worked with this one:
Template :
<a href="{% url 'admin:requests_requests_change' original.pk %}send-email/"
And the URL path:
path('<int:pk>/change/send-email/', views.send_email, name='send-email')

Django images not showing up

I've spent hours looking for a solution, figured I would post for myself. Django images won't show.
models.py:
class Item(models.Model):
...
image = models.ImageField(default='default.jpg', upload_to='item_pics')
urls.py
from django.urls import path
from . import views
from .views import ItemListView
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('', ItemListView.as_view(), name="site-home"),
]
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
html-file
{% extends "ui/base.html" %}
{% load static %}
{% block content %}
<ul>
{% for item in items %}
<li>
<p><img src="{{ item.image.url }}"></p>
<br>
</li>
{% endfor %}
</ul>
{% endblock content %}
It shows up like this:
When I copy image address, I get http://localhost:8000/media/default.jpg
There is no image at http://localhost:8000/media/default.jpg. Are you sure the path is correct? You uploaded way too little code. It seems like it should be http://localhost:8000/item_pics/default.jpg? Does that link work?
If I'm right, try this in models.py:
image = models.ImageField(default='default.jpg', upload_to='media')

Django: Reverse for '' not found. '' is not a valid view function or pattern name

I am doing an entry-level project and I met this problem.
urls.py of project:
urlpatterns = [
path('', TemplateView.as_view(template_name='welcome.html'), name='welcome'),
path('accounts/', include('login.urls')),
path('accounts/', include('django.contrib.auth.urls')), # use auth app
path('ride_sharing/', include('ride.urls')),
path('admin/', admin.site.urls),
]
urls.py of ride app:
app_name = 'ride'
urlpatterns = [
path('', views.home, name='home'),
path('requests/', views.view_requests, name='view_requests'),
path('new-request/', views.request_new, name='request_new'),
path('driver/', views.driver_home, name='driver_home'),
path('new-share-request/', views.sharer_request_new, name='sharer_request_new'),
]
views.py of ride app, just incomplete codes:
def home(request):
return render(request,'ride/home.html')
def view_requests(request):
return render(request, 'ride/home.html')
def request_new(request):
return render(request, 'ride/home.html')
def driver_home(request):
return render(request, 'ride/home.html')
def sharer_request_new(request):
return render(request, 'ride/home.html')
And home.html:
<!-- ride/templates/ride/home.html -->
{% extends 'ride/base.html' %}
{% block title %}HOmeeeeeeeeeee {% endblock %}
{% block content %}
{% if user.is_authenticated %}
Hi {{ user.username }}
<p>View My Requests</p>
<p>Request a Ride</p>
<p>Driver Entrance</p>
<p></p>
<p>Logout</p>
{% else %}
<p>Welcome to CJ & XY's Ride Sharing Service!</p>
login |
signup
{% endif %}
{% endblock %}
But after I login (I make LOGIN_REDIRECT_URL = 'home'), I get:
NoReverseMatch at /ride_sharing/
Reverse for 'view_requests' not found. 'view_requests' is not a valid view function or pattern name.
How could this happen? Could some give me the key? Thank you so much!
I see two issues with your URLs. First off when you include an app.urls file you should give it a namespace. This allows reverse to find the proper location of the urls.py file and makes your life easier. Your include URLs should look like.
path('ride_sharing/', include('ride.urls', namespace="ride")),
Second issue is that you did not provide the proper reverse for your LOGIN_REDIRECT_URL = "ride:home"
Then you should be good to go.

Reverse for 'register' not found. 'register' is not a valid view function or pattern name

I'm trying to make a simple app that uses the django built-in User model. I have created a registration page, but when I run the server, I get this error at the index page. Here's the code I'm using:
Registration.html
<!DOCTYPE html>
{% extends "basic/base.html" %}
{% block title_block %}
<title>Registration</title>
{% endblock title_block %}
{% block body_block %}
<div class="jumbotron">
{% if registered %}
<h1>Thank you for registering</h1>
{% else %}
<h1>Register here!</h1>
<h3>Fill out the form: </h3>
<form enctype="multipart/form-data" method="post">
{% csrf_token %}
{{userForm.as_p}}
{{profileForm.as_p}}
<input type="submit" value="Register" name="">
</form>
{% endif %}
</div>
{% endblock body_block %}
Views.py for the 'register' method
def register(request):
registered = False
if(request.method == 'POST'):
userForm = forms.UserForm(data=request.POST)
profileForm = forms.UserProfileInfoForm(data=request.POST)
if((userForm.is_valid()) and (profileForm.id_valid())):
user = userForm.save()
user.set_password(user.password)
user.save()
profile = profileForm.save(commit=False)
profile.user = user
if('profileImage' in request.FILES):
profile.profileImage = request.FILES['profileImage']
profile.save()
registered = True
else:
print(userForm.errors, profileForm.errors)
else:
userForm = forms.UserForm()
profileForm = forms.UserProfileInfoForm()
return render(request, 'basic/registration.html', {'userForm':userForm, 'profileForm':profileForm, 'registered':registered})
This is the urls.py for the project
from django.contrib import admin
from django.urls import path, include
from basic import views
urlpatterns = [
path('', views.index, name='index'),
path('admin/', admin.site.urls),
path('basic/', include('basic.urls', namespace='basic'))
]
This is the urls.py for the basic app
from django.urls import path
from . import views
app_name = 'basic'
urlpatterns = [
path('register/', views.register)
]
And the link to the page in base.html
<a class="nav-link" href="{% url 'basic:register' %}">Register</a>
What can cause the error here?
You must include a name argument to the register route.
path('register/', views.register, name='register')
https://docs.djangoproject.com/en/2.1/topics/http/urls/#reverse-resolution-of-urls
try this (inside your html file)
<a class="nav-link" href={% url 'basic:register' %}>Register</a>
and your urls.py (inside your app) as this:
urlpatterns = [
path('register/', views.register,name='register'),
]
this method worked for me I was fasing the same issue.

Django - How to get a form template to run (getting ' namespace not registered error ')

I am a newbie at Django.
Got Django 1.4.2 working with Python 2.7
on Windows 7.
I am following a tutorial and I need to get a form template appear
with radio buttons. Selecting a button sends data and the page should
ask you if you want to 'vote again?'. Also, if you do not select a button
and submit the form it should show a message asking you to make a choice.
So far,
here's the HTML form:
<h1>{{ poll.question }}</h1>
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
<form action="{% url 'polls:vote' poll.id %}" method="post">
{% csrf_token %}
{% for choice in poll.choice_set.all %}
<input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" />
<label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br />
{% endfor %}
<input type="submit" value="Vote" />
</form>
Now when I type http://localhost:8000/polls/1/ I should get the form, but instead I get the following error message:
NoReverseMatch at /polls/1/
u"'polls" is not a registered namespace
I registered polls as a namespace, see below in the project urls.py:
from django.conf.urls import patterns, include, url
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
url(r'^polls/', include('polls.urls', namespace="polls")),
url(r'^admin/', include(admin.site.urls)),
)
To answer cathy's kind request, here's the vote url:
from django.conf.urls import patterns, url
from polls import views
urlpatterns = patterns('',
url(r'^$', views.index, name='index'),
# ex: /polls/5/
url(r'^(?P<poll_id>\d+)/$', views.detail, name='detail'),
# ex: /polls/5/results/
url(r'^(?P<poll_id>\d+)/results/$', views.results, name='results'),
# ex: /polls/5/vote/
url(r'^(?P<poll_id>\d+)/vote/$', views.vote, name='vote'),
)
.. and below I include the project folder's urls if this could help:
from django.conf.urls import patterns, include, url
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
url(r'^polls/', include('polls.urls', namespace="polls")),
url(r'^admin/', include(admin.site.urls)),
# Uncomment the admin/doc line below to enable admin documentation:
# url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
)
And I just noticed the following error message shown on the browser (because Debug = True):
Error during template rendering
In template C:\Python27\Scripts\mysite\mytemplates\polls\index.html, error at line 4
u"'polls" is not a registered namespace
{% if latest_poll_list %}
<ul>
{% for poll in latest_poll_list %}
<li>{{ poll.question }}</li>
{% endfor %}
</ul>
{% else %}
<p>No polls are available.</p>
{% endif %}
Any help to make that form run properly will be appreciated!
urlpatterns = patterns('polls.views',
url(r'^$', 'index', name='index'),
url(r'^(?P<poll_id>\d+)/$', 'detail', name='detail'),
url(r'^(?P<poll_id>\d+)/results/$', 'results', name='results'),
url(r'^(?P<poll_id>\d+)/vote/$', 'vote', name='vote'),
)
{% url polls:detail poll.id %}
Go to your settings.py file and check out your template loaders. You may need to switch their order.
The correct order should be:
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
)
Hope this helps.
Try to put {% load url from future %} on the top of your html file. It should fix your problem.