Keep getting NoReverseMatch error in Django project - python

I am trying to do a update function for this form. The template page displays properly, but once i click submit button, i keep getting the NoReverseMatch error: Reverse for 'update_page' with keyword arguments '{'title': ''}' not found. 1 pattern(s) tried: ['wiki/(?P[^/]+)/update$']
The project does not have models, as per assignment. The db is basically a folder in the same directory. And the files in this folder are being managed through the list_entries(), save_entry() and get_entry() functions in the util.py.
urls:
app_name = "entries"
urlpatterns = [
path("", views.index, name="index"),
path("newpage", views.newpage, name="newpage"),
path("<str:title>", views.open_page, name="open_page"),
path("search/", views.search, name="search_query"),
path("<str:title>/update", views.update_page, name="update_page"),
path("random/", views.random_page, name="random_page"),
path("<str:title>/deleted", views.del_page, name="del_page")
]
My views code:
def update_page(request, title):
entered_content = util.get_entry(title)
form_dict = {'form_title': title, 'form_content': entered_content}
if request.method == "POST":
form = NewPageForm(request.POST or None, initial=form_dict)
if form.is_valid():
title = form.cleaned_data[title]
updated_content = form.cleaned_data['form_content']
util.save_entry(title, updated_content)
return HttpResponseRedirect(reverse("entries:open_page", args=(title), ))
else:
return render(request, "encyclopedia/updatepage.html", {
"form": form
})
return render(request, "encyclopedia/updatepage.html", {
"form": NewPageForm(request.POST or None, initial=form_dict),
"titles": title,
})
The template:
{% block body %}
<h2>Update the {{titles}} entry:</h2>
<form action="{% url 'entries:update_page' title=titles %}" method="post">
{% csrf_token %}
{{ form.form_content}}
<input type="submit" value="Update">
</form>
<form method="GET" action="{% url 'entries:del_page' title=titles %}" >
<button type = "submit" >Delete Entry</button>
</form>
View Entries
{% endblock %}

Could you try removing str from the path, as str according to Django docs, matches any non-empty string, excluding the path separator, '/'. This is the default if a converter isn’t included in the expression.
app_name = "entries"
urlpatterns = [
path("", views.index, name="index"),
path("newpage", views.newpage, name="newpage"),
path("title/", views.open_page, name="open_page"),
path("search/", views.search, name="search_query"),
path("title/update", views.update_page, name="update_page"),
path("random/", views.random_page, name="random_page"),
path("title/deleted", views.del_page, name="del_page")
]

Related

Using array elements as relative URLs in a django template

I am totally new to django, and have been struggling with the following issue for a while.
I am sending a sorted list of lists to a template from views.py to a template, in which each sublist (containing two elements) should be displayed. I would like the first element to be a link, in such a way that the String content should be the relative URL to be displayed.
So I used the following syntax:
{{user.0}}
but it gives me the following error:
TemplateSyntaxError at /app/best_travelled/
Could not parse the remainder: '{{user.0}}' from '{{user.0}}'
Please find below the relevant code snippets:
views.py:
def best_travelled(request):
trips = Trip.objects.all()
user_trips={}
for trip in trips:
user_trips[trip.owner] = user_trips.get(trip.owner,0)+1
user_list = []
for key, value in sorted(user_trips.items(), key = itemgetter(1), reverse = True):
user_list.append([key, value])
context_dict = {'user_list':user_list}
return render(request,'best_travelled.html',context_dict)
Template:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Most Recent Trips - Travelmate</title>
</head>
<body>
<h1>Best-Travelled</h1>
<div>
{% if user_list %}
<ol>
{% for user in user_list %}
{{user.0}}
<li>{{user.0}}, Number of trips: {{user.1}}</li>
{% endfor %}
</ol>
{% else %} There are no travellers yet! This is your chance to become the very first one! <br /> {% endif %}
Add a New Trip
</div>
<div>
<ul>
<li>Login</li>
</ul>
</div>
</body>
</html>
And for the profiles:
views.py
#login_required
def view_profile(request,username):
user = get_object_or_404(User, username=username)
trips = Trip.objects.filter(owner=request.user)
context_dict = {'user':user, 'trips':trips }
return render(request,'view_profile.html',context_dict)
app/urls.py
urlpatterns = [
url(r'^$', views.home, name='home'),
url(r'^about/$', views.about, name='about'),
url(r'^contact/$', views.contact, name='contact'),
url(r'^pop_trips/$', views.pop_trips, name='pop_trips'),
url(r'^recent_trips/$', views.recent_trips, name='recent_trips'),
url(r'^best_travelled/$', views.best_travelled, name='best_travelled'),
url(r'^most_active_travellers/$', views.contact, name='most_active_travellers'),
url(r'^passport/$', views.passport, name='passport'),
url(r'^add_trip/$', views.add_trip, name='add_trip'),
url(r'^settings/$', views.settings, name='settings'),
url(r'^my_trips/$', views.my_trips, name='my_trips'),
url(r'^(?P<username>[\w\-]+)/$', views.view_profile, name='view_profile')
]
project/urls.py
urlpatterns = [
url(r'^$', app_views.home, name='home'),
url(r'^admin/', admin.site.urls),
url(r'^login/$', auth_views.login, name='login'),
url(r'^logout/$',auth_views.logout,name='logout'),
url(r'^oauth/',include('social_django.urls',namespace='social')),
url(r'^accounts/register/$', MyRegistrationView.as_view(), name='registration_register'),
url(r'^accounts/',include('registration.backends.simple.urls')),
url(r'^app/', include('app.urls')),
url(r'^(?P<username>[\w\-]+)/$', app_views.view_profile, name='view_profile'),
]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Thanks heaps to anyone who can help!
You don't have to use {{ for variables inside {%. Just write:
{{user.0}}
It should be:
{{user.0}}
Considering you have:
url(r'my-url/(?P<arg_1>[0-9a-f-]+)/(?P<arg_2>[a-f-]+)/$', MyClassView.as_view(), name="url_name"),
Where:
url_name is the name of your url
arg_1 and arg_1 are your arguments for your url(if there is the case, if not stays without them).
like: {{user.0}}
Side-note:
Once you are {% here %} all the context pushed is available without any extra {{ and }}

NoReverseMatch for form using django-select2

I have two view section, one of them saves the fields into database and the other is to autocomplete a field. How can I use both of them in a html template?
First View:
def stock(request):
stocks_form=StocksForm(None)
if request.method == "POST":
stocks_form =StocksForm(data=request.POST)
if stocks_form.is_valid():
instance=stocks_form.save()
instance.user=request.user
instance.save()
messages.success(request,"Successful" ,extra_tags="savestock")
else:
messages.error(request, "Error!")
else:
stocks_form=StocksForm()
return render(request,'BallbearingSite/stock.html',{'stocks_form':stocks_form})
Second View:
class StocksAutocomplete(autocomplete.Select2QuerySetView):
def get_queryset(self):
if not self.request.user.is_authenticated():
return Stocks.objects.none()
qs = Stocks.objects.all()
if self.q:
qs = qs.filter(name__istartswith=self.q)
return qs
urls.py
url(r'^stock/$',views.stock,name='stock'),
url(r'^stock_autocomplete/$',views.StocksAutocomplete.as_view(create_field='name'),name='stock_autocomplete'),
Project urls.py:
urlpatterns = [
url(r'^$',views.index,name='index'),
url(r'^ajax_select/', include(ajax_select_urls)),
url(r'^admin/BallbearingSite/controlsite/$',views.sendemailview),
url(r'^admin/', include(admin.site.urls)),
url(r'^',include('BallbearingSite.urls', namespace='BallbearingSite')),
url(r'^logout/$',views.user_logout,name='logout'),
url(r'^login/$',views.user_login,name='login'),
url(r'^ckeditor/', include('ckeditor_uploader.urls')),
url('^', include('django.contrib.auth.urls')),
]
Template:
<form enctype="multipart/form-data" method="post" >
{% csrf_token %}
{{ stocks_form.as_p }}
<input id="savestocks" type="submit" name="" value="ثبت">
</form>
forms.py:
class StocksForm(forms.ModelForm):
class Meta():
model=Stocks
fields=('name','number','suffix','brand','comment','price')
widgets = {
'name': autocomplete.ModelSelect2(url='stock_autocomplete')
}
def clean_name(self):
return self.cleaned_data['comment'].upper()
It has this error:
NoReverseMatch at /stock/
Reverse for 'stock_autocomplete' with arguments '()' and keyword arguments'{}' not found. 0 pattern(s) tried: []
It highlighted these parts in error :
{{ stocks_form.as_p }}
and :
return render(request,'BallbearingSite/stock.html',{'stocks_form':stocks_form})
It looks like you might be missing the namespace from the url. If the stock_autocomplete url is in the BallbearingSite namespace, you would do:
'name': autocomplete.ModelSelect2(url='BallbearingSite:stock_autocomplete')

Reverse for 'sending_message' not found. 'sending_message' is not a valid view function or pattern name

I have an app called com when I try to access viewing_user template which contains a form with action to another view get the error above
this is urls.py
app_name = 'com'
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^(?P<name>[\w\-]+)/$',views.viewing_user, name='viewing_user'),
]
this is the views.py
from django.shortcuts import render
from django.contrib.auth.models import User
# Create your views here.
RECEIVER_ID = 0
def index(request):
return render(request, 'com/index.html',{})
def viewing_user(request, name):
#username = request.GET.get('username','')
try:
User_obj = User.objects.get(username = name)
RECEIVER_ID = User_obj.id
except User.DoesNotExist:
User_obj = None
return render(request, 'com/viewing_user.html',{'u':name,'obj':User_obj})
def sending_message(request):
form = MessageForm()
if request.method == 'POST':
form = MessageForm(request.POST)
if form.is_valid:
message = message_form.save(commit = False)
message.date = datetime.date.now()
message.from_user = user.id
message._to = RECEIVER_ID
message.save()
else:
print form.errors
return render(request, 'com/viewing_user.html', {'form':form})
this is the template vieweing_user.html which seems that has a problem in the action of the form
<html>
{% if obj == None %}
<h2>Sorry this user ({{u}}) DoesNotExist</h2>
{% else %}
<h3>Be honest, and Tellme what you want</h3>
<br>
<i>{{obj.username}}</i>
<form method="post" action="{%url 'com:sending_message' %}">
{%csrf_token%}
{% for hidden in form.hidden_fields%}
{{hidden}}
{%endfor%}
{% for visible in form.visible_fields%}
{{visible}}
{%endfor%}
<input type="submit" value='Tell'/>
</form>
{%endif%}
</html>
reverse tries to look for its parameter value in urlpatterns. You do not have any url pattern with name sending_message in com namespace.
You would want to create an url pattern with name sending_message
url(r'^(?Psomepattern)/$',views.sending_message, name='sending_message'),

Django redirect doesn't append to previous pattern

urls.py
url(r'^reg/$', views.reg_view, name='reg'),
url(r'^logout/$', views.logout_view, name="logout"),
url(r'^search/$', views.search_redirect, name='search_redirect'),
url(r'^search/(?P<keyword>.*?)/page/(?P<page>[0-9]+)/$', views.SearchView.as_view(), name='search'),
url(r'^search/(?P<keyword>.*?)/$', views.SearchView.as_view(), name='search'),
url(r'^t/create/$', views.create_topic, name='create_topic'),
url(r'^notifications/$', views.NotificationView.as_view(), name='notifications'),
url(r'^avatar/$', views.upload_avatar, name="upload_avatar"),
Those are icluded in the main urls.py as this(the forum one):
url(r'^accounts/', include('userena.urls')),
url(r'^forum/', include(niji_urls, namespace="niji")),
url(r'^$', index, name="index"),
url(r'^despre-noi/$', despre_noi, name='desprenoi'),
url(r'^(mugshots/.*)$', serve, {'document_root': settings.MEDIA_ROOT, }),
url(r'^messages/', include('userena.contrib.umessages.urls')),
url(r'^magazin/', include(application.urls)),
# url(r'^magazin/', include('magazin.urls', namespace="magazin")),
url(r'^oferte/', include('oferte.urls', namespace="oferte")),
Form
<form class="navbar-form navbar-left" role="search" method="get" action="{% url 'niji:search_redirect' %}">
<div class="form-group">
<input type="text" id="keywordInput" name="keyword" class="form-control" placeholder="{% trans 'Search' %}">
</div>
<button type="submit" id="navSearchBtn" class="btn btn-default">{% trans 'Search' %}</button>
</form>
Views.py
class SearchView(ListView):
model = Topic
paginate_by = 30
template_name = 'niji/search.html'
context_object_name = 'topics'
def get_queryset(self):
keywords = self.kwargs.get('keyword')
query = get_query(keywords, ['title'])
return Topic.objects.visible().filter(
query
).select_related(
'user', 'node'
).prefetch_related(
'user__forum_avatar'
).order_by(
get_topic_ordering(self.request)
)
def get_context_data(self, **kwargs):
context = super(ListView, self).get_context_data(**kwargs)
context['title'] = context['panel_title'] = _('Search: ') + self.kwargs.get('keyword')
context['show_order'] = True
return context
def search_redirect(request):
if request.method == 'GET':
keyword = request.GET.get('keyword')
return HttpResponseRedirect(reverse('niji:search', kwargs={'keyword': keyword}))
else:
return HttpResponseForbidden('Post you cannot')
When the user uses the form to submit a search query, the url becomes example.com/search/... instead of example.com/forum/search/.. . If I manually enter the url latter, it works perfectly, so I assume it has to be some how related to the form? Or the search_redirect function?
Apparently, it had something to do with the button. Specifically the id I think. I don't know exactly what.. but removing it made it work

Django HTML POST parameters causes NoReverseMatch

I have an HTML post with two drop down lists, I want to send selected Country in those lists to the search() method that's in views.py and then send me to the results view. Whenever I add government and location as parameters for the html POST action or add their value in the search regex, I try this I get a NoReverseMatch from my index page:
Reverse for 'search' with arguments '('', '')' and keyword arguments '{}' not found. 1 pattern(s) tried: ['search/(?P[A-Z]{3})/(?P[A-Z]{3})/']
and I don't what I'm doing wrong to cause this error. (See comments in code)
appname/views.py:
from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect, HttpResponse
from .models import Country, Embassy
from django.template import loader
from django.urls import reverse
def index(request):
country = Country.objects.filter()
template = loader.get_template('appname/index.html')
context = {'countries': country}
return render(request, 'appname/index.html', context)
def results(request, government, location):
return HttpResponse("Here are the Embassies sent by %s, located in %s." % (government, location))
def search(request):
countries = Country.objects.all()
form = request.POST
if request.method == 'POST':
try:
selected_government = get_object_or_404(pk=request.POST['government'])
except (KeyError, Country.DoesNotExist):
return render(request, 'appname/index.html', {
'error_message': "You didn't select a government.",
})
try:
selected_location = get_object_or_404(pk=request.POST['location'])
except (KeyError, Country.DoesNotExist):
return render(request, 'appname/index.html', {
'error_message': "You didn't select a location.",
})
else:
return HttpResponseRedirect(reverse('appname:results', args=(selected_government.code,selected_location.code,)))
appname/templates/appname/index.html:
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
# government and location in the form action causes a NoReverse Match
<form action="{% url 'appname:search' government location %}" method="POST">
{% csrf_token %}
<label>Find Embassies sent by</label>
<select name="government">
{% for entry in countries %}
<option value="{{ entry.code }}">{{ entry.name }}</option>
{% endfor %}
</select>
<label>that are located in</label>
<select name="location">
{% for entry in countries %}
<option value="{{ entry.code }}">{{ entry.name }}</option>
{% endfor %}
</select>
<input type="submit" value="Search" />
</form>
urls.py:
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r'^', include('appname.urls')),
url(r'^appname/', include('appname.urls')),
url(r'^admin/', admin.site.urls),
]
appname/urls.py:
from django.conf.urls import url
from . import views
app_name = 'appname'
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^(?P<embassy_id>[0-9]+)/$', views.embassy_info, name='embassy_info'),
url(r'^(?P<code>[A-Z]{3})/$', views.country_info, name='country_info'),
url(r'^find/(?P<government>[A-Z]{3})/(?P<location>[A-Z]{3})/$', views.results, name='results'),
# the government and location values in search regex also cause a NoReverse Match
url(r'^search/(?P<government>[A-Z]{3})/(?P<location>[A-Z]{3})/', views.search, name='search'),
]
appname/models.py:
from django.db import models
class Country(models.Model):
code = models.CharField(primary_key=True, max_length=3)
name = models.CharField(max_length=50, db_column="Name")
def __str__(self):
return self.name
class Meta:
verbose_name = 'Country'
verbose_name_plural = 'Countries'
class Embassy(models.Model):
government = models.ForeignKey(Country, on_delete=models.CASCADE, related_name="government")
location = models.ForeignKey(Country, on_delete=models.CASCADE, related_name="location")
name = models.CharField(max_length=200, db_column="Name")
street_address = models.CharField(max_length=200, db_column="Address")
city = models.CharField(max_length=50, db_column="City")
phone_number = models.IntegerField(default=-1, db_column="Phone Number")
fax_number = models.IntegerField(null=True, blank=True, db_column="Fax Number")
email_address = models.CharField(max_length=200, db_column="Email")
website = models.CharField(max_length=200, db_column="Link")
def __str__(self):
return self.name
class Meta:
verbose_name = 'Embassy'
verbose_name_plural = 'Embassies'
It doesn't work like that. The parameters to the url tag - like any template tag in fact - have to come from the context passed to the template at render time. But you're trying to use values dynamically from the form itself.
You should remove the parameters from the URL pattern altogether. You're not using them in the view anyway since you correctly get the values from request.POST.
url(r'^search/$', views.search, name='search'),
...
<form action="{% url 'search' %}" ...
You need to create a form with ModelChoiceField.
In forms.py
from django import forms
from models import Country
class SearchForm(forms.Form):
government = forms.ModelChoiceField(queryset=Country.objects.all(), to_field_name="code", label="Find Embassies sent by")
location = forms.ModelChoiceField(queryset=Country.objects.all(), to_field_name="code", label="that are located in")
In views.py
from forms import SearchForm
def index(request):
form = SearchForm()
context = {'form': form}
return render(request, 'appname/index.html', context)
def search(request):
form = SearchForm(request.POST or None)
if request.POST and form.is_valid():
govt = form.cleaned_data.get('government')
loc = form.cleaned_data.get('location')
return HttpResponseRedirect(reverse('appname:results', kwargs={"government": govt.code, "location": loc.code}))
else:
context = {'form': form}
return render(request, 'appname/index.html', context)
In appname/urls.py
add this url
url(r'^search/$', views.search, name='search'),
In index.html
<form method="post" action={% url 'appname:search' %}>
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Search" />
</form>
Django URL resolver reverse takes keyword arguments as parameters
reverse('search', kwargs={'government':goverment.code, 'location':location.code})
Hope this helps

Categories