I have a books app using a UUID with a listview of all books and detailview of individual books. I keep getting the following error message:
NoReverseMatch at /books/
Reverse for 'book_detail' with arguments '('/books/71fcfae7-bf2d-41b0-abc8-c6773930a44c',)' not found. 1 pattern(s) tried: ['books/(?P<pk>[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$']
Here is the models.py file:
# books/models.py
import uuid
from django.db import models
from django.urls import reverse
class Book(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
title = models.CharField(max_length=200)
author = models.CharField(max_length=200)
price = models.DecimalField(max_digits=6, decimal_places=2)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('book_detail', args=[str(self.id)])
The urls.py file where I'm using to convert the id from the model to a uuid.
# books/urls.py
from django.urls import path
from .views import BookListView, BookDetailView
urlpatterns = [
path('', BookListView.as_view(), name='book_list'),
path('<uuid:pk>', BookDetailView.as_view(), name='book_detail'),
]
The top-level urls.py file looks like this and adds a books/ route.
# urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('books/', include('books.urls')),
The views.py file:
from django.views.generic import ListView, DetailView
from .models import Book
class BookListView(ListView):
model = Book
context_object_name = 'book_list'
template_name = 'books/book_list.html'
class BookDetailView(DetailView):
model = Book
context_object_name = 'book'
template_name = 'books/book_detail.html'
And the relevant templates file.
<!-- templates/book_detail.html -->
{% extends '_base.html' %}
{% block content %}
{% for book in book_list %}
<div>
<h2>{{ book.title }}</h2>
</div>
{% endfor %}
{% endblock content %}
I believe I'm implementing this correctly but the URL is not liking my UUID. What is amiss?
The problem is not "adding uuid". The problem is that you are doing the URL reversal twice: once in get_absolute_url and once in the {% url %} tag. Use one or the other, not both.
Either:
{{ book.title }}
Or:
{{ book.title }}
Related
My detail View in Django, isn't successfully displaying the content selected from the listviews. The following is my code.
Models.py:
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Post_Model(models.Model):
Title = models.CharField(max_length=50)
Author = models.ForeignKey(User, on_delete=models.CASCADE)
Body = models.TextField()
def __str__(Self):
return Self.Title + ' | ' + str(Self.Author)
urls.py:
from django.urls import path
from .views import Article_details, Home_page
urlpatterns = [
path('', Home_page.as_view(), name="Home"),
path('Article/<int:pk>/', Article_details.as_view(), name="Article"),
Views.py:
from django.shortcuts import render
from django.views.generic import ListView, DetailView
from . models import Post_Model
class Home_page(ListView):
model = Post_Model
template_name = 'June11App/Home.html'
class Article_details(DetailView):
model = Post_Model
template_name = 'June11App/Article.html'
Html list view:
<h1>Home Page</h1>
<ul>
{% for Post in object_list %}
<li>
<a href="{% url 'Article' Post.pk %}">
{{Post.Title}}
</a>
- {{Post.Author}}<br>
{{Post.Body}}
</li>
<br>
{% endfor %}
</ul>
Html detail view:
<h1>Article Page</h1><br>
{{Post.Author}}
{{Post.Body}}
I hope my query made sense. I don't receive any error on myside, its just not working as it should.
The object data is passed as object and post_model, not Post, so:
<h1>Article Page</h1><br>
{{ object.Author }}
{{ object.Body }}
Note: Models normally have no …Model suffix. Therefore it might be better to rename Post_Model to Post.
Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.
Note: normally the name of the fields in a Django model are written in snake_case, not PascalCase, so it should be: author instead of Author.
I have been working on a blog site using django and I made a way to add post within the home page without going to the admin page but when I post using the new way I get this error
This is my models.py file
from django.db import models
from django.contrib.auth.models import User
from django.urls import reverse
class Post(models.Model):
title = models.CharField(max_length=255)
title_tag = models.CharField(max_length=255)
author = models.ForeignKey(User, on_delete=models.CASCADE)
body = models.TextField(max_length=3500)
def __str__(self):
return (self.title + " | " + str(self.author))
def get_absolute_url(self):
return reverse("article-view", args=(str(self.id)))
This is the views.py file
from django.views.generic import ListView, DetailView, CreateView
from .models import Post
class HomeView(ListView):
model = Post
template_name = "home.html"
class ArticleDetailView(DetailView):
model = Post
template_name = "detail_view.html"
class AddPostView(CreateView):
model = Post
template_name = "add_post.html"
fields = "__all__"
This is the polls/urls.py
from django.urls import path
from .views import HomeView, ArticleDetailView, AddPostView
urlpatterns = [
path('', HomeView.as_view(), name='home'),
path('article/<int:pk>', ArticleDetailView.as_view(), name='article-view'),
path('add_post/', AddPostView.as_view(), name='add_post'),
]
This is the add_post.html file
{% extends 'base.html' %}
{% block content %}
<head>
<title>Adding Post</title>
</head>
<h1>Add Blog Posts</h1>
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<button class="btn btn-secondary">Post</button>
</form>
{% endblock %}
Thank you.
Okay, so it looks like this is caused by the model's get_absolute_url reverse args=(). I changed the below code in models.py from:
def get_absolute_url(self):
return reverse("article-view", args=(str(self.id)))
Into
def get_absolute_url(self):
return reverse("article-view", args=[self.id])
The problem seems to be args=(), it is iterating over the str(self.id). So id=10 would actually be returned as a tuple (1,0). I also removed the str() around the self.id since the URL takes in an int.
I'm trying to display information from my model Administrateur into my HTML Template login.html, but nothing is happening.
This my Model:
from django.db import models
class Administrateur(models.Model):
nom = models.CharField(max_length=30)
prenom = models.CharField(max_length=30)
mdp = models.CharField(max_length=30)
mail = models.CharField(max_length=30)
def _str_(self):
return self.name
This is my view:
def Pseudo(request):
administrateurs = Administrateur.objects.all()
context={'administrateurs':administrateurs}
return render(request, "login.html",context)
This is my HTML:
{% extends "base.html" %}
{% load static %}
{% block content %}
{% for n in administrateurs %}
{{ n.nom }}
{{ n.prenom }}
{% endfor %}
{% endblock %}
I'm not sure what to do with urls.py
Do this step if you have not done it yet:
Add this to the file urls.py in the project's base directory:
from django.urls import include
urlpatterns = [
# your urls
path('login/', include('appname.urls')), #change appname to your app's name
]
now in your app make a new file called urls.py and add this to the file:
from django.urls import path
from .views import Pseudo
urlpatterns = [
path('', Pseudo, name="pseudo"),
]
then check when you go to login page (in url bar) what happens
models.py
from django.db import models
class Profile(models.Model):
name=models.CharField(max_length=20 )
age=models.IntegerField()
def __str__(self):
return self.name
class Like(models.Model):
user=models.ForeignKey(Profile,on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
like=models.IntegerField(default=0)
def __str__(self):
return self.choice_text
views.py
from django.shortcuts import render
from .models import Profile, Like
# Create your views here.
def index(request):
all_name=Profile.objects.all()
context={'all_name':all_name}
return render(request, 'database/index.html',context)
def detail(request, profile_id):
all_likes=Like.objects.get(pk=profile_id)
return render(request, 'database/detail.html', {'all_likes':all_likes})
index.html
<h1>hey</h1>
{% for name in all_name %}
<li>{{ name.name }}</li>
{% endfor %}
detail.html
{{all_likes}}
urls.py
from django.urls import path
from . import views
app_name='database'
urlpatterns = [
path('index/', views.index, name='index'),
path('<int:profile_id>/', views.detail, name='detail'),
]
now http://127.0.0.1:8000/database/index/ produces two list item,
but when I click on both, i am redirecting to http://127.0.0.1:8000/database/1/ .
http://127.0.0.1:8000/database/2/ is working manually but not when I click. Couldn't figure out the error in the code.
You pass all objects to HTML:
all_name = Profile.objects.all()
and on for loop in HTML you used
{% for name in all_name %}
Here:
<li>{{ name.name }}</li>
you are using user.id instead of name.id.
Use:
<li>{{ name.name }}</li>
Then it will use the id of the object in for loop and will hit the correct URL.
I'm new to Django and have been stuck on this for a few days now. Hoping to find some help here. I've searched stackoverflow and read through the django docs but haven't been able to grasp this. I'm using Django 1.6.2 and Python 2.7.
I'm setting up a simple news app in which article has a ManyToMany relationship with category. I'm running into trouble trying to display articles from a specific category. I have the index working displaying all articles and also the single page view is working e.g. clicking on article title from index brings you to the article itself. Once in the article I am displaying the article category. Up to here all is well. When I try to link the category and display an index for all posts in that category I get a NoReverseMatch for the url 'category-archive'.
Should I do this in a view like I'm trying or would the Manager work better? Open to all suggestions and answers. Like I said I'm new so would like to know best practice. Here is my code and thank you in advance for dealing with a noobie.
models.py
from django.db import models
from tinymce import models as tinymce_models
class ArticleManager(models.Manager):
def all(self):
return super(ArticleManager, self).filter(active=True)
class Category(models.Model):
title = models.CharField(max_length=65)
slug = models.SlugField()
def __unicode__(self, ):
return self.title
class Article(models.Model):
title = models.CharField(max_length=65)
slug = models.SlugField()
description = models.CharField(max_length=165)
content = tinymce_models.HTMLField()
categories = models.ManyToManyField(Category)
image = models.ImageField(upload_to='article/images')
active = models.BooleanField(default=False)
timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
updated = models.DateTimeField(auto_now=True, auto_now_add=False)
objects = ArticleManager()
def __unicode__(self, ):
return self.title
class Meta:
ordering = ['-timestamp',]
views.py
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render_to_response, RequestContext, get_object_or_404
from .models import Article, Category
def all_articles(request):
articles = Article.objects.all()
return render_to_response('news/all.html', locals(), context_instance=RequestContext(request))
def single_article(request, slug):
article = get_object_or_404(Article, slug=slug)
return render_to_response('news/single.html', locals(), context_instance=RequestContext(request))
def category_archive(request, slug):
articles = Article.objects.filter(category=category)
categories = Category.objects.all()
category = get_object_or_404(Category, slug=slug)
return render_to_response('news/category.html', locals(), context_instance=RequestContext(request))
single.html - for single article view
{% extends 'base.html' %}
{% block content %}
<h1>{{ article.title }}</h1>
<img src='{{ MEDIA_URL }}{{ article.image }}' class="article-image img-responsive"/>
<p>{{ article.content|safe }}</p>
<p class='small'>
**this next line gets an error for the url 'category-archive'**
{% for category in article.categories.all %}Category: <a href='{% url "category-archive" %}{{ category.slug }}'>{{ category }}</a>{% endfor %}</p>
{% endblock %}
category.html - display all articles in specific category
{% extends 'base.html' %}
{% block content %}
{% for article in articles %}
<h1><a href='{% url "articles" %}{{ article.slug }}'>{{ article }}</a></h1>
<a href='{% url "articles" %}{{ article.slug }}'><img src='{{ MEDIA_URL }}{{ article.image }}' class="img-responsive"/></a>
{{ article.description }}
{% if forloop.counter|divisibleby:4 %}
<hr/>
<div class='row'>
{% endif %}
{% endfor %}
</div>
{% endblock %}
urls.py - project urls
from django.conf.urls import patterns, include, url
from django.conf import settings
from filebrowser.sites import site
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
(r'^tinymce/', include('tinymce.urls')),
(r'^admin/filebrowser/', include(site.urls)),
(r'^grappelli/', include('grappelli.urls')),
(r'^static/(?P<path>.*)$', 'django.views.static.serve',{
'document_root': settings.STATIC_ROOT
}),
(r'^media/(?P<path>.*)$', 'django.views.static.serve',{
'document_root': settings.MEDIA_ROOT
}),
url(r'^admin/', include(admin.site.urls)),
url(r'^$', 'dl.views.home', name='home'),
(r'^news/', include('news.urls')),
(r'^guides/', include('guides.urls')),
)
urls.py - news urls
from django.conf import settings
from django.conf.urls import patterns, include, url
urlpatterns = patterns('news.views',
url(r'^$', 'all_articles', name='articles'),
url(r'^(?P<slug>[-\w]+)/$', 'single_article'),
**This next one is giving me the problem I suspect - should be url to category with articles**
url(r'^chive/(?P<slug>[-\w]+)/?', 'category_archive', name='category-archive'),
)
I would have post it as a comment but i don't have the reputation.
I think that the thing is that the URL Dispatcher expects the category-archive to also get the slug. so you should change the URL in the template to:
{% url "category-archive" category.slug %}
hope this helps!