NoReverseMatch with Redirect in Django - django

I am very new to Python and Django. I am trying to redirect to a second view function. Here is my url configuration:
urlpatterns = patterns('dept.pv.verif.views',
(r'^apps/dept/pv/verif/$', 'index', {}, 'index'),
(r'^apps/dept/pv/verif/display$', 'display', {}, 'display'),
(r'^apps/dept/pv/verif/display/(?P<action>\w{1})/(?P<id>\w{8})/$', 'display', {}, 'display'),
url(r'^apps/dept/pv/verif/display/(?P<action>\w{1})/(?P<id>\w{8})/$', 'display', name='display'),)
And here are my view functions:
def index(request):
context = {}
visit_switch = request.GET.get('visit_switch')
if not visit_switch:
id_form = Enter_ID()
else:
id_form = Enter_ID(request.GET)
if id_form.is_valid():
return redirect('display', action='R', id='test')
context['id_form'] = id_form
return render_to_response('index.html', {'context':context})
and the second:
def display(request, action, id):
# ...
return render_to_response('index.html')
I'm getting a NoReverseMatch error. I don't understand why the redirect line is not matching up with one of my urls. I would appreciate any help you can offer.

This regular expression group:
(?P<id>\w{8})
Will only match something 8 characters long. If you're actually passing id='test', that would be your problem.

Related

django - No User matches the given query. Page Not found 404: User post list view breaks post detail view

I'm fairly new to django and trying to build a message board app. Everything's been running smoothly up until I tried to add functionality to display a list of posts by author. I got it working but then my post detail view started throwing a 'No User matches the given query. Page Not found 404' error and I can't seem to figure out why. Can anyone help?
views.py
class UserPostList(generic.ListView):
model = Post
# queryset = Post.objects.filter(status=1).order_by('-created_on')
template_name = 'user_posts.html'
paginate_by = 6
def get_queryset(self):
"""
Method to return posts restricted to 'published' status AND to
authorship by the user whose username is the parameter in the
url.
"""
user = get_object_or_404(User, username=self.kwargs.get('username'))
return Post.objects.filter(
status=1, author=user
).order_by('-created_on')
class FullPost(View):
def get(self, request, slug, *args, **kwargs):
"""
Method to get post object.
"""
queryset = Post.objects.filter(status=1)
post = get_object_or_404(queryset, slug=slug)
comments = post.comments.order_by('created_on')
liked = False
if post.likes.filter(id=self.request.user.id).exists():
liked = True
return render(
request,
"full_post.html",
{
"post": post,
"comments": comments,
"liked": liked
},
)
# I'll be adding a comment form in here too
urls.py
urlpatterns = [
...
path('<slug:slug>/', views.FullPost.as_view(), name='boards_post'),
...
path('<str:username>/', views.UserPostList.as_view(), name='user_posts'),
...
]
Error message
(When trying to view a single post (previously working) after adding the UserPostList view and route)
Using the URLconf defined in mhcmsgboard.urls, Django tried these URL patterns, in this order:
1. admin/
2. summernote/
3. register/ [name='register']
4. profile/ [name='profile']
5. login/ [name='login']
6. logout/ [name='logout']
7. new/ [name='create_post']
8. <slug:slug>/update/ [name='update_post']
9. <slug:slug>/delete/ [name='delete_post']
10. <str:username>/ [name='user_posts']
The current path, test-post/, matched the last one.
for <str:name> in path "-" not allowed to use in name,
when you use Slug both paths are equal.
urlpatterns = [
...
path('<slug:slug>/', views.FullPost.as_view(), name='boards_post'),
...
path('<slug:username>/', views.UserPostList.as_view(), name='user_posts'),
]
there are 2 simple ways
use sub path for one or both paths : user_post/<slug:username>/
Use re_path and define the regex to change path
exp:
re_path(r'^(?P\<username>\w+)/$', views.UserPostList.as_view()),
The problem is that you match update_post, delete_post and user_posts URL's to the root. As the error message explains, the current request is made against user_posts. And it seems that you don't have a user called test-post.
You could solve it e.g. with the following URL conf:
urlpatterns = [
...
path('board/<slug:slug>/', views.FullPost.as_view(), name='boards_post'),
...
path('posts/<str:username>/', views.UserPostList.as_view(), name='user_posts'),
...
]
That way, each path is unique and Django knows which View it has to call.

django redirect causes a redirect to next page, but then returns to original?

My redirect function is causing some issues. I call a url from a view using reverse with the parameters required for the view. There are no errors and in the browser of the url it correctly displays these parameters. However it seems like it redirects to the new url, but immediately after requesting the new view for the new url the page returns to the original view with the new url still displayed in the browser. Can anyone tell me if I am using the redirect function correctly or maybe I am using the reverse incorrectly?
P.S. I chopped out a lot of code because StackOverflow won't let me post all of it.
home/urls.py
from django.conf.urls import url
from home import views
app_name = 'home'
urlpatterns = [
url('^$', views.index, name='index'),
url('^patient_summary/patientid=(?P<patient_id>\d+)&clinicid=(?P<clinic_id>\d+)/', views.patient_summary, name='patient_summary'),
url('^patient_summary/patientid=(?P<patient_id>\d+)&clinicid=(?P<clinic_id>\d+)/careplanid=(?P<careplan_id>\d+)/', views.care_plan, name='care_plan'),
]
home/views.py
def patient_summary(request, token, patient_id, clinic_id):
user = get_user(token)
if request.method == "POST":
if ('careplanselected' in request.POST):
props = request.POST.get('careplan')
props = props.split("#")
CPID = props[0]
cpname = props[1]
my_dict = {'token': token, 'patient_id': patient_id, 'clinic_id': clinic_id, 'careplan_id': CPID}
return redirect(reverse('home:care_plan', kwargs=my_dict))
return render(request, 'home/patient_summary.html')
def care_plan(request, token, patient_id, clinic_id, careplan_id):
user = get_user(token)
care_plan = []
cpname = ''
return render(request, 'home/care_plan.html' )
Your URL patterns are missing dollars to mark the end of the URL. That means that your patient_summary view will be handling requests meant for the care_plan view.
Change the patterns to:
url('^patient_summary/patientid=(?P<patient_id>\d+)&clinicid=(?P<clinic_id>\d+)/$', views.patient_summary, name='patient_summary'),
url('^patient_summary/patientid=(?P<patient_id>\d+)&clinicid=(?P<clinic_id>\d+)/careplanid=(?P<careplan_id>\d+)/$', views.care_plan, name='care_plan'),

Most appropriate way to redirect page after successful POST request in Django

I have build a view and a form in Django1.5. If the POST request is successful (based on some values I set) then I need the page to redirect to another URL which is created simultaneously.
Otherwise, if the POST was not successful I need to stay on the same page. Right now I have solved the problem as following but I am quite sure this is not the best way to do it:
This is a part of my view:
def layer_create(request, template='layers/layer_create.html'):
if request.method == 'GET':
....
elif request.method == 'POST':
out = {}
...
new_table = 'something that comes from the form'
if form.is_valid():
...
try:
...
out['success'] = True
except:
...
out['success'] = False
finally:
if out['success']:
status_code = 200
# THIS IS THE PART WHICH I THINK I CAN IMPROVE
template = '/something/workspace:' + new_table + '/metadata'
else: # if form not valid
out['success'] = False
return render_to_response(template, RequestContext(request, {'form': form}))
This part of the code:
template = '/something/workspace:' + new_table + '/metadata'
seems very ugly to me. But as I am quite new in Django I am not sure how to approach this matter.
A side note first about Django 1.5 - you're highly advised to upgrade to a supported version like 1.8.
Redirecting
For redirecting you can use the redirect shortcut. (Or HttpResponseRedirect)
from django.shortcuts import redirect
# out of a view context
return redirect('/url/to/redirect/to/')
Building URLs
Indeed - as you did mention, your attempt with template = '/something/workspace:' + new_table + '/metadata' is not the cleanest way :)
Django provides a really nice way with the URL dispatcher.
A complete solution here would go too far (or definitely would require more detailed information about your project structure) - I would recommend you to dive into the Django URL dispatcher.
In short you would do something like:
# app/urls.py
urlpatterns = [
#...
url(r'^workspace/(?P<id>[0-9]+)/metadata/$', views.workspace_detail, name='workspace-detail-metadata'),
#...
]
Then you are able to reverse your URL patterns:
from django.core.urlresolvers import reverse
url = reverse('workspace-detail-metadata', kwargs={'id': 123})
# would result in:
# .../workspace/123/metadata/
After all, I have used the "reverse" method as follows:
layer = 'geonode:' + new_table
return HttpResponseRedirect(
reverse(
'layer_metadata',
args=(
layer,
)))
Where my urls.py file includes:
url(r'^(?P<layername>[^/]*)/metadata$', 'layer_metadata', name="layer_metadata"),
As described here this is the most appropriate way to do it.

Django : url main page

I want to add a main page with a login but I have the error
A server error occurred. Please contact the administrator.
what does it means ??
url:
urlpatterns = patterns('',
url(r'^ยง', main_page),
url(r'^mainView/$', mainView.as_view()),
url(r'^material/(?P<slug>[-\w]+)/$', MaterialDetailView.as_view(), name='material_material_detail'),
)
view:
def main_page(request):
template = get_template('registration/main_page.html')
variables = Context({ 'user': request.user })
output = template.render(variables)
return HttpResponse(ouput)
Pretty sure you meant
url(r'^$', main_page),

NoReverseMatch error while redirecting to results page

I have intended to write an search application by Django.
I am getting a NoReverseMatch error when I redirect to results page.
I posted my codes here http://pastebin.com/AL4rG9NU
Or you can read it below
urls.py
urlpatterns = patterns('pylucene.views',
(r'^$', 'index'),
(r'^search/$', 'search'),
)
views.py
def index(request):
return render_to_response('pylucene/index.html', context_instance=RequestContext(request))
def search(request):
query = request.POST['query']
search_results = search_files(query)
return HttpResponseRedirect(reverse('pylucene.views.results', args=(search_results,)))
The Error:
NoReverseMatch at /pylucene/search/
Reverse for 'pylucene.views.results' with arguments
'([(u'Documents\\Dieu khien may tinh bang y nghi.txt', u'Dieu khien
may tinh bang y nghi.txt'), '1 total matching documents.'],)' and
keyword arguments '{}' not found.
def results(request, search_results):
return render_to_response('pylucene/results.html', {'search_results': search_results}, context_instance=RequestContext(request))
I read several similar topics but I can not solve my problem.
Please help me.
Thank you so much.
I think that you are not undestanding how the reverse function works and what are you trying is just not posible.
For the reverse function your url must be declared on urls.py for example:
#urls.py:
urlpatterns = patterns('blog.views',
(r'^$', 'index'),
url(r'^blog/(?P<slug>\d{4})/$', 'blog', name="blog-detail"),
)
Now in your code you can do
reverse('blog-detail', args=('django-urls',))
# the resolt of this is
# /blog/django-urls/
And this is how reverse works.
The real answer
I think that you do not need 2 views, but if you really want to: you have to do this to pass all the query already performed
def search(request):
query = request.POST['query']
search_results = search_files(query)
return results(request, search_results)
but i think that the best that you can do is this (using GET):
def search(request):
query = request.GET['query'] # I think using get is better because you are GETing info
search_results = search_files(query) # better if returns a generator
return render_to_response('pylucene/results.html',
{'search_results': search_results},
context_instance=RequestContext(request)