Add basic forum functions

This commit is contained in:
Nathan Chapman 2022-07-19 15:42:10 -06:00
parent dc1ffcad75
commit 70d6398863
12 changed files with 154 additions and 19 deletions

View File

@ -19,8 +19,11 @@ class Topic(models.Model):
""" """
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
def __str__(self):
return self.name
def get_absolute_url(self): def get_absolute_url(self):
return reverse('core:tag-detail', kwargs={'pk': self.pk}) return reverse('core:tag-detail', kwargs={'topic_pk': self.pk})
class Tag(models.Model): class Tag(models.Model):
@ -118,7 +121,10 @@ class Post(models.Model):
objects = PostManager() objects = PostManager()
def get_absolute_url(self): def get_absolute_url(self):
return reverse('core:post-detail', kwargs={'pk': self.pk}) return reverse('core:post-detail', kwargs={
'topic_pk': self.topic.pk,
'post_pk': self.pk
})
class Meta: class Meta:
ordering = ['-pub_date'] ordering = ['-pub_date']

View File

@ -0,0 +1,13 @@
{% extends 'base.html' %}
{% block content %}
<h1>Delete comments</h1>
<form method="POST" action="{% url 'core:comment-delete' comment.pk %}">
{% csrf_token %}
<p>Are you sure you want to delete "{{ comments }}"?</p>
{{ form.as_p }}
<p>
<input type="submit" value="Delete"> or <a href="{% url 'core:comment-detail' comment.pk %}">cancel</a>
</p>
</form>
{% endblock %}

View File

@ -0,0 +1,12 @@
{% extends 'base.html' %}
{% block content %}
<h1>+ New comments</h1>
<form method="POST" action="{% url 'core:comment-create' %}">
{% csrf_token %}
{{ form.as_p }}
<p>
<input type="submit" value="Create"> or <a href="{% url 'core:comment-list' %}">cancel</a>
</p>
</form>
{% endblock %}

View File

@ -0,0 +1,12 @@
{% load helpers %}
<figure class="comment">
<figcaption>
<span class="comment__author">{{ comment.author }}</span><br>
<time>{{ comment.created_at }}</time>
</figcaption>
<div>
{{ comment.content|markdown|safe }}
</div>
<div class="comment__options">&hellip;</div>
</figure>

View File

@ -0,0 +1,13 @@
{% extends 'base.html' %}
{% block content %}
<h1>Update comment</h1>
<p><a href="{% url 'core:commend-delete' comment.pk %}">Delete</a></p>
<form method="POST" action="{% url 'core:comment-update' comment.pk %}">
{% csrf_token %}
{{ form.as_p }}
<p>
<input type="submit" value="Save changes"> or <a href="{% url 'core:comment-detail' comment.pk %}">cancel</a>
</p>
</form>
{% endblock %}

View File

@ -0,0 +1,19 @@
{% extends 'base.html' %}
{% block content %}
<h1>Comments</h1>
<p>
<a href="{% url 'core:comment-create' %}">+ New comment</a>
</p>
<table>
<tbody>
{% for comment in comments_list %}
<tr>
<dt>{{ comment }}</dt>
</tr>
{% empty %}
<tr>No comments yet.</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}

View File

@ -2,11 +2,11 @@
{% block content %} {% block content %}
<h1>+ New Post</h1> <h1>+ New Post</h1>
<form method="POST" action="{% url 'post-create' %}" enctype="multipart/form-data"> <form method="POST" action="{% url 'core:post-create' topic.pk %}" enctype="multipart/form-data">
{% csrf_token %} {% csrf_token %}
{{ form.as_p }} {{ form.as_p }}
<p> <p>
<input type="submit" value="Create"> or <a href="{% url 'post-list' %}">cancel</a> <input type="submit" value="Create"> or <a href="{% url 'core:post-list' topic.pk %}">cancel</a>
</p> </p>
</form> </form>
{% endblock %} {% endblock %}

View File

@ -1,6 +1,11 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% load static %}
{% load helpers %} {% load helpers %}
{% block head %}
<script type="module" src="{% static 'scripts/comments.js' %}" defer></script>
{% endblock head %}
{% block content %} {% block content %}
<article class="post"> <article class="post">
<header> <header>
@ -9,12 +14,31 @@
</figure> </figure>
<h1>{{ post.title }}</h1> <h1>{{ post.title }}</h1>
<p> <p>
<a href="{% url 'post-update' post.pk %}">Edit</a> <a href="{% url 'core:post-update' post.topic.pk post.pk %}">Edit</a>
<a href="{% url 'post-delete' post.pk %}">Delete</a> <a href="{% url 'core:post-delete' post.topic.pk post.pk %}">Delete</a>
</p> </p>
</header> </header>
<section class="post__content"> <section class="post__content">
{{ post.content|markdown|safe }} {{ post.content|markdown|safe }}
</section> </section>
<section class="comments detail__comments">
<h2>Discussion</h2>
<div class="comments__list">
{% for comment in post.comments.all %}
{% include 'core/comment_detail.html' with comment=comment %}
<hr>
{% endfor %}
</div>
<div class="comments__form">
<h3>Add a comment</h3>
<form action="{% url 'core:comment-create' %}" method="POST">
{% csrf_token %}
{{ comment_create_form.as_p }}
<input class="action-button" type="submit" value="Post comment">
</form>
</div>
</section>
</article> </article>
{% endblock %} {% endblock %}

View File

@ -7,4 +7,13 @@
<a href="{% url 'core:topic-delete' topic.pk %}">Delete</a> <a href="{% url 'core:topic-delete' topic.pk %}">Delete</a>
</p> </p>
<p>{{ topic }}</p> <p>{{ topic }}</p>
<section>
<a href="{% url 'core:post-create' topic.pk %}">+ New post</a>
{% for post in topic.post_list.all %}
<h3><a href="{% url 'core:post-detail' topic.pk post.pk %}">{{ post.title }}</a></h3>
{% empty %}
<p>No posts</p>
{% endfor %}
</section>
{% endblock %} {% endblock %}

View File

@ -1,17 +1,22 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block content %} {% block content %}
<h1>Topics</h1> <article>
<a href="{% url 'core:topic-create' %}">+ New topic</a> <h1>Topics</h1>
<table> <a href="{% url 'core:topic-create' %}">+ New topic</a>
<tbody> <section>
{% for topic in topic_list %} {% for topic in topic_list %}
<tr> <h3><a href="{% url 'core:topic-detail' topic.pk %}">{{ topic.name }}</a></h3>
<dt>{{ topic }}</dt> <ul>
</tr> {% for post in topic.post_list.all %}
<li><a href="{% url 'core:post-detail' topic.pk post.pk %}">{{ post.title }}</a></li>
{% empty %}
<li>No posts yet</li>
{% endfor %}
</ul>
{% empty %} {% empty %}
<tr>No topics yet.</tr> <p>No topics yet.</p>
{% endfor %} {% endfor %}
</tbody> </section>
</table> </article>
{% endblock %} {% endblock %}

View File

@ -42,11 +42,11 @@ urlpatterns = [
name='topic-list' name='topic-list'
), ),
path( path(
'new/', 'topics/new/',
views.TopicCreateView.as_view(), views.TopicCreateView.as_view(),
name='topic-create' name='topic-create'
), ),
path('<int:pk>/', include([ path('topics/<int:topic_pk>/', include([
path( path(
'', '',
views.TopicDetailView.as_view(), views.TopicDetailView.as_view(),
@ -75,7 +75,7 @@ urlpatterns = [
views.PostCreateView.as_view(), views.PostCreateView.as_view(),
name='post-create' name='post-create'
), ),
path('<int:pk>/', include([ path('<int:post_pk>/', include([
path( path(
'', '',
views.PostDetailView.as_view(), views.PostDetailView.as_view(),

View File

@ -9,6 +9,7 @@ from django.views.generic.edit import (
from django.contrib import messages from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.messages.views import SuccessMessageMixin from django.contrib.messages.views import SuccessMessageMixin
from django.contrib.contenttypes.models import ContentType
from .models import Topic, Post, Comment from .models import Topic, Post, Comment
from .forms import PostForm, CommentCreateForm from .forms import PostForm, CommentCreateForm
@ -60,16 +61,19 @@ class TopicCreateView(SuccessMessageMixin, CreateView):
class TopicDetailView(DetailView): class TopicDetailView(DetailView):
model = Topic model = Topic
pk_url_kwarg = 'topic_pk'
class TopicUpdateView(SuccessMessageMixin, UpdateView): class TopicUpdateView(SuccessMessageMixin, UpdateView):
model = Topic model = Topic
pk_url_kwarg = 'topic_pk'
success_message = 'Topic saved.' success_message = 'Topic saved.'
fields = '__all__' fields = '__all__'
class TopicDeleteView(SuccessMessageMixin, DeleteView): class TopicDeleteView(SuccessMessageMixin, DeleteView):
model = Topic model = Topic
pk_url_kwarg = 'topic_pk'
success_message = 'Topic deleted.' success_message = 'Topic deleted.'
success_url = reverse_lazy('topic-list') success_url = reverse_lazy('topic-list')
@ -84,18 +88,36 @@ class PostCreateView(SuccessMessageMixin, CreateView):
template_name_suffix = '_create_form' template_name_suffix = '_create_form'
fields = '__all__' fields = '__all__'
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
context['topic'] = get_object_or_404(Topic, pk=self.kwargs['topic_pk'])
return context
class PostDetailView(DetailView): class PostDetailView(DetailView):
model = Post model = Post
pk_url_kwarg = 'post_pk'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
object_content_type = ContentType.objects.get_for_model(self.object).pk
context['comment_create_form'] = CommentCreateForm(initial={
'content_type': object_content_type,
'object_id': self.object.pk
})
return context
class PostUpdateView(SuccessMessageMixin, UpdateView): class PostUpdateView(SuccessMessageMixin, UpdateView):
model = Post model = Post
pk_url_kwarg = 'post_pk'
success_message = 'Post saved.' success_message = 'Post saved.'
fields = '__all__' fields = '__all__'
class PostDeleteView(SuccessMessageMixin, DeleteView): class PostDeleteView(SuccessMessageMixin, DeleteView):
model = Post model = Post
pk_url_kwarg = 'post_pk'
success_message = 'Post deleted.' success_message = 'Post deleted.'
success_url = reverse_lazy('article-list') success_url = reverse_lazy('article-list')