NoReverseMatch with slug variable, works with hard coded value - django

I'm updating some code from a Django 1.11 project to Django 2.x, and in one template (contacts list view with FK back to Clients), I am getting "NoReverseMatch" since it is not seeing the slug value in the URL parameter. If I hard code the value it works, and the same variable displays the proper value for each record if I just display as text on the page.
I don't see why the variable is getting dropped, but probably something stupid I've done.
This works:
<td class="">
<a href="{% url "clients:view" slug='sony' %}">
{{ contact.client.slug }}
</a>
</td>
This gets the NoReverse Error
<td class="">
<a href="{% url "clients:view" slug=contact.client.slug %}">
{{ contact.client.slug }}
</a>
</td>
In both cases, the variable {{ contact.client.slug }} returns the proper data.
urls.py:
import ...
app_name = "clients"
urlpatterns = [
path("ajax/validate_client_code", validate_client_code, name="validate_client_code"),
path("", ClientListView.as_view(), name="list"),
path("new/", ClientCreateView.as_view(), name="new"),
path("edit/<slug:slug>/", ClientUpdateView.as_view(), name="edit"),
path("delete/<int:pk>/", ClientDeleteView.as_view(), name="delete"),
path("<slug:slug>/", ClientDetailView.as_view(), name="view"),
]
Can anyone point out my mistake? Has to be something really simple, but I just cant see it.

Related

Reverse for with no arguments not found for URL

I am attempting to create a view that allows users to delete a build log. On the view that shows the delete button with a link to the delete page I am getting the error
Reverse for 'build-log-delete' with no arguments not found. 1 pattern(s) tried: ['post/(?P<pk>[0-9]+)/build\\-log/(?P<pkz>[0-9]+)/delete$']
If I understand this error correctly its because I am not passing paramaters in the url.
<a class="delete-btn" href="{% url 'build-log-delete' %}">Delete</a>
However I do not understand why I need to pass parameters in the URL as I am not passing any new values into the URL and if so what parameters I would pass. Do I have to re pass the previous two?
urls
path('post/<int:pk>/build-log/<int:pkz>/', views.BuildLogDisplay, name='build-log-view'),
path('post/<int:pk>/build-log/<int:pkz>/delete', views.BuildLogDelete, name='build-log-delete') #error
views
def BuildLogDisplay(request, pk, pkz ):
post = BuildLog.objects.filter(post_id=pk)
log = BuildLog.objects.get(pk=pkz)
context = {
'post':post, 'log':log
}
return render(request, 'blog/buildlog.html', context)
def BuildLogDelete(request):
context = { }
return render(request, 'blog/BuildLogDelete.html', context)
full template
<div class="row">
<article class="cars-article">
<div class="flex">
<img class="rounded-circle article-img" src="{{ log.author.profile.image.url }}" />
<div>
<a class="article-title">{{ log.title }}</a>
</div>
</div>
<br>
<div>
{% if log.author == user %}
<a class="update-btn" href=""> Update</a>
<a class="delete-btn" href="{% url 'build-log-delete' %}">Delete</a>
{% endif %}
</div>
<hr class="solid">
<p class="article-content">{{ log.content | safe}}</p>
</article>
</div>
There are multiple errors in you code. You are not passing args in BuildLogDelete view but in url you are using those arguments. So the correct view should look like this.
def BuildLogDelete(request,pk,pkz):
# delete code
# write here
Next mistake which i can see is you are assigning queryset rather than object for the post key in BuildLogDisplay view. You should assign object.
post = BuildLog.objects.get(post_id=pk)
Lastly your original error mentioned in the question is because your build-log-delete url expects two arguments i.e pk and pkz but you haven't passed them in template. So it should be like this.
<a class="delete-btn" href='{% url "build-log-delete" pk=post.post_id pkz=log.pk %}'>Delete</a>
I would highly suggest you to look for already given generic views like ListView, TemplateView, CreateView, UpdateView and DeleteView. This will prevent you from reinventing the wheel
Ref: Django Class Based Generic Views

How to use the href link feature as well as pass a Django url to a view in Django?

If I have an <a>..</a> Element which has a link it points to , but i also want to call a Django View when it's clicked ,how do i do it?
<td ><a href="{{ page.url }}" >Click Here</a>
But i also want to call 'updateViews' in /views.py like this
<td ><a href="{% url 'updateViews' page.title %}" >Click Here</a>
Okay just found out I could just use onclick for this :
<td ><a href="{% url 'updateViews' page.title %}" onclick="window.open('{{page.url}}');" >Click here</a></td>

obtain django dropdown menu item queryset

I am trying to make a calendar html page, that has a dropdown button to select the different months. How to get to this calendar page is via the nav bar that is created at base.html
base.html - how to get to the calendar page.
....
....
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" data-toggle="dropdown" data-target="scheduler_dropdown" href="#"><i class="fas fa-calendar"></i>Scheduler</a>
<div class="dropdown-menu" aria-labelledby="scheduler_dropdown">
<a class="dropdown-item" href="{% url 'view_schedule' %}"><i class="fas fa-calendar-alt"></i>View Schedule</a>
</div>
</li>
what i've build so far:
urls.py
urlpatterns = [
path('schedule/view-schedule/', views.view_schedule, name='view_schedule'),
path('schedule/view-schedule/?query=month<str:selected_month>', views.view_schedule,
name='view_schedule_selected_month'),
]
Views.py
def view_schedule(request, selected_month=None):
if request.method == 'POST':
print('post')
else:
current_month = date.today().month
current_year = date.today().year
# a = request.GET # How to get query set from dropdown menu???
# print(a)
args = {
'month_cal': monthcalendar(current_year, current_month),
'month_name': calendar.month_name[current_month],
'year_name': current_year,
}
return render(request, 'static/html/view_schedule.html', args)
view_schedule.html
<div class="card-header">
Schedule for {{ month_name }} {{ year_name }}
<form class="date-selector" method="post">
{% csrf_token %}
<div class="dropdown">
<button class="btn dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="far fa-caret-square-down"></i>
</button>
<div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
<a class="dropdown-item" href={% url 'view_schedule_selected_month' selected_month=1 %}>Jan</a>
<a class="dropdown-item" href={% url 'view_schedule_selected_month' selected_month=2 %}>Feb</a>
<a class="dropdown-item" href={% url 'view_schedule_selected_month' selected_month=3 %}>Mar</a>
</div>
</div>
</form>
</div>
My problem is that, when I click on the drop down button and select the relevant month Jan, Feb, Mar, the url changes, but in my views.py, the query set doesn't appear. So I can't extract the query for processing.
Any thoughts?
Turns out I could have just done print(selected_month) and it would print the query result.. I got the idea when I was watching this video: https://www.youtube.com/watch?v=qmxoGYCFruM
Don't use urlpatterns to handle query strings. urlpatterns handles only the URL itself; query parameters are part of the GET data and are handled within the callback method. You'll need to change the way your HTML, urlpatterns, and the view work to accommodate this.
urlpatterns = [
path('schedule/view-schedule/', views.view_schedule, name='view_schedule'),
]
In your HTML, you'll want a form with a dropdown that GETs the data to the URL above. You can use the select tag for this.
And then in the view, you can extract GET data from request.GET. Specifically, if you used the select tag as suggested above, then the user's choice will be in request.GET[NAME] where NAME is the name of the select tag.
There are other ways to go about this, depending on aesthetic preferences, etc., but the method I've explained above is likely to be the easiest.
Also, query set (or QuerySet) has a very specific meaning in Django. It refers to a type of object used in database queries as explained here. The results of an HTML form are not "query sets."

Getting an 'x' in the url derived from django regex

I am trying to generate an URL using regex and have got it to an extent. But, the problem is there is an 'x' in the URL which I don't want there, without it the URL is perfect. I have tried few changes on the regex but removing or adding anything throws an error.
views.py
def clothes_details(request,slug):
item = data.objects.get(slug=slug)
print(item)
return render(request,clothes_details.html,{'item':item})
urls.py
url(r'^(?P<designerlink>)[\w-]+/(?P<slug>[\w-]+)/$',views.clothes_details,name='clothes_details'),
item.html
<div class='items'>
{% for item in all_clothes %}
<div class='item'>
<a href="{% url 'clothes_details' designerlink=item.designerlink slug=item.slug %}">
<img src="{{item.itemimage.url}}" style="width:350px;height:450px;">
</a>
<p>{{item.itemcode}}</p>
<p>{{item.itemprice}}</p>
<p>{{item.itemname}}</p>
</div>
The result is getting 'http://127.0.0.1:8000/designernamex/dressname/' but I need to get 'http://127.0.0.1:8000/designername/dressname/'

Passing an id in Django url

I want to pass userid from django url to my view
Here is what I have written in Django template
<a href ={% url 'user_details' x.id %} class='btn btn-primary' style="float: right;" >Know More</a></div>
To handle this url I have written Url like
url(r'^User/(\d{userid})/$', 'search.views.user_detail',name='user_details'),
But I am getting an error i.e
NoReverseMatch at /search/
Reverse for ''user_details'' with arguments '(2L,)' and keyword arguments '{}' not found.
Please help me out What might I am doing wrong here .
No quote ''
<a href ={% url user_details x.id %} class='btn btn-primary' style="float: right;" >
Know More
</a>
Another your url
url(r'^User/(?P<userid>\d+)/$', 'search.views.user_detail', name='user_details'),
Be carefull, after Django 1.5, use must use quotes. I came across this solution and tried it, got an error. I'm using Django 1.6 and you need the quotes:
<a href ={% url 'user_details' x.id %} class='btn btn-primary' style="float: right;" >
Know More
</a>
hope it helps.