I've been trying to create a movie survey in Django for an assignment, and I am currently working on the function. I can't seem to understand why won't it recognize the URL I pass.
I tried removing the hardcoded URL as shown in the Django tutorial on the framework's site, but that doesn't make the error go away.
Here's an excerpt from urls.py:
urlpatterns = [
url(r'^$', views.index, name="index"),
path('movie=<int:movie_id>&user=<int:user_id>/', views.movie, name='movie'),
path('ratings/', views.ratings, name='movie'),
path('rating/<int:movie_id>/', views.rating, name='movie'),
path('movie=<int:movie_id>&user=<int:user_id>/vote/', views.vote, name='vote'),
path('register/',views.register, name='register'),
]
This is my movie view( supposed to present a movie and a star rating radio for the user to rate the movie), where the URL is constructed and passed to HTML:
def movie(request,movie_id,user_id):
movie = get_object_or_404(Movie, pk=movie_id)
voteURL = '/polls/movie=' + str(movie_id) + '&user='+str(user_id)+'/vote/'
context = {
'mymoviecaption':movie.Title,
'moviePoster': 'https://image.tmdb.org/t/p/original'+tmdb.Movies(movie.TMDBID).images().get('posters')[0].get('file_path'),
'myrange': range(10,0,-1),
'myuserid':user_id,
'voteurl': voteURL,
'mymovieid':movie_id
}
#print(nextURL)
translation.activate('en')
return HttpResponse(render(request, 'movieview.html', context=context))
The HTML excerpt, where the vote view is called:
<form action="{% url voteurl %}" method="post">
{% for i in myrange %}
<input id="star-{{i}}" type="radio" name="rating" value={{i}}>
<label for="star-{{i}}" title="{{i}} stars">
<i class="active fa fa-star" aria-hidden="true"></i>
</label>
{% endfor %}
<input type="submit">Vote!</input>
</form>
The vote view( should save to database and redirect to the next movie, doesn't save to database yet, because I didn't want to clutter it with records until I am sure I got the function to work):
def vote(request, movie_id,user_id):
try:
nextmovie=get_object_or_404(Movie, pk=movie_id+1)
nextURL = '/polls/movie=' + str(movie_id + 1) + '&user='+str(user_id)+'/'
except Http404:
nextURL = '/polls/ratings'
try:
myrating = int(request.POST['rating'])
print(myrating)
except:
# Redisplay the question voting form.
return render(request, '/polls/movie=' + str(movie_id + 1) + '&user='+str(user_id)+'/', {
'error_message': "You didn't select a choice.",
})
return HttpResponseRedirect(nextURL)
No matter what I try, I get the NoReverseMatch at /polls/movie=1&user=9/ whenever I try to load the first movie page, despite said URL being defined in urlpatterns.
This is not the way how you provide two pk in the urls
It should be like this
path('movie/<int:movie_id>/<int:user_id>/', views.movie, name='movie'),
Also this is not the way of providing url in the template so it should be something like this
<form action="{% url 'vote' %}" method="post">
# {% url 'url_name' %}
# if app_name provided {% url 'app_name:url_name' %}
And please follow the tutorials step by step
Related
I'm trying to create a search bar in Django, where users can enter a value to search for, click enter / search button, and then the url redirects to https:localhost:3000/usearch/abc, if they for example search for abc. This is URL paramter can always change based on the search, and it should send the parameter to the views.py file to be processed, though I can't get it to work.
urls.py
urlpatterns = [
path('', views.index, name='index'),
path('register/', views.register, name='register'),
path('usearch/', views.usearch, name='usearch'),
path('usearch/<str:query>', views.usearch_query, name='usearch_query'
]
views.py
def usearch(request):
return render(request, 'myapp/usearch.html')
def usearch_query(request, query):
context = {'query': query}
print(query) # Testing the search result
return render(request, 'myapp/usearch_query.html'}
usearch.html
<form method="GET" action="{% url 'usearch_query' %}
<input type="search" placeholder="Search here...">
<button type="submit"> Search </button>
</form>
usearch_query.html
{{ query }}
I essentially want the user to search something, have it navigate to usearch/<search_parameter> and process the search in the usearch_query function so I can do some computations with it.
So I'm building this learning log app where users can create multiple topics. I'm trying to create a single page where users can edit/save changes/delete their topic names. My logic in the edit_topic view function is to display the original topics in forms with save and delete button, code below or feel free to check GitHub Repo:
views.py
def edit_topics(request, topic_pk=None):
'''edit existing topics mainly the names'''
# modify the model data according to the request method and name
if request.method == 'POST' and topic_pk != None:
if 'save' in request.POST:
topic_to_change = get_object_or_404(Topic, pk=topic_pk)
form = TopicForm(instance=topic_to_change, data=request.POST)
if form.is_valid():
form.save()
elif 'delete' in request.POST:
topic_to_delete = get_object_or_404(Topic, pk=topic_pk)
topic_to_delete.delete()
return redirect('learning_logs:edit_topics')
# get the original/modified data passing to render
topics = Topic.objects.all()
topic_lst = []
for topic in topics:
form = TopicForm(instance=topic)
topic_lst.append(form)
context = {'topics': topics, 'topic_lst': topic_lst}
return render(request, 'learning_logs/edit_topics.html', context)
edit_topics.html
{% extends 'learning_logs/base.html' %}
{% block content %}
<section class="container">
<h3>Topics you have created</h3>
<ul class="">
{% for form in topic_lst %}
<li class="mb-5">
<form class="d-flex align-items-center"
action="{% url 'learning_logs:edit_topics' form.instance.pk %}" method="POST">
{% csrf_token %}
{{ form.as_p }}
<button class="btn btn-primary" name="submit">save</button>
<button class="btn btn-danger" name="delete">delete</button>
</form>
</li>
{% endfor %}
</ul>
<a class="btn btn-info" href="{% url 'learning_logs:topics' %}">Done</a>
</section>
{% endblock content %}
url.py
from django.urls import path
from . import views
app_name="learning_logs"
urlpatterns = [
path('', views.index, name='index'),
path('topics/', views.topics, name='topics'),
path('topics/edit/', views.edit_topics, name='edit_topics'),
path('new_topic/', views.new_topic, name='new_topic'),
path('topic_<int:topic_pk>/', views.topic, name='topic'),
path('topic_<int:topic_pk>/new_entry/', views.new_entry, name='new_entry'),
path('topic_<int:topic_pk>/entry_<int:entry_pk>/', views.entry, name='entry'),
path('topic_<int:topic_pk>/entry_<int:entry_pk>/edit_entry/', views.edit_entry, name='edit_entry'),
]
However, I think there might be some logic error, it keeps raising NoReverseMatch(msg) django.urls.exceptions.NoReverseMatch: Reverse for 'edit_topics' with arguments '(1,)' not found. 1 pattern(s) tried: ['topics/edit$']
If I delete form.instance.pk in edit_topics.html file, no error is raised. But consequently, the if logic in the view function wouldn't take action... I'm fairly new to programming, I'm sure there're some logic errors as well --
I'm struggling with the topic_pk optional argument in the view function because I'm not sure how to pass it in correctly.
Ideally, I hope the users can edit, save or delete the topics on this page one by one, and after they click save or delete the page will redirect back to this view and render the updated topic text. At the end, when they are done, they can click the Done button at the end...
Please help! Thanks!!
Feel free to check GitHub Repo for Learning_Log app
Update your url like this:
path('topics/edit/', views.edit_topics, name='edit_topics'),
path('topics/edit/<int:topic_pk>/', views.edit_topics, name='edit_topic'),
And in html, change this line:
<form class="d-flex align-items-center" action="{% url 'learning_logs:edit_topic' form.instance.pk %}" method="POST">
^^^^^^^^^^^
Here, what I did is that, have 2 urls point to same view, one with topic_pk and another is without it.
I'm having trouble working with inherited code to make a functional search bar. I've been having the most trouble properly creating a search_results page.
I stripped down my search_results page to having only one line. search_results.html: <div>You searched for {{ query }}</div> but right now, the search_results page doesn't render {{ query }}. No text that the user previously entered appears. All that shows up on that page is "You searched for"
searchbox.html
<form class="search" action="{% url 'search' %}" method='post'>
{% csrf_token %}
<input type="search" placeholder="Search here..." name="usr_query"
value='{{ query }}' required>
<button type="submit">Search</button>
</form>
views.py
def search(request):
query = request.POST['usr_query']
print "QUERY: "
print query
t = loader.get_template('gtr_site/test_search_results.html')
c = Context({ 'query': query,})
return HttpResponse(t.render(c))
I was getting a little cautious and added that "print" statement... and it does print out what the user enters in the search bar. But that isn't being generated on my search_results page.
Whats the reasoning for this?
edit:
Adding urls.py
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^about/$', views.about, name='about'),
url(r'^contact/$', views.contact, name='contact'),
url(r'^search_engine/$', views.statement_search_engine, name='statement-search') # <- url for searchbox.html,
url(r'^test_search_results/$', views.search, name='test-search'), # <- url for searchresults.
url(r'^(?P<statement_id>.+)/$', views.statement_page, name='statement'),
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
Change value='{{ request.GET.usr_query }}' to value="{{ query }}"
Right now you are forcing it to show the GET parameter. That works on initial page load (which is typically a GET) but at that point you haven't done any searching. You submit the search (properly in my opinion, but it is debatable) as a POST. The search function uses the POST parameter and returns in in context as query, which is correct. But then you display the GET value of usr_query - which does not exist at this point because the page is now a POSTed page. Change the value= and it should work.
Short answer:
Seems like this slipped by:
c = Context({ 'query': query,})
This is in views.py. Context() doesn't cause any error messages but... In order to get the functinality I needed, all I had to do was remove this function and make the c variable a regular dictionary.
I included the Context function because of this stackoverflow question Writing a very basic search form in Django
Your Searchbox.html method is a 'post' instead of a 'get'
<form class="search" action="{% url 'search' %}" method='get'>
{% csrf_token %}
<input type="search" placeholder="Search here..." name="usr_query"
value='{{ query }}' required>
<button type="submit">Search</button>
</form>
views.py
class search(ListView):
model = YourModel #The model model you want to search
template_name = 'gtr_site/test_search_results.html'
def get_queryset(self):
query = self.request.GET.get('usr_query')
object_list = YourModel.objects.filter(modelfield__icontains=query)
return object_list
The in your webpage probably index.html you should add the return.
{% for result in object_list %}
{{ result.name }}
{% endfor %}
I'm receiving this error:
NoReverseMatch at /comments_page/1/post_comment/
Reverse for 'post_comment' with arguments '('',)' not found. 1 pattern(s) tried: ['comments_page/(?P[0-9]+)/post_comment/$']
My views.py
def post_comment(request, product_id):
host_product = Product.objects.get(pk=product_id)
comment = Comment()
comment.product = host_product
comment.author = request.POST["author"]
comment.comment_text = request.POST["comment"]
comment.save()
return render(request, 'comments_page/detail.html', {"host_product": host_product})
My comments_page\urls.py
from django.conf.urls import url
from . import views
app_name = "comments_page"
urlpatterns = [
# /comments_page/
url(r'^$', views.index, name="index"),
# /comments_page/1/
url(r'^(?P<product_id>[0-9]+)/$', views.detail, name="detail"),
# /comments_page/1/post_comment/
url(r'^(?P<product_id>[0-9]+)/post_comment/$', views.post_comment, name='post_comment'),]
My detail.html
<form action="{% url 'comments_page:post_comment' product.id %}" method="post">
{% csrf_token %}
Name: <input type="text" id="author" name="author">
Comment:
<textarea id="comment" name="comment"></textarea><br>
<input type="submit" value="Post Comment">
I think I've identified the problem as being in the product.id here
{% url 'comments_page:post_comment' product.id %}
in the html page. I've tried formatting this a couple of different ways, but I haven't had any luck. Do note, the comment is going through and the form and it works as far as updating the database and loading the entry on the page goes, but the page is not being redirected. I have to reload it manually. Any help would be appreciated.
The error message shows that the argument you pass to the {% url %} tag does not exist and resolves to an empty string. Your view indeed does not pass in a product variable, only a host_product variable. You need to change the tag accordingly:
{% url 'comments_page:post_comment' host_product.id %}
For those who may wonder, the fix is to change the return function in views.py to this
return render(request, 'comments_page/detail.html', {"product": host_product})
I do not understand why this works, but it does. Any suggestions as to how to clean up my post_comment function would be appreciated. I feel it's overly convoluted by using host_product
I'm receiving the following error
Error: Reverse for placeinterest with arguments ('',) and keyword arguments {} not found. 1 pattern(s) tried:
[u'polls/(?P<section_id>[0-9]+)/placeinterest/$']
I worked through the Django example for a polling app, and now I'm trying to create a class registration app adapting what I already have. Error points to line 5 here:
<h1>{{ section.class_name }}</h1>
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
<form action="{% url 'polls:placeinterest' section.id %}" method="post">
{% csrf_token %}
<input type="radio" name="incr" id="incr" value="incr" />
<label for="incr"></label><br />
<input type="submit" value="Placeinterest" />
</form>
But I think the problem is in my placeinterest function:
def placeinterest(request, section_id):
section = get_object_or_404(Section, pk=section_id)
try:
selected_choice = section.num_interested
except (KeyError, Section.num_interested.DoesNotExist):
# Redisplay the question voting form.
return render(request, 'polls/detail.html', {
'section': section,
'error_message': "You didn't select a choice.",
})
else:
section.num_interested += 1
section.save()
# Always return an HttpResponseRedirect after successfully dealing
# with POST data. This prevents data from being posted twice if a
# user hits the Back button.
return HttpResponseRedirect(reverse('polls:results', args=(section.id,)))
I'm not sure what my POST call should be if my Section class looks like this:
class Section(models.Model):
class_name = models.CharField(max_length=200)
num_interested = models.IntegerField(default=0)
pub_date = models.DateTimeField('date published')
def __str__(self):
return self.class_name
def was_published_recently(self):
return self.pub_date >= timezone.now() - datetime.timedelta(minutes=3)
def some_interested(self):
if self.num_interested > 0:
return "There is currently interest in this class"
else:
return "There is currently no interest in this class"
The results part comes up fine in my browser, and here is urls.py for good measure:
from django.conf.urls import url
from . import views
app_name = 'polls'
urlpatterns = [
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^(?P<pk>[0-9]+)/$', views.DetailView.as_view(), name='detail'),
url(r'^(?P<pk>[0-9]+)/results/$', views.ResultsView.as_view(), name='results'),
url(r'^(?P<section_id>[0-9]+)/placeinterest/$', views.placeinterest, name='placeinterest'),
]
Edit: adding the original code from the example in hopes that might help someone see where I went wrong:
urls:
from django.conf.urls import url
from . import views
app_name = 'polls'
urlpatterns = [
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^(?P<pk>[0-9]+)/$', views.DetailView.as_view(), name='detail'),
url(r'^(?P<pk>[0-9]+)/results/$', views.ResultsView.as_view(), name='results'),
url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'),
]
vote function in views.py:
def vote(request, question_id):
question = get_object_or_404(Question, pk=question_id)
try:
selected_choice = question.choice_set.get(pk=request.POST['choice'])
except (KeyError, Choice.DoesNotExist):
# Redisplay the question voting form.
return render(request, 'polls/detail.html', {
'question': question,
'error_message': "You didn't select a choice.",
})
else:
selected_choice.votes += 1
selected_choice.save()
# Always return an HttpResponseRedirect after successfully dealing
# with POST data. This prevents data from being posted twice if a
# user hits the Back button.
return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))
detail.html, where I'm having problems after making my changes:
<h1>{{ question.question_text }}</h1>
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
<form action="{% url 'polls:vote' question.id %}" method="post">
{% csrf_token %}
{% for choice in question.choice_set.all %}
<input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" />
<label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br />
{% endfor %}
<input type="submit" value="Vote" />
</form>
The error has nothing to do with your view. It specifically says it's trying to match the URL named placeinterest in the error. It knows the URL exists, but the arguments are wrong.
It thinks you're trying to pass an empty string as a positional argument. This means that section.id is probably None when the template is rendered. It's converting the null value into an empty string and passing it as a positional argument, hence ('',). That's a tuple with one empty string value in it.
The problem is here:
<form action="{% url 'polls:placeinterest' section.id %}" method="post">
Django can't figure out the url argument as it's misconfigured. Use this:
<form action="{% url 'polls:placeinterest' section_id=section.id %}" method="post">
You also need to ensure that section id is valid a number (be careful of what you supply as "section" as your context.