Search controller is fetching the wrong template in Django - django

I'm trying to write the controller to search for articles. But the search does not find anything and a template appears that is not specified in the views.py.
# views.py
class SearchView(ListView):
template_name = 'search_view.html'
def get_queryset(self):
query = self.request.GET.get('q')
object_list = Article.objects.filter(Q(title__icontains=query))
return object_list
# urls.py
urlpatterns = [
path('', ArticlesList.as_view(), name='list_view'),
path('<tag>/', ArticlesByTagsList.as_view(), name='articles_by_tags'),
path('articles/<slug:slug>', ArticleDetail.as_view(), name='detail_view'),
path('articles/create/', ArticleCreate.as_view(), name='create_view'),
path('articles/<slug:slug>/', ArticleUpdate.as_view(), name='update_view'),
path('articles/<slug:slug>/delete/', ArticleDelete.as_view(), name='delete_view'),
path('search/', SearchView.as_view(), name='search_view'),
]
#search_view.html
{% extends 'layout/basic.html' %}
{% block content %}
{{ object_list }}
{% endblock %}
The form looks like this
<form action="{% url 'articles:search_view' %}" method="get">
<input type="text" name="q" placeholder="Search...">
</form>
What am I doing wrong?

You should enumerate over the objects, so:
{% extends 'layout/basic.html' %}
{% block content %}
{% for object in object_list %}
{{ object.title }}
{% endfor %}
{% endblock %}
You should also specify the search/ path before the <tag>/ path, since Django always takes the item that first matches, and if you write search/ then it would first match with the <tag>/ and thus not fire the SearchView.
The urlpatterns thus should look like:
urlpatterns = [
# &downarrow; first specify the search/ path
path('search/', SearchView.as_view(), name='search_view'),
path('<tag>/', ArticlesByTagsList.as_view(), name='articles_by_tags'),
]
an effect of this, is that you can not use search as a tag. If you should be able to visit the articles_by_tags with search as tag, you should define non-overlapping patterns, so:
urlpatterns = [
path('search/', SearchView.as_view(), name='search_view'),
path('tag/<tag>/', ArticlesByTagsList.as_view(), name='articles_by_tags'),
]

Related

Django using URL parameters in template

I need to redirect to another page with same url parameters so I don't understand how to use url parameters in current template to redirect.
dborg.html:
{% extends './frame.html' %}
{% block content %}
Создать нового пользователя
{% csrf_token %}
{{form}}
{% for i in o %}
<p><a href='{% url "view_user" i.id %}'>{{i.fld}}</a></p>
{% endfor %}
{% endblock %}
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.main, name='main'),
path('view_org/<str:orgtype>/<str:deg>',
views.view_org_db, name='view_org'),
path('token/<str:orgtype>/<str:deg>', views.get_token, name='token'),
path('token/<str:orgtype>', views.get_token, name='token'),
path('create/<str:orgtype>/<str:deg>',
views.create_user, name='create_user'),
path('search/', views.search_user, name='search_user'),
path('report/', views.view_report, name='view_report'),
path('view/<int:id>', views.view_user, name='view_user')
]

Django passing data through the url, not finding page in url patterns

I'm trying to pass an object's id through the url, but its not able to find the page even after it tries the path when it goes through its patterns
Error:
Using the URLconf defined in GroomingService.urls, Django tried these URL patterns, in this order:
admin/
[name='Home']
appointment-Maker/
account/
admin-home
view_appointment/<id>/
login/ [name='Login Page']
registration/ [name='Registration Page']
logout [name='Logout Page']
The current path, adminview_appointment/21/, didn’t match any of these.
GroomingService.urls
#urls
urlpatterns = [
path('admin/', admin.site.urls),
path('', Home_view, name="Home"),
path('appointment-Maker/', include('appointmentApp.urls')),
path('account/', include('accountApp.urls')),
path('admin-home', include('adminApp.urls')),
path('view_appointment/<id>/', viewAppointment_view), #this is the page it is not finding
path('login/', Login_view, name='Login Page'),
path('registration/', Registration_view, name='Registration Page'),
path('logout', Logout_view, name='Logout Page')
]
adminApp/views.py viewAppointment_view
def viewAppointment_view(request, id):
appointments = Appointment.objects.get(id = id)
context = {
'appointments' : appointments
}
return render(request, "admin_templates/viewappointment.html", context)
templates/admin_templates viewappointment.html
{% extends 'base.html' %}
{% block content %}
<a>appointment view</a>
{% endblock %}
templates/admin_templates adminhome.html (the link is clicked through this page)
{% extends 'base.html' %}
{% block content %}
<a>this is the admin page</a>
<br>
{% for a in appointments %}
Client name:{{a.client_dog_name}}<br> {% comment %} this is the link that is clicked {% endcomment %}
{% endfor %}
<br>
<a>find month</a>
<form method="POST">
{% csrf_token %}
{{ monthyear }}
<button class="btn btn-primary" type="submit">click</buttom>
</form>
{% endblock %}
If I'm missing anything please let me know, I had the path at the adminApp/urls.py earlier
urlpatterns = [
path('', views.adminhome_view, name="Admin Home"),
]
but moved it to where it was trying to find the urls. I have no idea why this might not be working.
It should be view_appointment/{{a.id}}, not adminview_appointment/{{a.id}}, but it is better to make use of the {% url … %} template tag [Django-doc]. You can give the view a name:
path('view_appointment/<int:id>/', viewAppointment_view, name='view_appointment'),
and then refer to it in the template:
Client name:{{a.client_dog_name}}<br>

adding multiple values in django path

I have the following paths set up:
urlpatterns = [
path("", views.index, name="index"),
path('entry/<str:title>', views.entry, name='entry'),
]
my entry method is:
def entry(request,title):
entries = []
entry = util.get_entry(title)
if entry != None:
entries.append(entry)
return render(request, "encyclopedia/entry.html", {
"title": title,
"entries": entries,
})
and in my html we have:
{% block body %}
<h1>All Pages</h1>
<ul>
{% for entry in entries %}
<li>
a href = "{% url 'entry' title=entry %}" >{{ entry }}</a>
</li>
{% endfor %}
</ul>
{% endblock %}
two questions:
Is this the right way to pass parameters with a link?
What would I need to change to pass multiple parameters?
Is this the right way to pass parameters with a link?
Yes, by using the {% url … %} template tag [Django-doc] you calculate the path for a given view name and parameter(s).
There is however a small error in the HTML: you need to open the <a> tag, and furthermore not use spaces between the equal sign (=):
{{ entry }}
What would I need to change to pass multiple parameters?
You define extra parameters in the view, for example:
urlpatterns = [
# …,
path('entry/<str:title>/<str:theme>/', views.entry, name='entry'),
]
and you specify values for the two parameters:
{{ entry }}
the view then takes three parameters:
def entry(request, title, theme):
# …

Reverse for 's_note' with arguments '()' and keyword arguments '{'note_t': 'note_1 opeth', 'user_name': 'opeth'}' not found. 0 pattern(s) tried: []

I have a link to note detail page (s_note) in the user page (username). So as long as I have no entries(notes) in the database for the user the user page renders fine, but as soon as there is a valid note the render fails with the above error and points to ln:6 of user.html.
my urls.py
from django.conf.urls import url
from notes.models import User, Note
from . import views
app_name = 'notes'
urlpatterns = [
url(r'^$', views.index, name='u_index'),
my url
url(r'^signup/$', views.signup, name='u_signup'),
url(r'^(?P<user_id>[\w\-]+)/$', views.user, name='username'),
url(r'^(?P<user_name>[\w\-]+)/(?P<note_t>[\w\-]+)/$', views.note, name='s_note'),
url(r'^(?P<user_name>[\w\-]+)/(?P<note_t>[\w\-]+)/$', views.note, name='s_note')
]
my views
def note(request, user_name, note_t):
nt = Note.objects.get(note_title=note_t)
return render (request, 'notes/detail.html', {'note': nt})
my users.html
<h2>Hi! {{ user.user_n }} Your notes are here.</h2>
{% if allnotes %}
<ul>
{% for note in allnotes %}
<li>{{ note.note_title }}</li>
{% endfor %}
</ul>
{% else %}
<p>You have no notes yet!</p>
{% endif %}
<form method="post" action"">
<table>
{% csrf_token %}
{{ NForm }}
</table>
<input type="submit" value="Create">
</form>
Your url doesn't match for underscores or spaces which your keyword currently contains.
url(r'^(?P<user_name>[\w\-]+)/(?P<note_t>[\w\-]+)/$', views.note, name='s_note'),
should be
url(r'^(?P<user_name>[\w\-]+)/(?P<note_t>[\w\-\_\s]+)/$', views.note, name='s_note'),
although this isn't much of a solution since most spaces would turn into %20's, you should try to remove any spaces from your keywords and update your regex accordingly.
It was a namespacing problem as #Alasdair observed, it sorted with the edit -
'{% url 'notes:s_note'...%}'
in the template.

Django Template not being rendered correctly using Class based views

I'm a django newbie and wanted to integrate Singly into the django Polls application. I have used class based views to allow for models from the singly app to be passed along with the Polls models.
The problem is, I'm unable to get data from the Singly model even when data is present inside the database.
For now I simply want to display the access_token and profile ID of the user profile.
Here is my Views.py code: (only the view in question)
class IndexView(ListView):
context_object_name='latest_poll_list'
queryset=Poll.objects.filter(pub_date__lte=timezone.now) \
.order_by('-pub_date')[:5]
template_name='polls/index.html'
def get_context_data(self, **kwargs):
context = super(IndexView, self).get_context_data(**kwargs)
context['user_profile'] = UserProfile.objects.all()
return context
This is my urls.py:
urlpatterns = patterns('',
url(r'^$',
IndexView.as_view(),
name='index'),
url(r'^(?P<pk>\d+)/$',
DetailView.as_view(
queryset=Poll.objects.filter(pub_date__lte=timezone.now),
model=Poll,
template_name='polls/details.html'),
name='detail'),
url(r'^(?P<pk>\d+)/results/$',
DetailView.as_view(
queryset=Poll.objects.filter(pub_date__lte=timezone.now),
model=Poll,
template_name='polls/results.html'),
name='results'),
url(r'^(?P<poll_id>\d+)/vote/$', 'polls.views.vote', name='vote'),
)
And here is my index.html:
{% load staticfiles %}
<h1>Polls Application</h1>
<h2>Profile Info:</h2>
<div id="access-token-wrapper">
<p>Here's your access token for making API calls directly: <input type="text" id="access-token" value="{{ user_profile.access_token }}" /></p>
<p>Profiles: <input type="text" id="access-token" value="{{ user_profile.profiles }}" /></p>
</div>
<link rel="stylesheet" type="text/css" href="{% static 'polls/style.css' %}" />
{% 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 %}
Its able to fetch Polls correctly but it doesn't print anything in either textboxes i.e. the user_profile.access_token and the user_profile.profiles.
I think the problem is incorrect rendering of the template. It should pass the context 'user_profile' but its not. Or for some reason its not taking the data from the database, because there is an entry in the UserProfile database.
I would be grateful for your help, people.
The user_profile context variable contains list of UserProfile objects. From code:
context['user_profile'] = UserProfile.objects.all() # will return a QuerySet, that behaves as list
And in template it is accessed as if it is a single object:
{{ user_profile.access_token }}
{{ user_profile.profiles }}
So either put to this variable a single UserProfile object in a view. For example:
if self.request.user.is_authenticated()
context['user_profile'] = UserProfile.objects.get(user=self.request.user)
else:
# Do something for unregistered user
Either iterate over profiles in template:
{% for up in user_profile %}
{{ up.access_token }}
{% endfor %}
Either access to profile by index in template:
{{ user_profile.0.access_token }}