Django No Reverse Match Error - django

I've been working on this error for the better part of a week and this is the error I keep receiving:
>
NoReverseMatch at /practice/practice/2/saleinfoedit/
Reverse for 'car_detail' with keyword arguments '{'pk': ''}' not found. 1 pattern(s) tried: ['practice/practice/(?P<pk>\\d)$']
I've simplified the code to what are the relevant parts of the error, I think. The idea is to have a list page of cars and when you click on the car link you can edit the Sale History of the vehicle. Eventually I'll setup formsets for this part, but babysteps. Here's the relevant code:
models.py
class Car(models.Model):
car_name = models.CharField(max_length=200)
color = models.CharField(max_length=200)
age = models.CharField(max_length=200)
def get_absolute_url(self):
return reverse('practice:car_detail',kwargs={'pk':self.pk})
def __str__(self):
return '%s' %(self.car_name)
class SaleInfo(models.Model):
car_name = models.ForeignKey(Car, on_delete=models.CASCADE,)
price = models.CharField(max_length=100)
date = models.CharField(max_length=100)
comments = models.CharField(max_length=200)
def __str__(self):
return '%s' %(self.car_name)
def get_absolute_url(self):
return reverse('practice:car_detail',kwargs={'pk':self.pk})
views.py
class IndexView(generic.ListView):
template_name = 'practice/carlist.html'
context_object_name = 'latest_car_list'
def get_queryset(self):
return Car.objects.all()
class DetailView(generic.DetailView):
model = Car
form_class = CarForm
template_name = 'practice/car_detail.html'
class UpdateView(generic.UpdateView):
model = Car
form_class = CarFormEdit
class SaleInfoUpdateView(generic.UpdateView):
model = SaleInfo
form_class = SaleInfoFormEdit
template_name = 'practice/saleinfo_form.html'
urls.py
app_name = 'practice'
urlpatterns = [
url(r'^$', views.IndexView.as_view(), name='index'), # shows lists of Cars via Car Name
url(r'^practice/(?P<pk>\d)$', views.DetailView.as_view(), name='car_detail'),
url(r'^practice/(?P<pk>\d)/edit/$', views.UpdateView.as_view(), name='car_edit'),
url(r'^practice/(?P<pk>\d)/saleinfoedit/$', views.SaleInfoUpdateView.as_view(), name='saleinfo_edit'),
]
car_detail.html
{% extends 'practice/car_base.html' %}
{% block post_content %}
<div class="col-md-8">
<a class='btn btn-primary' href="{% url 'practice:car_edit' pk=car.pk %}">
<span class='glyphicon glyphicon-pencil'></span>
</a>
<p>{{ car.car_name|safe }}</p>
<p>{{ car.color|safe }} {{ car.age|safe }} </p>
<a class='btn btn-primary' href="{% url 'practice:saleinfo_edit' pk=car.pk %}">
<span class='glyphicon glyphicon-pencil'> SaleInfo</span>
</a>
</div>
{% endblock %}
saleinfo_form.html
{% extends 'practice/car_base.html' %}
{% block post_content %}
{% load bootstrap3 %}
<form class="" action="" method="post">
{% csrf_token %}
{% bootstrap_form form %}
<!-- {{form.as_p}} -->
<input type="submit" name="" value="Update">
</form>
{% endblock %}
I can post my templates too if necessary. I'm sure it's something simple I keep looking past, but after a few days I'm lost.

According to the error message, the parameter pk you have given to the {% url %} tag is empty:
...with keyword arguments '{'pk': ''}'
There are two common reasons for that:
You have a typo in your variable name in your template.
You are creating a new object, so it doesn't have an ID/PK yet.
Your templates look fine though, so here is how I would debug it:
Remove {% url %} tags one after the other until you find the actual culprit.
Print out the variable you pass as keyword argument pk.
One more thing: \d matches exactly one digit, so your URL patterns will stop working once you have more than 9 cars. You have to add a + to match one or more digits:
url(r'^practice/(?P<pk>\d+)/edit/$', views.UpdateView.as_view(), name='car_edit'),
Also, like #wencakisa remarked, URLs in Django usually end with a slash, but that isn't mandatory.
Edit: I just noticed two more things:
your SaleInfo.get_absolute_url method uses practice:car_detail. Shouldn't that be saleinfo_edit?
in the car_detail.html template, you use {% url 'practice:saleinfo_edit' pk=car.pk %}. That won't work. If there is only one SaleInfo per car, use a OneToOneField instead of a ForeignKey in your model. Then you can do something like:
{% if car.sale_info %}
{% url 'practice:saleinfo_edit' pk=car.sale_info.pk %}
{% endif %}

Related

How to set success url as the previous page after updating an instance in django

I am trying to redirect the user to the previous page after they have updated an instance in the Model Class. So, here is the view for the update:
class ClassStatusDetailView(OrganisorAndLoginRequiredMixin, generic.UpdateView):
model = Class
template_name = "agents/class_status_detail.html"
context_object_name = "class"
fields = ['status']
def get_success_url(self):
return reverse("agents:agent-list")
Right now, as you can see, the get_success_url is set to "agents:agent-list", which is not the previous page. Also, here is the template for the update view in case you need it:
{% extends "base.html" %}
{% load tailwind_filters %}
{% block content %}
<div class="max-w-lg mx-auto">
<a class="hover:text-blue-500" href="#">Something</a>
<div class="py-5 border-t border-gray-200">
<h1 class="text-4xl text-gray-800">{{ class.student }}</h1>
</div>
<form method="post" class="mt-5">
{% csrf_token %}
{{ form|crispy }}
<button type='submit' class="w-full text-white bg-blue-500 hover:bg-blue-600 px-3 py-2 rounded-md">
Update
</button>
</form>
</div>
{% endblock content %}
However, there is a catch. The previous page I want to return to is a function view with a primary key. So, not only do I have to go back to this function view, but I also have to go to the correct primary key. Please tell me if you guys need any other information. Thank you!
When user successfully update their data then he/she redirect to class_list.html page..
urls.py(I assume):
path('class_list/<int:pk>/', class_list,name = 'class_list'),
path('edit_class/<int:pk>/', ClassStatusDetailView.as_view(),name = 'edit_class')
models.py:
class ClassStatusDetailView(OrganisorAndLoginRequiredMixin, generic.UpdateView):
model = Class
template_name = "agents/class_status_detail.html"
context_object_name = "class"
fields = ['status']
def get_success_url(self):
agent_id = self.object.teacher.id
return reverse_lazy('class_list', kwargs={'pk': agent_id})
Use reverse_lazy

how do i create a profile page that shows all users post to the user and to other users

am new to Django and am trying to create a blog site where users can sign up and post articles, but my problem is how can I display a user's post on the user's profile page so that when other users reading the post clicks on the author's name it takes them to the post.author's profile page with the post.author's recent post listed and not the request.user's post. here is my code.
here is accounts/views.py
views.py
#login_required()
def user_profile_view(request, username):
post = User.objects.filter(courses__author=username)
context = {'courses': courses}
return render(request, 'accounts/user_profile_view.html', context)
and here is post/models.py
models.py
class Posts(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE)
cover = ProcessedImageField(upload_to='post_featured_image',
processors=[ResizeToFill(600, 300)],
format='png',
options={'quality': 80},
blank=True)
slug = models.SlugField()
title = models.CharField(max_length=200)
body = models.TextField()
summary = models.TextField(max_length=200)
here is the template
post_list.html
{% extends 'base.html' %}
{% load static %}
{% block content %}
<div class="col-lg-6">
{% for course in courses_list %}
<div class="central-meta item">
<div class="user-post">
<div class="friend-info">
{% if post.author.profile.avatar %}
<figure>
<img src="{{ post.author.profile.avatar.url }}" alt="">
</figure>
{% else %}
<img src="{% static 'default.ico' %}" alt="">
{% endif %}
<div class="friend-name">
<ins>{{ course.author.get_full_name|title }}</ins>
<span>published: {{ post.published }}</span>
</div>
<div class="post-meta">
{% if course.cover %}
<img src="{{ post.cover.url }}" alt="">
{% endif %}
<div class="friend-name">
<ins>{{ course.title|title }}</ins>
</div>
<div class="description">
<p><span>{{ post.summary|capfirst }}</span></p>
</div>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
{% endblock content %}
here is my accounts/urls.py
urls.py
app_name = 'accounts'
urlpatterns = [
path('accounts/profile/<str:username>/', user_profile_view, name='user_profile'),
]
you should be able do that, easy and via lots of ways.
make a post model like this:
class Post(models.Model):
author = foreign_key(User, related_name="posts", on_delete=models.CASCADE)
title = char_field()
content ........
so with that related name you will be able to reverse from user to its posts too!.
in your template do this:
{{ post.author }}
this link will redirect user to the posts author dashboard if you arrange the urls pattern correctly.
then for sorting authors posts, you have to pass the dashboard_owner to the template and use this name instead of user which normally will refer to the request.user -> user who are visiting the page
{% for post in dash_owner.posts.all %}
<li> <a href="{{ post.get_abslute_url }}" target="_blink">
{{ post.title }} </a> </li>
{% endfor %}
in views.py
def dashboard(request, owner_id=None)
if owner_id:
dash_owner = get_or_404(User, id=owner_id)
elif request.user.is_authenticated:
dash_owner = User.objectd.get(id=request.user.id)
return render(request, 'dashboard.html', {'dash_owner': dash_owner})
in urls.py -> urlpatterns:
path('dashboard/<int:owner_id>/', views.dashboard, name="dashboard")
this is the idea behind that, but for get the better result, you may need to clearly define the get_absolute_url of User model, to give you the url which machts to
'dashboard/<int:id/'
or another way is instead of that, do this:
{{ post.author }}

urlpatterns not behaving as expected

I have specified a url to list students and a url to display the student details however the url for the student details doesnt seem to work.
The ursl.py looks like this:
urlpatterns = [
path('', views.SchoolListView.as_view(), name='list'),
path('<int:pk>/',views.SchoolDetailView.as_view(),name='detail'),
path('create/', views.SchoolCreateView.as_view(),name='create'),
path('update/<int:pk>/',views.SchoolUpdateView.as_view(),name='update'),
path('delete/<int:pk>/',views.SchoolDeleteView.as_view(),name='delete'),
path('students', views.StudentListView.as_view(), name='student_list'),
path('students/<int:pk>/',views.StudentDetailView.as_view(),name='student_details'),
]
but when I click on the actual student it doesnt take me to basic_app/students/1 (for example) but to basic_app/1
Also when I manually type /basic_app/students/1 I get an error which says:
NoReverseMatch at /basic_app/students/1/
Reverse for 'update' with keyword arguments '{'pk': ''}' not found. 1
pattern(s) tried: ['basic_app/update/(?P<pk>[0-9]+)/$']
no reverse error
my views:
class StudentListView(ListView):
context_object_name = 'students'
model = models.Student
class StudentDetailView(DetailView):
context_object_name = 'student_details'
model = models.Student
template_name = 'basic_app/student_detail.html'
the model:
class Student(models.Model):
name = models.CharField(max_length=150)
age = models.PositiveIntegerField()
school = models.ForeignKey(School, related_name='students', on_delete=models.CASCADE)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse("basic_app:student_details",kwargs={'pk':self.pk})
The student_details.html template:
{% extends 'basic_app/basic_app_base.html' %}
{% block body_block %}
<div class="container jumbotron">
<h2>Student Details:</h2>
<p>Name: {{student_details.name}}</p>
<p>Principal: {{student_details.age}}</p>
<p>Location: {{student_details.school}}</p>
<!-- <div class="container">
<a class="btn btn-primary" href="{% url 'basic_app:update' pk=school_details.pk %}">Update</a>
<a class="btn btn-danger" href="{% url 'basic_app:delete' pk=school_details.pk %}">Delete</a>
Cancel
</div> -->
{% endblock %}
What have I done wrong?`
The commented-out section in your student_details.html may be producing the error. Delete that part and it should work:
{% extends 'basic_app/basic_app_base.html' %}
{% block body_block %}
<div class="container jumbotron">
<h2>Student Details:</h2>
<p>Name: {{student_details.name}}</p>
<p>Principal: {{student_details.age}}</p>
<p>Location: {{student_details.school}}</p>
{% endblock %}

How can I send to DJANGO template the variable of current data?

I need to print the list of persons whose birthdays are today.
I do not know the correct way to introduce the current data variable in the if loop.
personal_list.html
{% for personal in personals %}
{% ifequal personal.data_nastere|date:"d/m" '??/??' %}
<ul>
<li><a class="titleOmagiat" href="{% url 'personalomagiat_detail' pk=personal.pk %}">
{{ personal.name }} {{ personal.surname }} </a>, {{ personal.birth_day|date:"d/m/Y" }}
</li>
</ul>
{% endifequal %}
{% endfor %}
models.py
class Personal(models.Model):
name = models.CharField(max_length=20)
surname = models.CharField(max_length=20)
birth_day = models.DateField(blank=True, null=True)
class Meta:
ordering = ['name']
def __str__(self):
return '%s %s' % (self.name, self.surname)
views.py
def personal_list(request):
personals = Personal.objects.order_by('name')
return render(request, 'blog/personal_list.html', {'personals': personals})
urls.py
urlpatterns = [
url(r'^personal/$', views.personal_list, name='personal_list'),
]
Tell me the correct answer in code.
The filtering must be done at the database level, not in the template, otherwise you are reading data from disk that you are not using which results in poor performances.
Update your view this way:
from django.utils import timezone
def personal_list(request):
today = timezone.now().date()
personals = Personal.objects.order_by('name').filter(
birth_day__month=today.month,
birth_day__day=today.day)
return render(request, 'blog/personal_list.html', {'personals': personals})
And your template this way:
<ul>
{% for personal in personals %}
<li><a class="titleOmagiat" href="{% url 'personalomagiat_detail' pk=personal.pk %}">
{{ personal.name }} {{ personal.surname }} </a>, {{ personal.birth_day|date:"d/m/Y" }}
</li>
{% endfor %}
</ul>

Django class based views with url issue

I'm trying to get to grips with class based views.
I have urls.py as follows:
urlpatterns = patterns('homework.views',
(r'^index/$', 'index'),
url(r'^(?P<sub_slug>\w+)/$', NavListView.as_view(), name='nav'),
url(r'^(?P<sub_slug>\w+)/(?P<class_grp_slug>\w+)/$', SubNavListView.as_view(), name='subnav'),
url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
url(r'^admin/', include(admin.site.urls)),)
I have my views.py:
# Subject navigation
class NavListView(ListView):
template_name = 'templates/home.html'
def get_queryset(self):
self.subject = Subject.objects.all()
return self.subject
def get_context_data(self, **kwargs):
context = super(NavListView, self).get_context_data(**kwargs)
context['subjects'] = self.subject
return context
# Class group navigation
class SubNavListView(NavListView):
def get_queryset(self):
self.group = Group.objects.filter(subject__name__iexact=self.kwargs['sub_slug'])
return self.group
def get_context_data(self, **kwargs):
context = super(NavListView, self).get_context_data(**kwargs)
context['groups'] = self.group
return context
In my 'templates/home.html' I have:
{% extends 'templates/base.html' %}
{% load url from future %}
{% block nav-menu-items %}
<ul class="nav">
{% for sub in subjects %}
<li class="">{{ sub }}</li>
{% endfor %}
<li class="active">Add Subject</li>
</ul>
{% endblock nav-menu-items %}
{% block class_groups_nav %}
<div class="tabbable">
<ul class="nav nav-tabs">
{% for group in groups %}
<li>
<a data-toggle="tab" href="{% url 'subnav' sub_slug class_grp_slug %}">{{ group }}</a>
</li>
{% endfor %}
<li>Add</li>
</ul>
{% endblock class_groups_nav %}
I'm trying to achieve a 'nav' of subjects, then a 'subnav' below showing a tab for each class group for the subject selected in the navigation above.
I've tried different ways of doing this such as making Subject.objects.all() available as context processors. I have also attempted to subclass NavListView so I can inherit the previous context, making them available in SubNavListView.
At the moment, I'm getting a NoReverseMatch error where the url named 'nav' is not passing the sub_slug and so I can't use it in the url in the template.
Any thoughts on getting this working?
Many thanks,
Assuming your Subject model has field named slug in it, you need to update your code to
<li class="">{{ sub }}</li>
ie. pass an appropriate parameter to {%url ... %}. Change sub.slug to whatever field name you want to refer to.
If you want to, you can also do {% url 'nav' sub_slug=sub.slug %}.
You are trying to pass sub_slug, but which is not defined in the template context, and result in empty string. So nav url will not get any parameter.
I see similar problem in your other {%url ...%} tags in the template.