django - urlconf request mapping and views not reached - python

i have a form in a template, but it can't reach the correspondant view. the method is GET. i've tried also to pass it an argument just to populate the query string, but the request doesnt reach the mapped view. here'sthe views.py, urls.py and the template:
template.html
<div id="search-new-btn">
<form action="/anagrafica/new/" method="get">
<input type="submit" title="Crea nuovo soggetto anagrafica" value="Nuovo" />
</form>
</div>
views.py
def anagrafica_new(request):
if request.method == 'GET':
form = AnagraficaForm()
sub = 'Nuovo soggetto anagrafica'
dict = {'sub':sub,'form':form}
return render_to_response('anagrafica_form.html', dict, context_instance=RequestContext(request))
urls.py
...
url(r'^anagrafica/new/',('gpf1.views.anagrafica_new')),
...
(http://openpaste.org/05b157c1)
Anyway, i've also tried to remove the () from the callback url.py mapping, but it didnt change nothing.
the request seems to be mapped cause my debug server print this:
"GET /anagrafica/new/? HTTP/1.1" 200 17310
but nothing more. the browser remain on the same page; i also put a print statement just inside the view but it never has been reached. any idea?
thanks,
Luke

As Willian suggested don't put the view in a tuple. Another thing you are missing is the $ at the end of regular expression i.e.:
urls.py
...
url(r'^anagrafica/$','gpf1.views.anagrafica'),
...
url(r'^anagrafica/new/$','gpf1.views.anagrafica_new'),
...
Make sure that the folder containing gpf1 package is within Pythonpath variable (reachable by python).
Edit:
Subsequently I noticed you have a root url map for
url(r'^anagrafica/','gpf1.views.anagrafica')
Since you are missing $ at the end Django will try to map anagrafica/anything here to gpf1.views.anagrafica which is probably not what you want. Consider rereading regular expressions and Django's url mapping documentation as it will make things a bit clearer.

Related

Customizing django-allauth password_reset_from_key template

I'm using django 2.2.3, I'm overriding django-allauth templates and on password_reset_from_key template I came across a NoReverseMatch Exception,
Reverse for 'account_reset_password_from_key' with no arguments not found. 1 pattern(s) tried: ['accounts/password/reset/key/(?P<uidb36>[0-9A-Za-z]+)-(?P<key>.+)/$']
So it expects argument and probably that argument is the key that is generated during resetting password. From the URL pattern, 'key' is the variable's name
I tried to pass it with 'key'.
<form method="POST" action="{% url 'account_reset_password_from_key' key %}">
...
</form>
but it did not work. What is wrong?
If you're not overriding the allauth view, then use action_url:
<form method="POST" action="{{ action_url }}">
that's what the view passes to the template.
You didn't supply where that error is coming from, but if I look for where that url name is used in the code, it's not being used in a template.
See:
https://github.com/pennersr/django-allauth/search?q=account_reset_password_from_key&unscoped_q=account_reset_password_from_key
My guess is you're calling this url name and not passing the parameters to it?
url(r"^password/reset/key/(?P<uidb36>[0-9A-Za-z]+)-(?P<key>.+)/$",
views.password_reset_from_key,
name="account_reset_password_from_key"),
PS:
As a general rule when overriding django app templates I'd suggest starting with the original template (eg copy the file allauth/templates/account/password_reset.html or whatever to your templates dir (creating all the subdirectories)), and then change the pieces you need - that way if something goes wrong it's easy to roll back and figure out why.
I know from experience that allauth templates are fairly complex and it's easy to break functionality in them if you don't fully understand how they work.

Cannot have any URLs with slugs. NoReverseMatch

I'm a begginer grasping at straws with difficulty dealing with the django slug url system and these NoReverseMatch errors that make no sense to me even after reading the docs.
I have a django project. In one of the views, I pass a list of geoJSON features into a template, and show them on a map. I want to have each feature act as a clickable 'link' to a view that will show stuff about it. The following is part of the template that has those features that I want to click on:
//part of the template:
<script type="text/javascript">
...
function onEachFeature(feature, layer) {
layer.on('click', function (e) {
window.location.href = "{% url 'polls:areadetail' feature.properties.myslug%}";
});
}
(I have confirmed that feature.properties.myslug does in fact contain the slug I want).
The url pattern I want to go to:
urlpatterns = [...
url(r'^areadetail/(?P<areaslug>[-\w]+)/$', views.AreaDetail, name='areadetail'),]
And the view it relates to:
def AreaDetail(request, areaslug):
area = get_object_or_404(Area, nameslug=areaslug)
return render(request, 'polls/areadetail.html', {'area':area})
The issue I get is, by doing what I show and placing that url reference inside that template I show above, that I want to be able click on, that template won't even work at all, giving me a 'Error during template rendering' full page error info that starts with:
NoReverseMatch at /polls/areas/
Reverse for 'areadetail' with arguments '('',)' and keyword arguments '{}' not found. 1 pattern(s) tried: [u'polls/areadetail/(?P[-\w]+)/$']
Any help would be immensely appreciated
EDIT part1: As I've said in response to falsetru, I'm sure feature.properties.myslug has in fact got a slug expression in it.
EDIT2: Based on something I found in a django ticket, I've made a slight change in the url regex at urls.py, from (?P<areaslug>[-\w]+)/$ to (?P<areaslug>[-\w]+)?/$ and now the error is:
Page not found (404)
Request Method: GET Request URL: http://127.0.0.1:8000/polls/areadetail// Raised by: polls.views.AreaDetail
Is it possible that because the "{% url 'polls:areadetail' feature.properties.myslug%}" bit is inside javascript, that feature.properties.myslug is not being inserted there correctly? Like some sort of brackets are needed here?
According to the error message, feature.properties.myslug is empty or has no value.
Make sure the feature.properties.myslug is passed correctly from view.
Comment out {% url .. %} temporarily.
Print {{ feature }}, {{ feature.properties }}, {{ feature.properties.myslug }} to see if which part is missing.
Fix view accordingly.
Uncomment {% url .. %}.
After some more digging around I've found the answer to why doesn't this work in another question at:
How to pass javascript variable to django custom filter
The answer to it by Ludwik Trammer says:
Django templates are build on the server side, while JavaScript is executed on the client side.
That means that template code is always executed before JavaScript (as
it is executed by the server, before the page is sent to the client).
As a consequence it is absolutely impossible to mix JavaScript and
Django code the way you want to.
Which clearly applies here. I was focused on problems with the URL template, regex on the urls.py file etc. when the problem was that no matter what I did, because it's in a javascript section, run client-side, that URL template will always be incomplete no matter what I do, therefore being an impossible solution to what I want.

Pass <input> value to Django view

Let's say I have the following pointless example view:
def foo(request, input):
return HttpResponse()
and in a template I have a form:
<form method="get" action="{% url 'foo' ??? %}">
<input id="myinput" type="text" name="myinput">
...
</form>
Finally, I have the following url in my URLconf:
urlpatterns = [
url(r'^foo/(.+)/', views.foo, name='foo'),
]
What I would like to do, is pass the value entered by the user into the input with the id of #myinput to the foo() view function. To put it another way, you should be able to enter bar in the html input, and when you submit the form it will take you to foo/bar/.
I know that within the foo view I could access the value of the input easily with request.GET['myinput'], but I want it to show up in the url as well.
This seems like it should be a fairly common task, but I have not been able to come up with a solution yet. Any suggestions would be appreciated. My Frankenstein's Monster of a first Django site is almost complete, and this is one of last pieces I am missing.
The source of my misunderstanding
Although I did not make this clear in an attempt to simplify my example and avoid using app-specific code, my use case is a simple search view. The view was actually one of the first views I wrote in the start of my Django journey, and I mistakenly was POSTing my data instead of GETing it. This was making it so that if I was searching for the item foo, it would take me to the detail page for foo, but the url would be mysite/search/ (i.e., the search query is not included in the url though it is included in the request), and I can't return to those search results by visiting the url mysite/search/.
While I was using a GET request in my toy example in this question, I didn't realize that I had been using a POST in my app, and that with some minor tweaking I can get the functionality I want for free very easily. I know that all of this is extremely obvious to veteran and even intermediate web developers, but for someone starting from scratch without web or cs experience, things like HTTP can be a little confusing. At least for me it is. Thanks so much to #Two-Bit Alchemist for explaining this in a way that I can understand.
Applying all this to my toy example
I would get rid of the passed parameter in my view:
def foo(request):
# If I want to do something with the search query, I can access it with
# request.GET['search_query']
return HttpResponse()
change my form in my template to:
<form method="get" action="{% url 'foo' %}">
<input id="myinput" type="text" name="search_query">
...
</form>
and change my url to:
urlpatterns = [
url(r'^foo/search/', views.foo, name='foo'),
]
As #Two-Bit Alchemist said: "The rest will happen like magic". If a user enters bar in the input and submits the form, they will be taken to foo/search/?search_query=bar. This is what I was looking for.

Django object deletion does not work

I've spend hours today figuring out how to delete objects in Django.
Now I have found and tried 4 different approaches on the Net, that only differ in whether a form/POST/GET approach is used or not. CSRF attacks are irrelevant for me, as the page is supposed to run locally.
What does the app do? So far only uploading files under a certain project name. This name is slugified and used as a key to hash files of a project together. Now I want to also delete files (later whole projects).
Here one of the approaches:
In the .html:
<a href="{{file.pk}}/delete" class="btn btn-sm" role="button" title="Delete File">
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span>
</a>
This link is diplayed in a detail view, so the url already looks somethin like /files/SLUG/
Then in urls.py:
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^upload/$', views.file_upload, name ='upload'),
url(r'^upload/(?P<slug>[\w-]+)/$', views.file_upload, name ='upload'),
url(r'^(?P<slug>[\w-]+)/$', views.file_detail, name='detail'),
url(r'^(?P<slug>[\w-]+)/(?P<pk>\d+)/delete$', views.file_delete, name="file_delete"),
]
And finally the views.py:
def file_delete(request, slug=None, pk=None):
instance = get_object_or_404(File, slug=slug, pk=pk)
# instance = File.objects.filter(pk=pk, slug=slug)[0] # the same as above
instance.delete() #does not work
return redirect("index") # or anything, this part is no problem
Everything runs through without any errors, but when I check the database on /admin, no file is gone. It simply does not get deleted. Sometimes, when logging in on /admin after trying a couple of times, I see multiple "File successfully deleted" messages at the login screen. But then the files are still in the database list.
Django Docs tells me delete() should return some kind of dictionary and how many objects were deleted e.g. like so:
>>> e.delete()
(1, {'weblog.Entry': 1})
But in may case it just says: None or returns a path starting with a slug.
I'd be very gratefull for any hint. I know there is at least one other post on stackoverflow concerning this, but unfortunately no answers
The queryset delete method (e.g. File.objects.filter(...).delete()) returns a tuple.
When you delete an instance (e.g. instance.delete()) it returns None.
I'm not sure what you mean by 'when I check the file list, no file is gone'. Note that when you delete a model instance, it will remove the row from the database. If the model has a FileField, it won't automatically delete the associated file.
I had a similar problem (that's how I found this), and I think if you simply put a '/' in the end of the URL for delete, it should work. At least thats what worked with me.
...
url(r'^(?P<slug>[\w-]+)/(?P<pk>\d+)/delete/<<<<$', views.file_delete, name="file_delete"),
]

Can make a Search with a template form work

I use crispy-forms in all of my search,but in this one I need to do it with a template form, I don't know what's wrong with my code 'cause I have the same code in other project and it works fine, I don't know if is the Django version, currently I'm using 1.8. The error that I get is Page not found (404), I doesn't find the url.Here's my code hope you can help me. I use q and param in the url but none works.
urls.py
url(r'^search/(?P<param>\S+)$', permission_required('agenda.change_agenda', login_url='/no_access')(SearchContact.as_view()), name='searchcontact'),
template_form.html
<form class="well form-search" action="/search/" method="get">
<input type="text" class="input-medium search-query" name="param">
<button type="submit" class="btn">Search</button>
</form>
views.py
class SearchContact(ListView):
template_name = 'agenda_contacts.html'
def get_queryset(self):
query = self.request.GET.get('param')
return Agenda.objects.filter(name=param)
Your regex
r'^search/(?P<param>\S+)$
matches urls like /search/hello or /search/my-search.
However, your search form is sending the search terms in the GET paramters, for example /search/?param=hello or /search/?param=my-search.
GET parameters are not captured in urls.py. You can access them with request.GET in the view as you are already doing.
Therefore, you should remove param from the regex, and change your url pattern to the following.
url(r'^search/$', permission_required('agenda.change_agenda', login_url='/no_access')(SearchContact.as_view()), name='searchcontact'),

Categories

Resources