I am following "django by example"
and i met the problem but i don't know what causes it.
The following is the error page:
NoReverseMatch at /blog/
Reverse for 'post_detail' with arguments '('', '', '')' not found. 1 pattern(s) tried: ['blog/(?P\d{4})/(?P\d{2})/(?P\d{2})/(?P[-\w]+)/$']
Request Method:
GET
Request URL:
http://127.0.0.1:8000/blog/
Django Version:
1.11
Exception Type:
NoReverseMatch
Exception Value:
Reverse for 'post_detail' with arguments '('', '', '')' not found. 1 pattern(s) tried: ['blog/(?P\d{4})/(?P\d{2})/(?P\d{2})/(?P[-\w]+)/$']
Exception Location:
E:\workspace\pycharm\djangobyexample\mysite\env\lib\site-packages\django\urls\resolvers.py in _reverse_with_prefix, line 497
Python Executable:
E:\workspace\pycharm\djangobyexample\mysite\env\Scripts\python.exe
Python Version:
3.5.2
Python Path:
['E:\workspace\pycharm\djangobyexample\mysite',
'E:\workspace\pycharm\djangobyexample\mysite\env\Scripts\python35.zip',
'E:\workspace\pycharm\djangobyexample\mysite\env\DLLs',
'E:\workspace\pycharm\djangobyexample\mysite\env\lib',
'E:\workspace\pycharm\djangobyexample\mysite\env\Scripts',
'c:\users\richard\appdata\local\programs\python\python35\Lib',
'c:\users\richard\appdata\local\programs\python\python35\DLLs',
'E:\workspace\pycharm\djangobyexample\mysite\env',
'E:\workspace\pycharm\djangobyexample\mysite\env\lib\site-packages']
Main URLConfiguration
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^blog/', include('blog.urls', namespace='blog', app_name='blog')),
]
blog/url.py
from django.conf.urls import url
from . import views
urlpatterns = [
# post views
# url(r'^$', views.post_list, name='post_list'),
url(r'^$', views.PostListView.as_view(), name='post_list'),
url(r'^(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})/(?P<post>[-\w]+)/$',
views.post_detail,
name='post_detail'),
#url(r'^(?P<post_id>\d+)/share/$', views.post_share, name='post_share'),
]
views.py
from django.shortcuts import render, get_object_or_404
from .models import Post
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.views.generic import ListView
from .forms import EmailPostForm
from django.core.mail import send_mail
# Create your views here.
class PostListView(ListView):
queryset = Post.published.all()
context_object_name = 'posts'
paginate_by = 3
template_name = 'blog/post/list.html'
def post_detail(request, year, month, day, post):
post = get_object_or_404(Post, slug=post,
status='published',
publish__year=year,
publish__month=month,
publish__day=day)
return render(request, 'blog/post/detail.html', {'post': post})
models.py
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse
class PublishedManager(models.Manager):
def get_query(self):
return super(PublishedManager, self).get_query().filter(status='published')
class Post(models.Model):
STATUS_CHOICES = {
('draft', 'Draft'),
('published', 'Published'),
}
title = models.CharField(max_length=250, primary_key=True)
slug = models.SlugField(max_length=250, unique_for_date='publish')
author = models.ForeignKey(User, related_name='blog_post')
body = models.TextField()
publish = models.DateTimeField(default=timezone.now)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='draft')
class Meta:
# Telling django to sort results by the publish field in descending order by default when we query the database
ordering = ('-publish',)
def __str__(self):
return self.title
objects = models.Manager()
published = PublishedManager()
def get_absolute_url(self):
return reverse('blog:post_detail', args=[self.publish.year,
self.publish.strftime('%m'),
self.publish.strftime('%d'),
self.slug])
detail.html
{% extends "blog/base.html" %}
{% block title %}{{ post.title }}{% endblock %}
{% block content %}
<h1>{{ post.title }}</h1>
<p class="date">
Published {{ post.publish }} by {{ post.author }}
</p>
{{ post.body|linebreaks }}
{% endblock %}
list.html
{% extends "blog/base.html" %}
{% block title %}My Blog{% endblock %}
{% block content %}
<h1>My Blog</h1>
{% for post in posts %}
<h2>
<a href="{{ post.get_absolute_url }}">
{{ post.title }}
</a>
</h2>
<p class="date">
Published {{ post.publish }} by {{ post.author }}
</p>
{{ post.body|truncatewords:30|linebreaks }}
{% endfor %}
{% include "pagination.html " with page=page_obj %}
{% endblock %}
base.html
{% load staticfiles %}
<html>
<head>
<meta charset="UTF-8">
<title>{% block title %}{% endblock %}</title>
</head>
<body>
<div id="content">
{% block content %}
{% endblock %}
</div>
<div id="sidebar">
<h2>My blog</h2>
<p>This is my blog.</p>
</div>
</body>
</html>
This line is giving you the error, because the arguments are invalid.
<!-- <a href="{% url 'blog:post_detail' post.year post.month post.day %}">-->
The post does not have year, month and day attributes -- they are attributes of post.publish.
You are already using {{ post.get_absolute_url }} on the next line of the template to get the url. Since the url tag line is inside an html comment <!-- -->, the easiest fix is to simply delete the line.
Related
I got an error message while clicking [Delete] option/link in post_detail.html:
Page not found (404)
No comment found matching the query
Request Method: GET
Request URL: http://127.0.0.1:8000/post/7/comment/delete/
Raised by: blog.views.CommentDeleteView
Here is my files:
post_detail.html file
{% extends "blog/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
{% if not post.comments.all %}
No Comments Yet...
Add Comment
<br/><br/><br/><br/><br/><br/>
{% else %}
Add Comment
<br/><br/>
{% for comment in post.comments.all %}
<strong>
{{user}},
</strong>
<small>
{{comment.date_added}}
</small>
<br/>
{{comment.body}}
<br/>
{% if request.user == user %}
[Delete]
{% endif %}
<br/><br/>
{% endfor %}
{% endif %}
{% endblock content %}
models.py file
from django.db import models
from django.urls.base import reverse_lazy
from django.utils import timezone
from django.contrib.auth.models import User
from django.urls import reverse
class Comment(models.Model):
post = models.ForeignKey(Post,
on_delete=models.CASCADE,
related_name='comments')
name = models.CharField(max_length=80)
email = models.EmailField()
body = models.TextField()
created = models.DateTimeField(default=timezone.now)
date_added = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.title
class Meta:
ordering = ['-date_added']
views.py file
from django.contrib.messages.api import success
from django.urls.base import reverse_lazy
from users.forms import CommentForm
from django import forms
from django.shortcuts import render
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.views.generic import (
ListView,
DetailView,
CreateView,
UpdateView,
DeleteView
)
from .models import Post, Comment
from django.shortcuts import get_object_or_404
from django.http import HttpResponseRedirect
from django.urls import reverse
class AddCommentView(LoginRequiredMixin,CreateView):
model = Comment
form_class = CommentForm
template_name = 'blog/add_comment.html'
def form_valid(self, form):
form.instance.author = self.request.user
form.instance.post_id = self.kwargs['pk']
return super().form_valid(form)
def get_success_url(self):
pk = self.kwargs['pk']
return reverse_lazy('post-detail', kwargs={'pk': pk})
class CommentDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
model = Comment
template_name = 'blog/comment_delete.html'
def get_success_url(self):
pk = self.kwargs['pk']
return reverse_lazy('post-detail', kwargs={'pk': pk})
def test_func(self):
comment = self.get_object()
return self.request.user == comment.author
comment_delete.html file
{% extends "blog/base.html" %}
{% block content %}
<div class="content-section">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Delete Post</legend>
<h2>Are you sure you want to delete the post comment</h2>
</fieldset>
<div class="form-group">
<button class="btn btn-outline-danger" type="submit">Delete</button>
<a class="btn btn-outline-secondary" href="{% url 'post-detail' object.id %}">Cancel</a>
</div>
</form>
</div>
{% endblock content %}
urls.py file
from django.urls import path
from .views import (
AddCommentView,
PostListView,
PostDetailView,
PostCreateView,
PostUpdateView,
PostDeleteView,
CommentDeleteView,
)
from . import views
urlpatterns = [
path('', PostListView.as_view(), name='blog-home'),
path('post/<int:pk>/', PostDetailView.as_view(), name='post-detail'),
path('post/new/', PostCreateView.as_view(), name='post-create'),
path('post/<int:pk>/update/', PostUpdateView.as_view(), name='post-update'),
path('post/<int:pk>/delete/', PostDeleteView.as_view(), name='post-delete'),
path('post/<int:pk>/comment/delete/', CommentDeleteView.as_view(), name='comment-delete'),
path('post/<int:pk>/comment/', AddCommentView.as_view(), name='post-comment'),
path('about/', views.about, name='blog-about'),
]
So i have a project called star social project this project is similar to a socail media that you can post and create group but this project you can only post when you are in a group. So i get an error message that is not familiar to me which is on the title, i tried to search on google and get some result but when i implement it to my project it does not work. So why im getting this error is because i'm trying to create a comment section and when i click the add comment that's when i get the error message. So i'm here to ask someone to help me because i'm not really familiar on this error and i'm just learning django for about 2 months now.
models.py
##########################
## POSTS MODELS.PY FILE ##
##########################
from django.contrib.auth import get_user_model
from django.db import models
from groups.models import Group
from misaka import html
from django.urls import reverse
from django.utils import timezone
User = get_user_model()
class Post(models.Model):
user = models.ForeignKey(User, related_name='posts', on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now=True)
message = models.TextField()
message_html = models.TextField(editable=False)
group = models.ForeignKey(Group, related_name='posts', null=True, blank=True, on_delete=models.CASCADE)
def __str__(self):
return self.message
def save(self, *args, **kwargs):
self.message_html = html(self.message)
super().save(*args, **kwargs)
def get_absolute_url(self):
return reverse(
'posts:single',
kwargs={
'username': self.user.username,
'pk': self.pk
}
)
class Meta:
ordering = ['-created_at']
class Comment(models.Model):
post = models.ForeignKey(Post, related_name='comments', on_delete=models.CASCADE)
username = models.CharField(max_length=50)
text = models.TextField()
created = models.DateTimeField(auto_now_add=True)
approved = models.BooleanField(default=False)
def __str__(self):
return self.text
def approved(self):
self.approved = True
self.save()
views.py
class AddComment(LoginRequiredMixin, generic.CreateView):
model = Comment
fields = ('username', 'text')
def form_valid(self, form):
post = get_object_or_404(Post, pk=self.kwargs.get('pk'))
self.object = form.save(commit=False)
self.object.post = post
self.object.save()
return super().form_valid(form)
urls.py
########################
## POSTS URLS.PY FILE ##
########################
from django.urls import path
from posts import views
app_name = 'posts'
urlpatterns = [
path('', views.PostList.as_view(), name='all'),
path('by/<username>/', views.UserPost.as_view(), name='for_user'),
path('by/<username>/<int:pk>/', views.PostDetail.as_view(), name='single'),
path('new/', views.CreatePost.as_view(), name='create'),
path('delete/<int:pk>/', views.DeletePost.as_view(), name='delete'),
path('post/comment/', views.AddComment.as_view(), name='add_comment'),
]
comment_form.html
{% extends 'posts/post_base.html' %}
{% load bootstrap4 %}
{% block prepost %}
<h4>Add New Comment</h4>
<form id="commentForm" action="{% url 'posts:add_comment' %}" method="POST">
{% csrf_token %}
{% bootstrap_form form %}
{% buttons %}
<button type="submit" class="btn btn-large btn-primary">Add Comment</button>
{% endbuttons %}
</form>
{% endblock %}
_post.html
<div class="media">
<h3 class="mr-5">#{{ post.user.username }}</h3>
<div class="media-body">
<strong>{{ post.user.username }}</strong>
<h5>{{ post.message_html|safe }}
<time class="time">{{ post.created_at }}</time>
{% if post.group %}
<span class="group-name">in {{ post.group.name }}</span>
{% endif %}
</h5>
<hr>
{% if user.is_authenticated %}
<a class="btn btn-primary btn-comment" href="{% url 'posts:add_comment' %}">Add Comment</a>
{% endif %}
<div class="container">
{% for comment in comment_list %}
<br>
{{ comment.created }}
<p>{{ comment.text|safe|linebreaks }}</p>
<p>Posted By: <strong>{{ comment.username }}</strong></p>
{% endfor %}
</div>
<div class="media-footer">
{% if user.is_authenticated and post.user == user and not hide_delete %}
<a class="btn btn-simple" href="{% url 'posts:delete' pk=post.pk %}" title="delete"><span class="fa fa-remove text-danger" aria-hidden="true"></span><span class="text-danger icon-label">Delete</span></a>
{% endif %}
</div>
</div>
</div>
main urls.py
from django.contrib import admin
from django.urls import path, include
from sm_project import views
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.HomePage.as_view(), name='home'),
path('loginpage/', views.LoginPage.as_view(), name='loginpage'),
path('thankspage/', views.ThanksPage.as_view(), name='thankspage'),
path('accounts/', include('accounts.urls', namespace='accounts')),
path('accounts/', include('django.contrib.auth.urls')),
path('groups/', include('groups.urls', namespace='groups')),
path('posts/', include('posts.urls', namespace='posts')),
]
First you used incorrect action in your comment form i think it should be action="{% url 'posts:AddComment' %}" instead of action="{% url 'posts:add_comment' %}"
and second you are using get_object_or_404() which returns 404 page if object is not found so try to to remove it for debugging you will get exact error.
`I'm working on the code in chapter 1 of the django by example. Followed all instructions and reviewed many feedbacks on this site and other areas but not to my luck. I had earlier attempted get_absolute_url and return reverse method unsuccessfully. I was trying an instructed approach and land exactly the same issues in listview and detailview. I'm a beginner so I guess I'm missing something may be fundamental. Is there any version dependency. I've installed latest django and python. Need advice and thanks for any help!
This is the error message
models.py
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.urls import reverse
# Create your models here.
class PublishedManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(status='published')
class Post(models.Model):
STATUS_CHOICES = (
('draft', 'Draft'),
('published', 'Published'),
)
title = models.CharField(max_length=250)
slug = models.SlugField(max_length=250, unique_for_date='publish_date')
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='blog_posts')
body = models.TextField()
publish_date = models.DateTimeField(default=timezone.now)
created_date = models.DateTimeField(auto_now_add=True)
updated_date = models.DateTimeField(auto_now_add=True)
status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='draft')
objects = models.Manager() # default Manager
published = PublishedManager() # our custom manager
class Meta:
ordering = ['-publish_date',]
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse(
'blog:post_detail',
args=[
self.publish_date.year,
self.publish_date.month,
self.publish_date.day,
self.slug,
]
)
views.py
from django.shortcuts import render, get_object_or_404
from .models import Post
def post_list(request):
posts = Post.published.all()
return render(request, 'blog/post/post_list.html', {'posts':posts})
def post_detail(request, year, month, day, post):
post = get_object_or_404(Post, slug=post,
status='published',
publish_date__year=year,
publish_date__month=month,
publish_date__day=day)
return render(request, 'blog/post/post_detail.html',{'post':post})
urls.py ( For app)
from django.urls import path
from . import views
app_name = 'blog'
urlpatterns = [
#post views
path('', views.post_list, name='post_list'),
path('<int:year>/<int:month>/<int=day>/<slug=post>/',
views.post_detail,
name='post_detail'),
]
admin.py
from django.contrib import admin
from .models import Post
#admin.register(Post)
class PostAdmin(admin.ModelAdmin):
list_display = ('title', 'slug', 'author', 'publish_date', 'status')
list_filter = ('status', 'created_date','publish_date', 'author')
search_fields = ('title', 'body')
prepopulated_fields = {'slug':('title',)}
raw_id_fields = ('author',)
date_hierarchy = 'publish_date'
ordering = ('status', 'publish_date')
post_detail.html
{% extends "blog/base.html" %}
{% block title %}{{post.title}}{% endblock %}
{% block content %}
<h> {{post.title}} </h>
<p class="date">
Published {{ post.publish_date }} by {{ post.author }}
</p>
{{ post.body|linebreaks }}
{%endblock%}
post_list.html
{% extends "blog/base.html" %}
{% block title %}My Blog{% endblock %}
{% block content %}
<h1>My Blog</h1>
{% for post in posts %}
<h2>
<a href="{% url 'blog:post_list' post.title %}"
{{ post.title }}
</a>
</h2>
<p class="date">
Published {{ post.publish_date }} by {{ post.author }}
</p>
{{ post.body|truncatewords:30|linebreaks }}
{% endfor %}
{% endblock %}
Modified post_list.html
{% extends "blog/base.html" %}
{% block title %}My Blog{% endblock %}
{% block content %}
<h1>My Blog</h1>
{% for post in posts %}
<h2>
{% url 'blog:post_detail' post.publish_date.year post.publish_date.month post.publish_date.day post.publish_date.slug as post.title %}
<a href="{{ post.title }}">
{{ post.title }}
</a>
</h2>
<p class="date">
Published {{ post.publish_date }} by {{ post.author }}
</p>
{{ post.body|truncatewords:30|linebreaks }}
{% endfor %}
{% endblock %}
in your post_list.html
change this
<a href="{% url 'blog:post_list' post.title %}"
to
<a href="{% url 'blog:post_list'%}"
your url doesn't accept an argument but you are passing an argument from your template.
I have created an app on Django, following the documentaries. I created base HTML, and then 2 more, list and detail respectively. list.html works fine, but when I click a post, it gets redirected to the same page
I have tried ordering the URLs, but it doesn't work.
models.py
class PublishedManager(models.Manager):
def get_queryset(self):
return super(PublishedManager, self)\
.get_queryset()\
.filter(status='published')
class Post(models.Model):
STATUS_CHOICES = (
('draft', 'Draft'),
('published', 'Published'),
)
title = models.CharField(max_length=250)
slug = models.SlugField(max_length=250,
unique_for_date='publish')
author = models.ForeignKey(User, related_name='blog_posts', on_delete=models.CASCADE)
body = models.TextField()
publish = models.DateTimeField(default=timezone.now)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=10, choices=STATUS_CHOICES,
default='draft')
objects = models.Manager()
published = PublishedManager()
class Meta:
ordering = ('-publish',)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('blog:post_detail', args=[self.publish.year,
self.publish.strftime('%m'),
self.publish.strftime('%d'),
self.slug])
urls.py for the app
urlpatterns = [
url(r'^(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})/'\
r'(?P<post>[-\w]+)/$',
views.post_detail,
name='post_detail'),
url(r'^$', views.post_list, name='post_list'),
]
views.py
def post_list(request):
posts = Post.published.all()
return render(request, 'blog/post/list.html', {'posts': posts})
def post_detail(request, year, month, day, post):
post = get_object_or_404(Post, slug=post, status='published',
publish__year=year,
publish__month=month,
publish__day=day)
return render(request,
'blog/post/detail.html',
{'post': post})
urls.py for main(mysite)
app_name = 'blog'
urlpatterns = [
url(r'^blog/', include('blog.urls')),
url(r'^admin/', admin.site.urls),
]
base.html
{% load staticfiles %}
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}{% endblock %}</title>
</head>
<body>
<div id="content">
{% block content %}
{% endblock %}
</div>
<div id="sidebar">
<h2>My blog</h2>
<p>This is my blog.</p>
</div>
</body>
</html>
list.html
{% extends "blog/base.html" %}
{% block title %}My Blog{% endblock %}
{% block content %}
<h1>My Blog</h1>
{% for post in posts %}
<h2>
<a href="{{ post.get_absolute_url }} " target="_blank">
{{ post.title }}
</a>
</h2>
<p class="date">
Published {{ post.publish }} by {{ post.author }}
</p>
{{ post.body|truncatewords:30|linebreaks }}
{% endfor %}
{% endblock %}
detail.html
{% extends "blog/base.html" %}
{% block title %}My Blog{% endblock %}
{% block content %}
<h1>My Blog</h1>
{% for post in posts %}
<h2>
<a href="{{ post.get_absolute_url }} " target="_blank">
{{ post.title }}
</a>
</h2>
<p class="date">
Published {{ post.publish }} by {{ post.author }}
</p>
{{ post.body|truncatewords:30|linebreaks }}
{% endfor %}
{% endblock %}
You've put the app_name declaration in the wrong urls.py. It needs to go in the one inside the app, not the project-level one.
I made a slug field and I made migrations. My slug field is called slug and it is visible in in the site administration, but it doesn't work properly.
My browser tells me:
TypeError at /None/
detail() got an unexpected keyword argument 'slug'
models.py
from django.db import models
class Question(models.Model):
title = models.CharField(max_length=200)
slug = models.SlugField(null=True, blank=True)
description = models.CharField(max_length=200)
data_published = models.DateTimeField('date published')
large_description = models.TextField(max_length=20000)
def __str__(self):
return self.title
def save(self):
if not self.id:
self.s = slugify(self.q)
super(test, self).save()
def was_published_recently(self):
return self.datum_objave >= timezone.now() - datetime.timedelta(days=1)
urls.py
from django.conf.urls import include, url
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.contrib import admin
urlpatterns = [
url(r'^$', 'books.views.index', name='index'),
url(r'^admin/', include(admin.site.urls)),
url(r'^(?P<slug>[\w_-]+)/$', 'books.views.detail', name='detail'),
]
urlpatterns += staticfiles_urlpatterns()
index.html
{% extends "master.html" %}
{% block h1 %}
<div class="box first">
<div class="row">
<div class="container">
{% for question in latest_question_list %}
<div class="col-xs-12 col-sm-4 col-md-3">
<div class="center">
<h4>{{ question.title }} </h4>
<p>{{ question.description }}</p>
</div>
</div>
{% endfor %}
</div>
</div>
{% endblock %}
{% block title %} Index {% endblock %}
admin.py
from django.contrib import admin
from .models import Question
class QuestionAdmin(admin.ModelAdmin):
question_fields = {"slug": ("title",)}
admin.site.register(Question, QuestionAdmin)
views.py
from django.shortcuts import render
from .models import Question
def index(request):
latest_question_list = Question.objects.all()
context = {'latest_question_list': latest_question_list}
return render(request, 'papers/index.html', context)
def detail(request, book_title):
question = Question.objects.get(title=book_title)
return render(request, 'books/detail.html', {'question': question})`
detail.html
{% extends "master2.html" %}
{% block h1 %}
<div class="center">
<h4>{{question.title}} </h4>
<p>{{question.large_description}}</p>
</div>
{% endblock %}
{% block title %} Detail {% endblock %}
This part of your urls.py, (?P<slug>[\w_-]+), means that there is a view that accepts a parameter named slug and if Django is unable to find that view, it will complain. So your view should probably be something like this:
def detail(request, slug):
question = Question.objects.get(slug=slug)
return render(request, 'papers/detail.html', {'question': question})
UPDATE
It's also a good idea not to create your urls manually in your templates:
{{ question.naslov }}