Reverse for with no arguments not found for URL - django

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

Related

django include template repeated in all url but get data from main url

i have one html template for my main body and in every url this main body is fixed. but the data from this fixed body is show only in main url or in one url
like this i have a inbox and number of message on it
inbox message number
in every url i have this message but in main url or view i send data to template for example if yo go to main url the number on inbox show but if you go to another url because the data is not in your view yo dont have number
how can i fix this !!?
or my question is how include template get data from special url in every url in django!?
No, Django does not provide any special URL concepts, But you can archive those things like this...
views.py
def navbar_counters(request):
a={'inbox':10,'mesages':20}
return a
def Oneview(request):
counters= navbar_counters(request)
context = {'counters':counters}
return render(request,'index.html',context)
def Twoview(request):
counters= navbar_counters(request)
context = {'counters':counters}
return render(re
quest,'page2.html',context)
index.html
{% block body %}
<h1>Page - 1</h1>
<div class="container-fluid mt-5 ">
<div>
{% for i,j in counters.items %}
<button type="button" class="btn btn-primary position-relative ms-5 ">
{{i}}
<span class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger">
{{j}}+
</span>
</button>
{% endfor %}
</div>
</div>
{% endblock body %}
browser Output
NOTE - You need to call navbar_counters(request) function in every view function, I mean you need to call below code snippet in every views function.
counters= navbar_counters(request)
context = {'counters':counters}

How to pass a <select> in a View using Django

I was trying to make a cart system in Django and wanted to pass Size and the Quantity of product as <Select>
input in View.
My Template have :
<ul class="list-unstyled">
Select Size:
<select name="sizes">
{% for size in product.sizes.all %}
<li class="list-item list-inline-item"><option value="{{size.nameSize}}">{{size.nameSize}}</option> </li>
{% endfor %}
</select>
</ul>
This is how it looks :
But when i Submit it using the Add to Cart Button i get error:
This is the code in the view:
def add_item(request,pk):
product = get_object_or_404(Product,pk=pk)
size = request.POST['sizes']
selectsize = Size.objects.get(nameSize=size)
user = request.user
usercart = Cart.objects.get(owner=user)
newitem = CartItems.objects.create(cart = usercart,product=product,size=selectsize)
items = usercart.cartitems
return render(request,'cart.html',{'cartitems':items})
I am trying to use the name of the size from the Template and compare the size name i have in the database for that product Using:
selectsize = Size.objects.get(nameSize=size)
I was able to get size with name 36 so i wanted to pass the value 36 from the template to the variable size using post.
But i get the error mentioned which i believe is because name for the <select> is common in all the <option>.
If i can either get an alternate way to do that or solve this error both type of solutions are welcomed.
*I am not using Django Forms because i don't know how to have django form display like i am displaying my products in cart and on the product page.
ANSWER
I was missing a submit button and was rather using a <a href="{% url 'add_item' product.pk %}>Add To Cart</a>" to submit the form which was not working.
Now i replaced it with <button class="btn btn-success" style="margin-top: 10px;" type="submit">Add To Cart New</button>
And the form Action is given the link i was trying to go to.
<form method="post" enctype="multipart/form-data" action="{% url 'add_item' product.pk %}">
A silly mistake on my side.
Thanks for the answers.
Expanding on what #Yevhenii M. said, and talking particularly about the MultiValueDictKeyError:
This error happens when the given key (sizes in this case) is not found in the POST dict. This might be happening (i'm only guessing, since you didn't post the full html code), because you didn't put the corresponding <form> tag surrounding the select.
So, the final code would look something like:
<form action="url-to-send-form-data" method="POST">
{% csrf_token %}
<select name="sizes">
{% for size in product.sizes.all %}
<option value="{{size.nameSize}}">{{size.nameSize}}</option>
{% endfor %}
</select>
</form>
The {% csrf_token %} is needed in order to protect you against Cross Site Request Forgery attacks (more info: https://docs.djangoproject.com/en/2.2/ref/csrf/)
EDIT: Now that I take a closer look, the error message shows that the url is being called with a GET request (maybe because of trying to access to /item_added/1 straight from the browser's url). That is why django can't find the sizes key.
One common way to call the url via post, is as shown in the code snipet above, and adding a submit button to the html:
...
<button type="submit">Submit</button>
</form>
You don't need to use <ul> tag here.
You can write:
Select Size:
<select name="sizes">
{% for size in product.sizes.all %}
<option value="{{size.nameSize}}">{{size.nameSize}}</option>
{% endfor %}
</select>
and result will be the same.
Since you didn't specify that add_item(request, pk) works only by POST, then you can't expect that request.POST always will be presented.
Better write your code as this:
if request.POST:
# do something
And if you don't specify default value for your select in template, then sizeswill not be in your request.POST.
You can write like this just to be sure that you got some value:
request.POST.get('sizes', 'some_default_value')
Just because you get MultiValueDictKeyError you need to see what you get in request. Maybe you get QueryDict, then you need to extract first value. For example, see this SO question. For example, print your request.POST or check type.

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.