I have done a lot of experiments and very much feel out of my depth. I can't get existing comments to appear (I added some via the admin page) or the comment form. I have tried to Google the problem and rearrange my code. Unfortunately I don't have the foggiest idea what is causing the problem. So I don't know if any of my experiments were remotely along the right lines.
After posting the original question I tried using dispatch() in my code. I got error messages I tried to Google but I was just trying to apply band aid on top of band aid.
post_detail.html
{% extends "blog/base.html" %}
{% block content %}
<article class="media content-section">
<img class="rounded-circle article-img" src="{{ object.author.profile.image.url }}">
<div class="media-body">
<div class="article-metadata">
<a class="mr-2" href="#">{{ object.author }}</a>
<small class="text-muted">{{ object.date_posted|date:"F d, Y" }}</small>
{% if object.author == user %}
<div>
<a class="btn btn-secondary btn-sm mt-1 mb-1" href="{% url 'post-update' object.id %}">Update</a>
<a class="btn btn-danger btn-sm mt-1 mb-1" href="{% url 'post-delete' object.id %}">Delete</a>
</div>
{% endif %}
</div>
<h2 class="article-title">{{ object.title }}</h2>
<p class="article-content">{{ object.content }}</p>
</div>
</article>
<article class="media content-section">
<!-- comments -->
<h3>{{ comments.count }} Comments</h3>
{% for comment in comments %}
<div class="media-body">
<a class="mr-2" href="#">{{ comment.name }}</a>
<small class="text-muted">{{ comment.created_on|date:"F d, Y" }}</small>
</div>
<h2 class="article-title">{{ object.title }}</h2>
<p class="article-content">{{ comment.body | linebreaks }}</p>
{% endfor %}
</article>
{% endblock content %}
views.py
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
from .forms import CommentForm
from django.shortcuts import render, get_object_or_404
def home(request):
context = {
'posts': Post.objects.all()
}
return render(request, 'blog/home.html', context)
class PostListView(ListView):
model = Post
template_name = 'blog/home.html' # <app>/<model>_<viewtype>.html
context_object_name = 'posts'
ordering = ['-date_posted']
#class PostDetailView(DetailView):
# model = Post
class PostDetailView(DetailView):
model = Post
def dispatch():
post = get_object_or_404(Post)
comments = post.comments.filter(active=True, slug=slug)
new_comment = None
if request.method == 'POST':
comment_form = CommentForm(data=request.POST)
if comment_form.is_valid():
new_comment = comment_form.save(commit=False)
new_comment.post = post
new_comment.save()
else:
comment_form = CommentForm()
return render(request, post_detail.html, {'post': post,
'comments': comments,
'new_comment': new_comment,
'comment_form': comment_form})
class PostCreateView(LoginRequiredMixin, CreateView):
model = Post
fields = ['title', 'content']
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
class PostUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = Post
fields = ['title', 'content']
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
def test_func(self):
post = self.get_object()
if self.request.user == post.author:
return True
return False
class PostDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
model = Post
success_url = '/'
def test_func(self):
post = self.get_object()
if self.request.user == post.author:
return True
return False
def about(request):
return render(request, 'blog/about.html')
forms.py
from .models import Comment
from django import forms
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('name', 'email', 'body')
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 Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
date_posted = models.DateTimeField(default=timezone.now())
author = models.ForeignKey(User, on_delete=models.CASCADE)
url= models.SlugField(max_length=500, unique=True, blank=True)
def save(self, *args, **kwargs):
self.url= slugify(self.title)
super().save(*args, **kwargs)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('article_detail', kwargs={'slug': self.slug})
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_on = models.DateTimeField(auto_now_add=True)
active = models.BooleanField(default=False)
class Meta:
ordering = ['created_on']
def __str__(self):
return 'Comment {} by {}'.format(self.body, self.name)
urls.py (in Blog app)
from django.urls import path
from .views import (
PostListView,
PostDetailView,
PostCreateView,
PostUpdateView,
PostDeleteView
)
from. import views
from django.views.generic import TemplateView
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('about/', views.about, name='blog-about'),
path('facebook/',TemplateView.as_view(template_name='blog/index.html'), name="facebook")
]
signals.py (in Users app)
from django.db.models.signals import post_save
from django.contrib.auth.models import User
from django.dispatch import receiver
from .models import Profile
#reciever(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
#reciever(post_save, sender=User)
def save_profile(sender, instance, created, **kwargs):
instance.profile.save()
correct your indentation of the code
class PostDetailView(DetailView):
model = Post
def post_detail(request, slug):
post = get_object_or_404(Post, slug=slug)
comments = post.comments.filter(active=True)
new_comment = None
# Comment posted
if request.method == 'POST':
comment_form = CommentForm(data=request.POST)
if comment_form.is_valid():
# Create Comment object but don't save to database yet
new_comment = comment_form.save(commit=False)
# Assign the current post to the comment
new_comment.post = post
# Save the comment to the database
new_comment.save()
else:
comment_form = CommentForm()
return render(request, template_name, {'post': post,
'comments': comments,
'new_comment': new_comment,
'comment_form': comment_form})
Related
I am new to Django and I'm having problems with comment forms. I just want to add a text field for comment on a specific Post's page, but it is hidden. Here is my models.py file in blog app:
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.urls import reverse
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk': self.pk})
class Comment(models.Model):
post = models.ForeignKey(Post, related_name='comments', on_delete=models.CASCADE)
author = models.ForeignKey(User, on_delete=models.CASCADE)
content = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
class Meta:
ordering = ['date_posted']
def __str__(self):
return '{} - {}'.format(self.author, self.date_posted)
forms.py:
from django import forms
from .models import Comment
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('content',)
views.py file:
from django.db import models
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.mixins import UserPassesTestMixin
from django.contrib.auth.models import User
from django.shortcuts import redirect, render
from django.shortcuts import get_object_or_404
from django.views.generic import ListView
from django.views.generic import DetailView
from django.views.generic import CreateView
from django.views.generic import UpdateView
from django.views.generic import DeleteView
from .forms import CommentForm
from .models import Post
from .models import Comment
def home(request):
context = {
'title': 'Home',
'posts': Post.objects.all()
}
return render(request, 'blog/home.html', context)
class PostListView(ListView):
model = Post
template_name = 'blog/home.html'
context_object_name='posts'
ordering = ['-date_posted']
paginate_by = 7
class UserPostListView(ListView):
model = Post
template_name = 'blog/user_posts.html'
context_object_name='posts'
paginate_by = 7
def get_queryset(self):
user = get_object_or_404(User, username=self.kwargs.get('username'))
return Post.objects.filter(author=user).order_by('-date_posted')
def post_detail(request, slug):
template_name = 'post_detail.html'
post = get_object_or_404(Post, slug=slug)
comments = post.comments.filter(active=True)
new_comment = None
if request.method == 'POST':
comment_form = CommentForm(data=request.POST)
if comment_form.is_valid():
new_comment = comment_form.save(commit=False)
new_comment.post = post
new_comment.save()
else:
comment_form = CommentForm()
return render(request, template_name, {'post': post,
'comments': comments,
'new_comment': new_comment,
'form': comment_form})
class PostCreateView(LoginRequiredMixin, CreateView):
model = Post
fields = ['title', 'content']
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
class PostUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = Post
fields = ['title', 'content']
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
def test_func(self):
post = self.get_object()
if self.request.user == post.author:
return True
return False
class PostDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
model = Post
success_url = '/'
def test_func(self):
post = self.get_object()
if self.request.user == post.author:
return True
return False
def about(request):
return render(request, 'blog/about.html', {'title': 'About'})
and finally, the post_detail.html template where everything should be displayed:
{% extends 'blog/base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<article class="media content-section">
<img class="rounded-circle article-img" src="{{ object.author.profile.image.url }}">
<div class="media-body">
<div class="article-metadata">
<a class="mr-2" href="{% url 'user-posts' object.author.username %}">
{{ object.author }}
</a>
<small class="text-muted">{{ object.date_posted | date:"F d, Y" }}</small>
{% if object.author == user %}
<div>
<a class="btn btn-secondary btn-sm mt-1 mb-1" href="{% url 'post-update' object.id %}">Update</a>
<a class="btn btn-danger btn-sm mt-1 mb-1" href="{% url 'post-delete' object.id %}">Delete</a>
</div>
{% endif %}
</div>
<h2 class="article-title">
{{ object.title }}
</h2>
<p class="article-content">{{ object.content }}</p>
</div>
</article>
<div>
<strong><h2>Comments Section</h2></strong>
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Leave A Comment</legend>
{{ form | crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Leave A Comment</button>
</div>
</form>
<ul>
{% for comment in object.comments.all %}
<div>
<img class="rounded-circle article-img" src="{{ post.author.profile.image.url }}">
{{ comment.author }} - {{ comment.date_posted | date:"F d, Y" }}
<br>
{{ comment.content }}
</div>
{% endfor %}
</ul>
</div>
{% endblock content %}
I am stuck with the problem. Any suggestions are appreciated.
I am working on a movie website with Django and I'm trying to add user comments. Only the registered users should be allowed to comment. I have the following so far:
models.py:
class Comment(models.Model):
movie = models.ForeignKey(Movie, related_name = "comments", on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete = models.CASCADE)
content = models.TextField()
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
return '%s - %s' % (self.movie.title, self.name)
forms.py
class CommentForm(forms.ModelForm):
content = forms.CharField(label ="", widget = forms.Textarea(
attrs ={
'class':'form-control',
'placeholder':'Comment here!',
'rows':5,
'cols':50
}))
class Meta:
model = Comment
fields =['content']
views.py
class MovieDetailsView(generic.DetailView):
model = Movie
template_name = "details.html"
def comment(request, id):
movie= Movie.objects.get(id)
if request.method == 'POST':
cf = CommentForm(request.POST or None)
if cf.is_valid():
content = request.POST.get('content')
comment = Comment.objects.create(movie = movie, user = request.user, content = content)
comment.save()
return redirect(movie.get_absolute_url())
else:
cf = CommentForm()
context ={
'comment_form':cf,
}
return render(request, 'details.html', context)
details.html
<form method="POST" action="#" class="form">
{% csrf_token %}
{{comment_form.as_p}}
<button type="submit" class="btn btn-primary btn-lg">Submit</button>
<textarea id="text" name="text" class="form__textarea" placeholder="Add comment"></textarea>
<button type="button" class="form__btn">Send</button>
</form>
The MovieDetailsView displays the details page of the movie and has a comment section. However, when I submit the comment, it simply displays a white page and this link: http://127.0.0.1:8000/details/1# . The comment is not saved on the database and I can't seem to find what the issue is. I am also following the example from this link.
Thanks in advance!
You can combine FormMixin with DetailView - Using FormMixin with DetailView.
from django.urls import reverse
from django.views.generic.detail import DetailView
from django.views.generic.edit import FormMixin
from django.http import HttpResponseForbidden
class MovieDetailsView(FormMixin, DetailView):
model = Movie
template_name = "details.html"
form_class = CommentForm
def get_success_url(self):
return reverse('movie_detail', kwargs={'pk': self.object.pk})
# or
# return self.object.get_absolute_url()
def post(self, request, *args, **kwargs):
if not request.user.is_authenticated:
return HttpResponseForbidden()
self.object = self.get_object()
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
form.instance.user = self.request.user
form.instance.movie = self.object
form.save()
return super().form_valid(form)
In the post() method, we first check if the user is logged in:
if not request.user.is_authenticated:
return HttpResponseForbidden()
In template:
<form method="POST" class="form">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary btn-lg">Submit</button>
</form>
You can remove the action attribute, the form will be submitted to the same page.
I am having this error any time i want to view posts that belong to a group
NoReverseMatch at /groups/posts/in/python/
Reverse for 'user-posts' with keyword arguments '{'username': ''}' not found. 1 pattern(s) tried: ['user/(?P<username>[^/]+)$']
Following is my urls.py codes
from django.urls import path
from .views import (PostListView, PostCreateView,
PostUpdateView, PostDetailView, PostDeleteView, UserPostListView)
from . import views
app_name = 'posts'
urlpatterns = [
path('', PostListView.as_view(), name="blog-home"),
path('user/<str:username>', UserPostListView.as_view(), name="user-posts"),
path('post/<int:pk>/', PostDetailView.as_view(), name="post-detail"),
path("post/<int:pk>/", views.post_comment, name="comments"),
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('about/', views.about, name="blog-about"),
]
The problem seems to be coming from my _posts.html file, but I cant resolve it.
here is the _posts.html codes
<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 }}</h5>
<time class="time">{{ post.created_at }}</time>
{% if post.group %}
<span class="group-name">in {{ post.group.name }}</span>
{% endif %}
</h5>
<div class="media-footer">
{% if user.is_authenticated and post.user == user and not hide_delete %}
<a href="{% url 'posts:post-delete' pk=post.pk %}" title="delete" class="btn btn-simple">
<span class="fa fa-remove text-danger" aria-hidden="true"></span>
<span class="text-danger icon-label">Delete</span>
</a>
{% endif %}
</div>
</div>
</div>
Once I click on the group's list page to take me to posts associated with the group, I get the above error.
Someone said the username I am passing to the urls.py is empty, i cant figure out what is wrong with code from my views.py
from django.contrib import messages
from django.contrib.auth.mixins import (LoginRequiredMixin, UserPassesTestMixin)
from django.contrib.auth.models import User
from django.urls import reverse_lazy, reverse
from django.http import HttpResponseRedirect, Http404
from django.shortcuts import render, get_object_or_404, redirect
from django.views.generic import (ListView, DetailView, CreateView,
UpdateView, DeleteView)
from .models import Post, Comment
from django.core.files.storage import FileSystemStorage
from .forms import CommentForm, PostForm
from . import models
def home(request):
context = {
'posts': Post.objects.all()
}
return render(request, 'blog/home.html', context)
def upload(request):
if request.method == 'POST':
form = PostForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect('post_detail')
else:
form = PostForm()
return render(request, 'blog/post_detail.html',
{'form': form })
class PostListView(ListView):
model = Post
template_name = 'blog/home.html'
context_object_name = 'posts'
ordering = ['-date_posted']
paginate_by = 6
class UserPostListView(ListView):
model = Post
template_name = 'blog/user_posts.html'
context_object_name = 'posts'
paginate_by = 6
def get_queryset(self):
user = get_object_or_404(User, username=self.kwargs.get('username'))
return Post.objects.filter(author=user).order_by('-date_posted')
class PostDetailView(DetailView):
model = Post
def post_comments(request, slug):
template_name = 'blog/post_detail.html'
post = get_object_or_404(Post, slug=slug)
comments = post.comments.filter(active=True)
new_comment = None
# Comment posted
if request.method == 'POST':
comment_form = CommentForm(data=request.POST)
if comment_form.is_valid():
# Create Comment object but don't save to database yet
new_comment = comment_form.save(commit=False)
# Assign the current post to the comment
new_comment.post = post
# Save the comment to the database
new_comment.save()
else:
comment_form = CommentForm()
return render(request, template_name, {'post': post,
'comments': comments,
'new_comment': new_comment,
'comment_form': comment_form})
class PostCreateView(LoginRequiredMixin, CreateView):
model = models.Post
fields = ['title', 'content', 'group', 'image']
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
class PostUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = Post
fields = ['title', 'content']
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
def test_func(self):
post = self.get_object()
if self.request.user == post.author:
return True
return False
class PostDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
model = Post
success_url = reverse_lazy('blog-home')
def test_func(self):
post = self.get_object()
if self.request.user == post.author:
return True
return False
def about(request):
return render(request, 'blog/about.html', {'title': 'About'})
There is nothing wrong with your urls.py and template. The problem is with '{'username': ''}' because username is empty it won't match with the regex(user/(?P<username>[^/]+)$). try to find out why username is empty.
I am new to coding and especially new to working with Django. I want to build a small "forum" for me and the other students and it works pretty fine.
There is just one error I encounter over and over:
Exception Type: NoReverseMatch
Exception Value: Reverse for 'thread-create' with
arguments '('',)' not found. 1 pattern(s) tried: ['forum/(?P<pk>[0-9]+)/add/$']
I can work around it using functions instead of class based Views, but I doubt that's how it's supposed to be done.
I have the feeling I am missing something very important while working with class views.
I really would appreciate if someone could help me out :-)
It's the links that are not working:
{% url 'user-posts' thread.author.username %}
and more importantly:
{% url 'forum:thread-create' thread.id %}
What's also not working while using classes is:
{% for thread in thema.thread_set %} (works with the functions)
(I only want to see the threads that are bind to a certain thema. That also works pretty well with functions).
And you might also be asking why I don't just use the function based views:
I want to know what am I doing wrong
I want to be able to easy paginate my site.
Code:
# models.py
from django.db import models
from django.urls import reverse
from PIL import Image
from django.utils import timezone
from django.contrib.auth.models import User
class Thema(models.Model):
themengebiet = models.CharField(max_length=350)
beschreibung = models.TextField()
themen_logo = models.FileField(max_length=350, upload_to="logos", default='default.jpg')
erstellt_am = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.themengebiet
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
img = Image.open(self.themen_logo.path)
if img.height > 300 or img.width > 300:
output_size = (300, 300)
img.thumbnail(output_size)
img.save(self.themen_logo.path)
class Thread(models.Model):
thema = models.ForeignKey(Thema, on_delete=models.CASCADE)
titel = models.CharField(max_length=350)
author = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
erstellt_am = models.DateTimeField(default=timezone.now)
thread_logo = models.ImageField(upload_to="logos", d efault='default.jpg')
def get_absolute_url(self):
return reverse('forum:thread-page', kwargs={'pk': self.thema.id})
def __str__(self):
return self.titel
class Posting(models.Model):
thread = models.ForeignKey(Thread, on_delete=models.CASCADE)
titel = models.CharField(max_length=350)
erstellt_am = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
inhalt = models.TextField()
def __str__(self):
return self.titel
views.py
from django.views import generic
from django.views.generic import CreateView, UpdateView, DeleteView, ListView
from .models import Thema, Thread, Posting
from django.shortcuts import render, get_object_or_404
from django.urls import reverse_lazy
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.decorators import login_required
from django.http import Http404
from django.core.paginator import Paginator
class ThemenView(ListView):
template_name = 'forum/posts_original.html'
context_object_name = 'all_themen'
def get_queryset(self):
return Thema.objects.all()
class ThemaCreate(CreateView):
model = Thema
fields = ['themengebiet', 'beschreibung', 'themen_logo']
success_url = "/forum/"
class ThreadCreate(CreateView):
model = Thread
fields = ['thema', 'titel', 'erstellt_am']
success_url = reverse_lazy('forum:posts_original')
def get_object(self):
return Thread.objects.get(pk=self.kwargs['pk'])
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
class PostCreate(CreateView):
model = Posting
fields = ['thread', 'titel', 'inhalt', 'erstellt_am']
success_url = "/forum/"
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
class ThreadView(ListView):
model = Thread
context_object_name = 'threads'
template_name = 'forum/thread.html'
success_url = reverse_lazy('forum:posts_original')
def get_object(self):
return Thread.objects.get(pk=self.kwargs['pk'])
class PostView(ListView):
model = Posting
context_object_name = 'posts'
template_name = 'forum/posts.html'
urls.py
from django.urls import path
from . import views
app_name = 'forum'
urlpatterns = [
# /forum/
path('', views.ThemenView.as_view(), name='posts_original'),
# forum/id/
path('<int:pk>/', views.ThreadView.as_view(), name='thread-page'),
# forum/thread/add
#path('<int:pk>/add/', views.thread_create, name='thread-create'),
# forum/id//id
path('thread/<int:pk>/', views.PostView.as_view(), name='post-page'),
path('add/', views.ThemaCreate.as_view(), name='thema-create'),
path('<int:pk>/add/', views.ThreadCreate.as_view(), name='thread-create'),
path('thread/<int:pk>/add/', views.PostCreate.as_view(), name='post-create'),
]
'''
def thread(request, pk):
try:
thema = get_object_or_404(Thema, pk=pk)
except Thema.DoesNotExist:
raise Http404("Thema existitiert nicht")
return render(request, 'forum/thread.html', {'thema': thema})
def post(request, pk):
try:
thread = get_object_or_404(Thread, pk=pk)
except Thread.DoesNotExist:
raise Http404("Thema existitiert nicht!")
return render(request, 'forum/posts.html', {'thread': thread})
'''
{% extends "blog/base.html" %}
{{ threads }}
{% block content %}
Zurück zur Themenübersicht
{% for thread in threads %}
<article class="media content-section">
<img class="rounded-circle article-img" src= "{{ thread.thread_logo.url }}">
<div class="media-body">
<div class="article-metadata">
<a class="mr-2" href="{% url 'user-posts' thread.author.username %}">{{ thread.author }}</a>
<small class="text-muted">{{ thread.erstellt_am|date:"d. F Y" }}</small>
</div>
<h2><a class="article-title" href=" {% url 'forum:post-page' thread.id %}">{{ thread.titel }}</a></h2>
<p class="article-content">Thema: {{ thread.thema }}</p>
</div>
</article>
{% endfor %}
<form action="{% url 'forum:thread-create' thread.id %}" method="post" enctype="multipart/form-data" style="display: inline;">
{% csrf_token %}
Thread hinzufügen
</form>
{% endif %}
{% endblock content %}
I keep getting this error in django: NoReverseMatc, and I can't figure out why.
my models.py:
from django.conf import settings
from django.core.urlresolvers import reverse
from django.db import models
import misaka
from groups.models import Group
from django.contrib.auth import get_user_model
User = get_user_model()
class Post(models.Model):
user = models.ForeignKey(User, related_name="posts")
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)
def __str__(self):
return self.message
def save(self, *args, **kwargs):
self.message_html = misaka.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"]
unique_together = ["user", "message"]
my views.py:
from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.urlresolvers import reverse_lazy
from django.http import Http404
from django.views import generic
from braces.views import SelectRelatedMixin
from . import forms
from . import models
from django.contrib.auth import get_user_model
User = get_user_model()
class PostList(SelectRelatedMixin, generic.ListView):
model = models.Post
select_related = ("user", "group")
class UserPosts(generic.ListView):
model = models.Post
template_name = "posts/user_post_list.html"
def get_queryset(self):
try:
self.post_user = User.objects.prefetch_related("posts").get(
username__iexact=self.kwargs.get("username")
)
except User.DoesNotExist:
raise Http404
else:
return self.post_user.posts.all()
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["post_user"] = self.post_user
return context
class PostDetail(SelectRelatedMixin, generic.DetailView):
model = models.Post
select_related = ("user", "group")
def get_queryset(self):
queryset = super().get_queryset()
return queryset.filter(
user__username__iexact=self.kwargs.get("username")
)
class CreatePost(LoginRequiredMixin, SelectRelatedMixin, generic.CreateView):
# form_class = forms.PostForm
fields = ('message','group')
model = models.Post
# def get_form_kwargs(self):
# kwargs = super().get_form_kwargs()
# kwargs.update({"user": self.request.user})
# return kwargs
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.user = self.request.user
self.object.save()
return super().form_valid(form)
class DeletePost(LoginRequiredMixin, SelectRelatedMixin, generic.DeleteView):
model = models.Post
select_related = ("user", "group")
success_url = reverse_lazy("posts:all")
def get_queryset(self):
queryset = super().get_queryset()
return queryset.filter(user_id=self.request.user.id)
def delete(self, *args, **kwargs):
messages.success(self.request, "Post Deleted")
return super().delete(*args, **kwargs)
and my urls.py is this:
from django.conf.urls import url
from . import views
app_name='posts'
urlpatterns = [
url(r"^$", views.PostList.as_view(), name="all"),
url(r"new/$", views.CreatePost.as_view(), name="create"),
url(r"by/(?P<username>[-\w]+)/$",views.UserPosts.as_view(),name="user_posts"),
url(r"by/(?P<username>[-\w]+)/(?P<pk>\d+)/$",views.PostDetail.as_view(),name="single"),
url(r"delete/(?P<pk>\d+)/$",views.DeletePost.as_view(),name="delete"),
]
my _post.html:
<div class="post media">
<h3>{{ post.message_html|safe }}</h3>
<div class="media-body">
<strong>{{ post.user.username }}</strong>
<h5 class="media-heading">
<span class="username">#{{ post.user.username }}</span>
<time class="time">{{ post.created_at }}</time>
{% if post.group %}
<span class="group-name">in {{ post.group.name }}</span>
{% endif %}
</h5>
<div class="media-footer">
{% if user.is_authenticated and post.user == user and not hide_delete %}
<a href="{% url 'posts:delete' pk=post.pk %}" title="delete" class="btn btn-simple">
<span class="glyphicon glyphicon-remove text-danger" aria-hidden="true"></span>
<span class="text-danger icon-label">Delete</span>
</a>
{% endif %}
</div>
</div>
</div>
I have another application called 'questions' in my project, and it uses almost the phrases so maybe that's the problem, but I'm not sure.
The url name that you specify in the template file is 'for_user'. This does not match with the url name that is defined in the urls.py file (name='user_posts'). These two names have to be the same for django to be able to establish a match in the urlpatterns. Also the url patterns in your code is for django 1.11 or below.
However, if you are using django 2.0 or above, use one of these two urls below;
from django.urls import path, re_path
urlpatterns = [
re_path(r'^by/(?P<username>\w+)/$', views.UserPosts.as_view(), name='for_user'),
path('by/<slug:username>/', views.UserPosts.as_view(), name='for_user')
]