Django 3.0.8 URL/Template/Routing Troubles "No reverse match" - python

first post so please forgive my ignorance as this is my first django app.
I am trying to create a template that displays all of the information regarding a specific "Ticket" from a list of all open tickets.
Unfortunately I am receiving following message whenever I attempt to add an anchor with a template url tag:
NoReverseMatch at /tickets/tasks/ Reverse for 'order' with arguments
'('',)' not found. 1 pattern(s) tried:
['tickets/order/(?P<ticket_id>[^/]+)/$']
Error message updated. Please see Update below.
And it is ONLY on this one HTML Template.
Below is all of the code I believe will be able to shed some light into the issue:
models.py:
from django.db import models
# Create your models here.
class Ticket(models.Model):
"""A basic support ticket"""
# User ticket title.
ticket_Name = models.CharField(max_length=50)
# When the request was submitted.
ticket_Submitted = models.DateTimeField(auto_now_add=True)
#Ticket Type
ticketTypeChoices=[
('Update', 'Article Edit/Update'),
('Addition', 'New Content/Article Request'),
('Typo', 'Article Typo/Formatting Issue'),
('Issue', 'Website Error/Issue'),
('Other', 'Other'),
]
# Type of ticket (Update, Addition, Typo, Site Issue)
ticket_Type = models.CharField(
max_length=50,
choices=ticketTypeChoices,
default= 'Other'
)
# Users Name
ticket_Contact = models.CharField(max_length=50)
# User Email (for follow up)
ticket_Email = models.EmailField(max_length=254)
# Article URL (if applicable)
ticket_URL = models.CharField(blank=True, max_length=254)
# User description of the issue.
ticket_Description = models.TextField()
#Ticket Status Choices
StatusChoices = [
('Pending', 'Pending'),
('Open', 'Open'),
('Complete', 'Complete'),
('Deferred', 'Deferred'),
('Awaiting Response', 'Awaiting Response'),
]
# Status of the Ticket
ticket_Status = models.CharField(
max_length=50,
choices=StatusChoices,
default= 'Pending'
)
# Comments from HelpDesk Staff
ticket_Comments = models.TextField(blank=True )
#Shows when the ticket was last saved.
ticket_Last_Updated = models.DateTimeField(auto_now=True)
def __str__(self):
"""Return a string representation of the model"""
return self.ticket_Name
views.py:
# Imports Models from the app
from . models import *
# Imports from the Forms List
from . forms import TicketForm
# Create your views here.
# View of all active tickets
def ticket(request):
tickets = Ticket.objects.all().order_by('-ticket_Submitted')
context = {'ticket': tickets}
return render(request, 'tickets/joblist.html', context)
# User can view details about a Ticket
def order(request, ticket_id):
order = Ticket.objects.get(id=ticket_id)
context= {'order': order}
return render(request, 'tickets/tix.html', context)
urls.py
from django.urls import path,include
from . import views
app_name='tickets'
urlpatterns = [
# Include default auth urls.
path('', include('django.contrib.auth.urls')),
# Support Ticket Form
path('submit/', views.submit, name='submit'),
# Contact Us Form
path('contact/', views.contact, name='contact'),
# TicketWeblist
path('tasks/', views.ticket, name='tasks'),
# Ticket Details
path('order/<str:ticket_id>/', views.order, name='order' )
]
Template (joblist.html):
{% for tickets in ticket %}
<tr>
<td>{{tickets.ticket_Name}}</td>
<td>{{tickets.ticket_Type}}</td>
<td>{{tickets.ticket_Contact}}</td>
<td>{{tickets.ticket_Status}}</td>
<td>{{tickets.ticket_Submitted}}</td>
<td>{{tickets.ticket_Last_Updated}}</td>
<td><a class="btn btn-sm btn-info" href="{% url 'tickets:order' ticket.id %}">View</a>
</tr>
{% endfor %}
After reviewing the code a dozen time, all I can be sure of is that is an issue that begins with the template anchor template url tag. (View) but no matter what format I try it comes up with this or a similar error.
UPDATE: At Mel's suggestion changed the url 'order' to 'tickets:order' and am now receiving the following message:
NoReverseMatch at /tickets/tasks/ Reverse for 'order' with arguments
'('',)' not found. 1 pattern(s) tried:
['tickets/order/(?P<ticket_id>[^/]+)/$']
I have been attempting to resolve this issue for about three days and was determined to solve it myself. Any type of help is appreciated and please feel free to point out any spaghetti code or lack of notes as well as I am looking for ways to grow.
Thanks!

You've set a namespace for your urls: app_name = 'tickets'
So correct reverse url would be.
{% url 'tickets:order' tickets.id %}
Can you try changing your order view function to this -
def order(request, ticket_id):
active_order = Ticket.objects.get(id=ticket_id)
context= {'order': active_order}
return render(request, 'tickets/tix.html', context)

You have created a separate urls.py for you app (it looks like it), so be sure to include namespace = tickets in your project urls.py file. And then in your template, you should do as follows:
{% url 'tickets:order' ticket.id %}
In other words, you need to include the name of the app as well.

I just saw that you are passing ticket.id from your template to the view, however there is no ticket.id anywhere in the code. Why don't you try passing a value that is there in the template. It should work.

Related

Django Slug raising error NoReverse Match

I am working on a django project(Django v2.0) which has users from different groups, this group is set up within the user profile. I would like to make the website more personal and have the user's group at the start of the website's url (added in through a slug), after they login.
Ideally once they login they would then be redirected to the right page with that slug at the beginning of the url. Within the login page I access the user's group, this group is called and will from now on be referred to as troop, to minimise confusion with Django groups. Here's my login class post view where I retrieve this:
def post(self, request):
def normal_user(user):
return user.groups.filter(name='Normal_User').exists()
username = request.POST['username']
password = request.POST['password']
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
if normal_user(user):
redirecting_url = 'accounts:home'
elif user.is_superuser:
redirecting_url = 'admin:index'
slug = user.userprofile.troop
return redirect(redirecting_url, slug=slug)
else:
form = AuthenticationForm()
error = True
args = {'form': form, 'error': error}
return render(request, self.template_name, args)
In this case I am trying to access the url "account" which I have called "home" and is in my app "accounts".
My home function in views.py in the app accounts has this code:
def home(request, slug):
args = {'user': request.user}
return render(request, 'accounts/home.html', args)
I do not want to do anything with the slug except display it in the url.
My template view looks like this:
<div class="container">
<br>
<h2><strong>Your Progress:</strong></h2><br>
<h3>
<strong>50% progress</strong>
<div class="progress">
<div class="progress-bar bg-danger progress-bar-striped progress-bar-
animated" role="progressbar" style="width:50%" aria-valuenow="50" aria-
valuemin="0" aria-valuemax="100">50%</div> </div>
</div></h3>
<br><br>
{% endblock %}
I also have a link to 'home' within my navbar and I link it in the similar fashion than the link above, using {% url 'accounts:home' slug = instance.slug %}
I'm currently having the following error:
"NoReverseMatch at /BC/account/
Reverse for 'home' with keyword arguments '{'slug': ''}' not found. 1 pattern(s) tried: ['(?P[-a-zA-Z0-9_]+)/account/$']"
The slug in this case is 'BC'.
My urls.py look like this:
In the root folder:
main_urls = [
path('leaders/admin/', admin.site.urls),
path('account/', include('accounts.urls', namespace='accounts'))
]
urlpatterns = [
path('', include('home.urls', namespace='home_page')),
path('login/', include('login.urls', namespace='login')),
path('<slug:slug>/', include(main_urls))
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
And my urls.py in my accounts app looks something like this:
app_name="accounts"
urlpatterns = [
path('', views.home, name="home")
]
Sorry for the long description, but I've been reading every possible site/video I could find on Django slugs and have not been able to find anything which works yet. Could someone please help me with this problem?
Your regular expression for your url requires the slug to be at least one character long. However, the exception you're getting suggests that the troop name (which is used as the slug named argument) is empty:
Reverse for 'home' with keyword arguments '{'slug': ''}'
If the user isn't required to have a troop, in which case you want to just redirect him to /accounts/ instead of /troop/accounts, I suggest you add a separate URL for just accounts/$, or tweak the regular expression to allow an empty troop.
After poking around my code I found something which works. This is as it seems to be that I should be able to have views which take in a slug argument whilst still working if the slug is empty. To fix this all I did was change the slug part in my view function definitions to **kwargs.
Then I added a varaiable which accessed what the slug was and passed that through my templates for when I have a link.
For example:
def home(request, **kwargs):
slug = request.user.userprofile.troop
args = {'slug_arg': slug}
return render(request, 'accounts/home.html', args)
My links in my templates then look like this: {% url 'accounts:home' slug=slug_arg %}
Edit
I have found that the problem was that during my rendering, I should be able to pass through the slug, and in this case slug=instance.slug was not working and was sometimes coming up as being empty. However if I have it at slug=request.user.userprofile.troop then this works without having to accept an argument from the view.
In having said such, I am unable to do this for the admin site as I do not know how to access the views.py for the admin and thus add the parameter to take in the slug.

how to create a autocomplete input field in a form using Django

I am pretty new to django and its ways. I am trying to create an autocomplete field for a form. My code is as below
forms.py
from django import forms
class LeaveForm(forms.Form):
leave_list = (
('Casual Leave', 'Casual Leave'),
('Sick Leave', 'Sick Leave')
)
from_email = forms.EmailField(required=True, widget=forms.TextInput(attrs={'style': 'width: 400px'}))
start_date = end_date = forms.CharField(widget=forms.TextInput(attrs={'type': 'date', 'style': 'width: 175px'}))
leave_type = forms.ChoiceField(choices=leave_list, widget=forms.Select(attrs={'style': 'width: 400px'}))
comments = forms.CharField(required=True, widget=forms.Textarea(attrs={'style': 'width: 400px; height: 247px'}))
def clean_from_email(self):
data = self.cleaned_data['from_email']
if "#testdomain.com" not in data:
raise forms.ValidationError("Must be #testdomain.com")
return data
What I want to achieve is that when an user types words into the "From Email" field the list of emails I have stored in an external DB should appear in the autocomplete list option.
models.py
from django.db import models
class ListOfUsers(models.Model):
emp_number = models.CharField(db_column='Emp_Number', primary_key=True, max_length=50, unique=True) # Field name made lowercase.
name = models.CharField(db_column='Name', max_length=40) # Field name made lowercase.
supervisor = models.CharField(db_column='Supervisor', max_length=40) # Field name made lowercase.
email = models.CharField(db_column='Email', max_length=50, blank=False, null=False, unique=True) # Field name made lowercase.
class Meta:
managed = False
db_table = 'List of users'
Any idea how this can be done ?
Update :
I started messing around with django-autocomplete-light and now able to get a reply from the autocomplete url. It looks like this
{"results": [{"id": "user1#mydomain.com", "text": "user1#mydomain.com"}, {"id": "user2#mydomain.com", "text": "user2#mydomain.com"}, {"id": "user3#mydomain.com", "text": "user3#mydomain.com"}]}
views.py
class EmailAutocomplete(autocomplete.Select2ListView):
def get_list(self):
qs = ListOfUsers.objects.using('legacy')
if self.q:
qs = qs.filter(email__icontains=self.q).values_list('email', flat=True)
return qs
I still do not know how to get this data to appear in the field "from_email"
I finally got the autocomplete search working using the instructions found here
https://github.com/xcash/bootstrap-autocomplete
https://bootstrap-autocomplete.readthedocs.io/en/latest/
It is very simple to use and does not need to install any app in settings.py and it works for both bootstrap 3 and bootstrap 4
There are lot of other packages available but this was simple and easy for my need.
I am going to explain the code I used
page.html
{% block script %}
<script src="https://cdn.rawgit.com/xcash/bootstrap-autocomplete/3de7ad37/dist/latest/bootstrap-autocomplete.js"></script>
<script>
$('.basicAutoComplete').autoComplete(
{minLength: 1}
);
$('.dropdown-menu').css({'top': 'auto', 'left': 'auto'})
</script>
{% endblock %}
.
.
.
.
.
{% if field.name == "from_email" %}
{% render_field field class="basicAutoComplete form-control" %}
{% else %}
{% render_field field class="form-control" %}
{% endif %}
autoComplete is the function called to perform the action and minLength specifies the minimum length of the text before performing the fetch action
I added an extra CSS to fix the autocomplete dropdown otherwise it was weird.
The Jinja render kept overwriting the class definition from views so I added an if check for it.
urls.py
from . import views
urlpatterns = [
.
.
.
path('email_autocomplete/', views.email_autocomplete, name='email_autocomplete')
]
Added this line to urls.py
forms.py
class LeaveForm(forms.Form):
from_email = forms.EmailField(required=True, widget=forms.TextInput(
attrs={
'style': 'width: 400px',
'class': 'basicAutoComplete',
'data-url': "/domain/email_autocomplete/"
}))
The above is the code for the input field in forms.py. data-url points to where the JSON result would be generated.
views.py
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
from .models import model
def email_autocomplete(request):
if request.GET.get('q'):
q = request.GET['q']
data = model.objects.using('legacy').filter(email__startswith=q).values_list('email',flat=True)
json = list(data)
return JsonResponse(json, safe=False)
else:
HttpResponse("No cookies")
This was the most confusing part for me. The GET request is easy to understand but it took a while to convert the data from model.objects into a JSON formatted object. The trick was to use
values_list('columnName',flat=True)
when filtering the data from the database, then converting to a list using list(data) and finally use JsonResponse to convert it to JSON.
Hope this will help any one who wants a simple autocomplete
A very little addition.
The answer of Abilash is great and very clear.
But if it doesn't work for you, may be you should wrapping you basicAutoComplete activation into
$(document).ready(function(){
};
The reason and some explanation could be found here :
Bootstrap Auto-complete Error: Cannot read property " " of undefined
You can consider a different way to get the autocompletion for the input element using the standard HTML tag <datalist>.
Consider the example below. It does not use Javascript and it does not need anything to do in the server code.
<input list="browsers" id="browser_id" name="browser" placeholder="Starting typing the name of the browser" size="50"/>
<datalist id="browsers">
<option>Chrome</option>
<option>Firefox</option>
<option>Internet Explorer</option>
<option>Opera</option>
<option>Safari</option>
<option>Microsoft Edge</option>
</datalist>
The documentation about the tag is here - https://developer.mozilla.org/en-US/docs/Web/HTML/Element/datalist

Django Reverse Error: NoReverseMatch at

Hello StackOverFlow Members, before i get down to the point, let me retrace my thought/process here to help further slim down my issue. When i click a location object in "location_tree.html" it would redirect me to a new page, "location.html", displaying the location name and its type. From the very same page, the name would be a hyperlink to another page with more details about the "location".
Above is the general flow i want, but when i attempt to click the name from location.html, it redirects me to this error:
NoReverseMatch at /accounts/location/2/
Reverse for 'continent' with keyword arguments '{u'pk': 2}' not found. 1 >pattern(s) tried: ['accounts/location/(?>P\d+)/location_continent/(?P\d+)/']
Some key things to note, i am using python2.7. Lastly, when i remove the {% url %} from location.html everything works perfectly fine.
Here is my working code,
App/models.py:
class Location(models.Model):
title = models.CharField(max_length=255)
location_type = models.CharField(max_length=255, choices=LOCATION_TYPES)
parent = models.ForeignKey("Location", null=True, blank=True,
related_name="parent_location")
def __unicode__(self):
return self.title
class Continent(models.Model):
title = models.CharField(max_length=255)
location = models.OneToOneField(Location, on_delete=models.CASCADE, primary_key=True)
is_an_island = models.BooleanField(default=False)
def __unicode__(self):
return self.location.title
App/views.py:
def view_page_location(request, location_id):
location = Location.objects.get(id=location_id)
if location.location_type == 'Continent':
continent = Continent(location=location, is_an_island=False)
return render(request, 'accounts/location.html', {'location':location, 'continent':continent})
def view_continent(request, pk):
get_continent=get_object_or_404(Continent, pk)
return render(request, 'accounts/location_continent.html', {'get_continent':get_continent})
Project/urls.py:
from App.views import *
url(r'^accounts/location/(?P<location_id>\d+)/', view_page_location, name='location'),
url(r'^accounts/location/(?P<location_id>\d+)/location_continent/(?P<pk>\d+)/', view_continent, name='continent'),
Templates,
location_tree.html:
{% for child in locations %}
{% if child.parent == location %}
<ul>
{{ child }}
location.html:
{% if location.location_type == 'Continent' %}
<h2> Location: {{ location.title }}</h2>
<h3> Type: {{ location.location_type }} </h3></br>
location_continent.html:
<p> hello </p>
I left location_continent pretty generic because i wanted to see if i can get it to work. I feel that something is wrong somewhere in my Urls.py or maybe i'm not properly constructing my views.py.
So the BIG question is, what changes/modifications do i need to alter in order to fix that error? I can't see it myself so i turn to 'you'. Any links for me to read up on and find the answer myself is appreciated as well. I hope my question is clear and not vague.
Two issues.
Your continent url in the location.html doesn't provide location_id argument, you provided only pk. Change it to something like:
{{ location.title }}
In the urls.py, you must add $ at the end of the location url, else there is going to be confusion between location and continent urls. $ has a special meaning in regular expression and means that it requires that the pattern matches the end of the string. Change urls to:
url(r'^accounts/location/(?P<location_id>\d+)/$', view_page_location, name='location'),
url(r'^accounts/location/(?P<location_id>\d+)/location_continent/(?P<pk>\d+)/', view_continent, name='continent')

django categories views(error page not found)

my task is to create on main page of my web site two list one list for my post
and second list categories titles which belong my post.
i create that and work fine,and i create post details connect and again work fine.
but i cant to work category details if i want to see list from my post which belong specific category i cant show me error page not found.
my code
my model
class Category(models.Model):
categorytitle =models.CharField(max_length=1,choices=CAT_CHOICES,unique=True)
slug= models.SlugField()
class Posts(models.Model):
Title = models.CharField(max_length=100,blank=True)
slug= models.SlugField()
category = models.ManyToManyField(Category)
my view category
def view_category(request, slug):
category = get_object_or_404(Category, slug=slug)
return render_to_response('blog/view_category.html', {
'category': category,
'posts': Posts.objects.filter(category=category)
})
my urls category
url(r'^(?P<slug>[^\.]+)/$', views.view_category, name='view_category'),
main template tags
{% for category in categories %}
<li>{{ category.categorytitle }}</li>
{% endfor %}
error message
Page not found (404)
Request Method:
GET
Request URL:
http://127.0.0.1:8000/category1/
Raised by:
blog.views.view_post
No Posts matches the given query.
my view post
def view_post(request, slug):
return render_to_response('blog/movies_details.html', {
'post': get_object_or_404(Movies,slug=slug)
})
my urls view
url(r'^(?P<slug>[^\.]+)/$', views.view_post, name='view_post'),
if i use browser db for sqlite view
Change your regex in urls.py to:
url(r'^(?P<slug>[\w-]+)/$', views.view_category, name='view_category'),
\w = alphanumeric signs + underscore
- = hyphen
(These characters are now allowed in the slug)
And change the Post filter to:
Posts.objects.filter(category_id=category.id)
NOTE:
Posts filtering have to placed before rendering, not in it (do it in the same way like "category")
How do you create slugs in the Category model? In admin? Manually or automatically via prepopulated_fields? Because I don'ลง like in the categorytitle field the max_length=1
If your error message shows: "Raised by: blog.views.view_post" Than obviously django is hitting view_post function in your views and not view_category.
Due to wrong function call view_post can't find the post with slug:"category1" so gives a 404 error ( obviously!! ).
So i will suggest to check out if there is a url mismatch that is causing this first.
So I had a similar problem, did all I could by reading various solutions and none was helpful. My solution was real funny(ironic) since I spent an hour to find out what was wrong.
In the urls.py, the order of the url s is pretty important.
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^', include('shop.urls')),
url(r'^shpcart/', include('shpcart.urls')),
]
The above pattern kept saying 404 shpcart/ not found, but shpcart was already there.
Just as I was about to find myself trying to persuade the pc, I moved the shpcart url 1 line above, everything started to sound. If anyone is stuck like I was, hope this helps
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^shpcart/', include('shpcart.urls')),
url(r'^', include('shop.urls')),
]

Using URL in Django Views? Possible?

I have content = 'Please get me the Python book you talked about, #friend'
Then this in my views.py:
new_content = re.sub(r'(#\w+)', r"<a href='#'>\g<0></a>>", content)
This returns
new_content = 'Please get me the Python book you talked about, <a href='#'>#friend</a>'
I want if a user clicks of #friend, it should redirect to this url:
url(r'^user/(?P<user_name>\w+)/$', views.profile, name='profile'),
How do I include this url(profile) in #{{user.username}}?
You use reverse()
return HttpResponseRedirect(reverse('url_name'))
You can check this answer for reference.
And the documentation for the function.
You may need to pass arguments. You can do it like this:
reverse('profile', kwargs={'user_name': 'auth'})
For your case you can try:
content = 'Please get me the Python book you talked about, #friend'
new_content = re.sub(r'(#\w+)', r"<a href='%s'>\g<0></a>>" % (reverse('profile', kwargs={'user_name': 'friend_username'})), content)
You already named argument it's user_name
# urls.py
url(r'^user/(?P<user_name>\w+)/$', views.profile, name='profile'),
# views.py
from django.views.generic.detail import DetailView
class UserDetailView(DetailView):
"""
Takes keyword argument 'user_name'
and looks for it in database:
User.objects.get(username='dude')
"""
model = User
slug_field = 'username'
context_object_name = 'user'
slug_url_kwarg = 'user_name'
template_name = 'user_detail.html'
# Pass your keyword argument
#{{ user.username }}

Categories

Resources