Add post and comment creation functionality

This commit is contained in:
Piotr Szkudlarek 2024-01-06 14:14:15 +01:00
parent c6ba3dd6b0
commit d23cdff3af
19 changed files with 235 additions and 36 deletions

View File

@ -0,0 +1,18 @@
from django import forms
from .models import Post, Comment
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ["title", "content"]
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ["content"]
labels = {
"content": "Comment",
}
widgets = {"content": forms.Textarea(attrs={"rows": 3})}

View File

@ -0,0 +1,21 @@
# Generated by Django 4.2.7 on 2024-01-05 19:44
from django.db import migrations, models
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
("Community", "0002_post_date_pub"),
]
operations = [
migrations.AddField(
model_name="comment",
name="date_added",
field=models.DateField(
auto_now_add=True, default=django.utils.timezone.now
),
preserve_default=False,
),
]

View File

@ -10,8 +10,13 @@ class Post(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE, null=False) author = models.ForeignKey(User, on_delete=models.CASCADE, null=False)
date_pub = models.DateField(auto_now_add=True) date_pub = models.DateField(auto_now_add=True)
@property
def sorted_comments(self):
return self.comment_set.all().order_by("-date_added")
class Comment(models.Model): class Comment(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE, null=False) author = models.ForeignKey(User, on_delete=models.CASCADE, null=False)
content = models.TextField() content = models.TextField()
post = models.ForeignKey(Post, on_delete=models.CASCADE) post = models.ForeignKey(Post, on_delete=models.CASCADE)
date_added = models.DateField(auto_now_add=True)

View File

@ -6,4 +6,5 @@ from . import views
urlpatterns = [ urlpatterns = [
path("posts/", views.ListPosts.as_view(), name="posts"), path("posts/", views.ListPosts.as_view(), name="posts"),
path("posts/<int:pk>", views.PostDetails.as_view(), name="post-details"), path("posts/<int:pk>", views.PostDetails.as_view(), name="post-details"),
path("posts/create/", views.AddPost.as_view(), name="add_post"),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

View File

@ -1,6 +1,12 @@
from django.shortcuts import render from typing import Any
from django.db.models.query import QuerySet
from django.http import HttpResponse
from django.shortcuts import redirect, render
from django.views.generic import ListView, DetailView from django.views.generic import ListView, DetailView
from django.views.generic.edit import FormView, FormMixin
from .models import Post, Comment from .models import Post, Comment
from .froms import PostForm, CommentForm
# Create your views here. # Create your views here.
@ -8,8 +14,44 @@ from .models import Post, Comment
class ListPosts(ListView): class ListPosts(ListView):
model = Post model = Post
template_name = "list_posts.html" template_name = "list_posts.html"
paginate_by = 3
def get_queryset(self) -> QuerySet[Any]:
queryset = Post.objects.all().order_by("-date_pub")
return queryset
class PostDetails(DetailView): class PostDetails(DetailView, FormMixin):
model = Post model = Post
template_name = "post_details.html" template_name = "post_details.html"
form_class = CommentForm
# def get_queryset(self) -> QuerySet[Any]:
# queryset = Post.objects.get(pk=self.request.GET.get("pk"))
def post(self, request, *args, **kwargs):
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) -> HttpResponse:
post = self.get_object()
new_comment = form.save(commit=False)
new_comment.author = self.request.user
new_comment.post = post
new_comment.save()
return redirect("post-details", pk=post.id)
class AddPost(FormView):
template_name = "add_post.html"
form_class = PostForm
def form_valid(self, form) -> HttpResponse:
new_post = form.save(commit=False)
new_post.author = self.request.user
new_post.save()
return redirect("post-details", pk=new_post.id)

View File

@ -10,5 +10,5 @@ urlpatterns = [
path( path(
"detection/<int:pk>", views.DetectionDetails.as_view(), name="detection-details" "detection/<int:pk>", views.DetectionDetails.as_view(), name="detection-details"
), ),
path("export_pred/<int:pk>", views.download_pred_res, name="download_predicitons"), path("export_pred/<int:pk>", views.download_pred_res, name="download_predicitions"),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

View File

@ -1,8 +1,10 @@
from django.shortcuts import render, redirect from django.shortcuts import render, redirect
from django.contrib.auth.forms import AuthenticationForm, UserCreationForm from django.contrib.auth.forms import AuthenticationForm, UserCreationForm
from django.contrib.auth import authenticate, login, logout from django.contrib.auth import authenticate, login, logout
from django.urls import reverse_lazy
from django.views import View from django.views import View
class LoginView(View): class LoginView(View):
form_class = AuthenticationForm form_class = AuthenticationForm
template_name = "login_signup.html" template_name = "login_signup.html"
@ -12,6 +14,7 @@ class LoginView(View):
return render(request, self.template_name, {"form": form}) return render(request, self.template_name, {"form": form})
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
redirection_path = request.GET.get("next")
form = self.form_class(data=request.POST) form = self.form_class(data=request.POST)
if form.is_valid(): if form.is_valid():
user = authenticate( user = authenticate(
@ -20,7 +23,10 @@ class LoginView(View):
) )
if user is not None: if user is not None:
login(request, user) login(request, user)
return redirect("detect") if redirection_path is not None:
return redirect(redirection_path)
else:
return redirect("detect/")
return render(request, self.template_name, {"form": form}) return render(request, self.template_name, {"form": form})
@ -37,10 +43,14 @@ class SignupView(View):
if form.is_valid(): if form.is_valid():
user = form.save() user = form.save()
login(request, user) login(request, user)
return redirect("detect") return redirect("detect/")
return render(request, self.template_name, {"form": form, "signup": True}) return render(request, self.template_name, {"form": form, "signup": True})
def logout_view(request): def logout_view(request):
redirection_path = request.GET.get("next")
logout(request) logout(request)
return redirect("detect") if redirection_path is not None:
return redirect(redirection_path)
else:
return redirect("detect/")

Binary file not shown.

View File

@ -27,6 +27,7 @@ ul{
align-items: flex-start; align-items: flex-start;
justify-content: space-between; justify-content: space-between;
margin-bottom: 25px; margin-bottom: 25px;
box-shadow: 0 2px lightgray;
} }
.date_author{ .date_author{
@ -36,3 +37,15 @@ ul{
align-items: flex-start; align-items: flex-start;
justify-content: space-between; justify-content: space-between;
} }
#add_post{
text-align: center;
padding: 1px 6px 1px 6px;
width: 10%;
background-color: chartreuse;
border-radius: 25px;
border: 2px black;
box-shadow: 0 0 0 2px black;
font-size: 20px;
font-family: Arial;
}

View File

@ -77,9 +77,46 @@ body, html{
margin-top:10px; margin-top:10px;
} }
#comment-author{ #add_comment{
display: flex; display: flex;
width: 100%; flex-direction: row;
justify-content: flex-end; width: 55%;
justify-content: space-evenly;
align-items: center;
margin-top:30px;
} }
#comment_form{
width: 100%;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
#comment_form textarea{
height: auto;
}
#comment_form label{
font-size: 20px;
}
.date_author{
display: flex;
width: 100%;
flex-direction: row;
align-items: flex-start;
justify-content: space-between;
}
#submit{
background-color: chartreuse;
border-radius: 25px;
border: 2px solid black;
font-size: 20px;
text-decoration: none;
color:black;
font-family: Arial;
text-align: center;
}

View File

@ -29,17 +29,6 @@ form{
margin: 10px 0px 15px 0px; margin: 10px 0px 15px 0px;
} }
#submit{
background-color: chartreuse;
margin-top: auto;
height: 50px;
width: 80%;
border-radius: 25px;
border: 2px white;
box-shadow: 0 0 0 4px white;
font-size: 25px;
}
.upload_field { .upload_field {
margin: auto; margin: auto;
display: flex; display: flex;
@ -91,7 +80,26 @@ form{
height: 50px; height: 50px;
width: 60%; width: 60%;
border-radius: 25px; border-radius: 25px;
border: 2px white; border: 2px solid black;
box-shadow: 0 0 0 4px white;
font-size: 25px; font-size: 25px;
text-decoration: none;
color:black;
font-family: Arial;
text-align: center;
line-height:45px;
}
#submit{
background-color: chartreuse;
margin-top: auto;
height: 50px;
width: 80%;
border-radius: 25px;
border: 2px solid white;
font-size: 25px;
text-decoration: none;
color:black;
font-family: Arial;
text-align: center;
line-height:45px;
} }

View File

@ -34,9 +34,13 @@ form{
height: 50px; height: 50px;
width: 80%; width: 80%;
border-radius: 25px; border-radius: 25px;
border: 2px white; border: 2px solid white;
box-shadow: 0 0 0 4px white;
font-size: 25px; font-size: 25px;
text-decoration: none;
color:black;
font-family: Arial;
text-align: center;
line-height:45px;
} }
.upload_field { .upload_field {

View File

@ -0,0 +1,12 @@
{%extends 'base.html'%}
{%load static%}
{%block extracss%}
<link rel="stylesheet" href="{% static 'Community/css/add_post.css' %}">
{%endblock extracss%}
{%block content%}
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Add post">
</form>
{%endblock content%}

View File

@ -18,9 +18,9 @@
<a href="{% url 'detect' %}">Predict</a> <a href="{% url 'detect' %}">Predict</a>
{% if user.is_authenticated %} {% if user.is_authenticated %}
<a href="{% url 'history' %}">History</a> <a href="{% url 'history' %}">History</a>
<a href="{% url 'logout' %}">Logout {{user}}</a> <a href="{% url 'logout' %}?next={{request.path}}">Logout {{user}}</a>
{%else%} {%else%}
<a href="{% url 'login' %}">Login</a> <a href="{% url 'login' %}?next={{request.path}}">Login</a>
{%endif%} {%endif%}
</div> </div>
{%block content%}{%endblock content%} {%block content%}{%endblock content%}

View File

@ -6,7 +6,10 @@
{%block content%} {%block content%}
<div class="post_list"> <div class="post_list">
<h2>Posts</h2> <h2>Posts</h2>
{% for post in object_list %} {% if user.is_authenticated %}
<a href="{%url 'add_post'%}" id="add_post">Add new post</a>
{%endif%}
{% for post in page_obj %}
<div class="post_details"> <div class="post_details">
<a href="{%url 'post-details' pk=post.id %}"> <a href="{%url 'post-details' pk=post.id %}">
<h3 class="title">{{ post.title }}</h3> <h3 class="title">{{ post.title }}</h3>
@ -17,5 +20,22 @@
</a> </a>
</div> </div>
{% endfor %} {% endfor %}
<div class="pagination">
<span class="step-links">
{% if page_obj.has_previous %}
<a href="?page=1">&laquo; first</a>
<a href="?page={{ page_obj.previous_page_number }}">previous</a>
{% endif %}
<span class="current">
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
</span>
{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}">next</a>
<a href="?page={{ page_obj.paginator.num_pages }}">last &raquo;</a>
{% endif %}
</span>
</div>
</div> </div>
{%endblock content%} {%endblock content%}

View File

@ -14,12 +14,22 @@
<p id="author">{{object.author}}</p> <p id="author">{{object.author}}</p>
</div> </div>
</div> </div>
<div id="add_comment">
<form method="POST" id="comment_form">
{%csrf_token%}
{{form}}
<input type="submit" id="submit" value="Add comment">
</form>
</div>
<p id="comment-label">Comments:</p> <p id="comment-label">Comments:</p>
<div class="comments"> <div class="comments">
{%for comments in object.comment_set.all%} {%for comment in object.sorted_comments%}
<div class="single-comment"> <div class="single-comment">
<p id="comment-content">{{comments.content}}</p> <p id="comment-content">{{comment.content}}</p>
<p id="comment-author">{{comments.author}}</p> <div class="date_author">
<p id="comment-date">{{comment.date_added}}</p>
<p id="comment-author">{{comment.author}}</p>
</div>
</div> </div>
{%endfor%} {%endfor%}
</div> </div>

View File

@ -9,7 +9,7 @@
<div class="side_menu"> <div class="side_menu">
{% if not user.is_authenticated %} {% if not user.is_authenticated %}
<p id="description">Please login to see results</p> <p id="description">Please login to see results</p>
<button onclick="location.href='{% url 'login' %}'" id='submit' method="GET" type='button'>Login</button> <a href="{% url 'login'%}?next={{request.path}}" id="submit">Login</a>
{% else %} {% else %}
<p id="description">Results:</p> <p id="description">Results:</p>
{%for img in img.images.all %} {%for img in img.images.all %}
@ -20,7 +20,7 @@
</div> </div>
{%endfor%} {%endfor%}
{%endfor%} {%endfor%}
<button onclick="location.href='{% url 'detect' %}'" id='submit' method="GET" type='button'>Submit again</button> <a href="{% url 'detect' %}" id="submit">Submit again</a>
{%endif%} {%endif%}
</div> </div>
<div class="upload_field"> <div class="upload_field">
@ -29,7 +29,7 @@
<img src="{{img.image.url}}" alt="upload_image" style="width:640px; height:460px;"> <img src="{{img.image.url}}" alt="upload_image" style="width:640px; height:460px;">
{%endfor%} {%endfor%}
</label> </label>
<button onclick="location.href='{%url 'download_predicitons' pk=img.id%}'" id="download_json" method="GET" type="button">Export predictions</button> <a href="{%url 'download_predicitions' pk=img.id %}" id="download_json">Export predictions</a>
</div> </div>
</form> </form>
<script> <script>

View File

@ -9,7 +9,7 @@
<div class="side_menu"> <div class="side_menu">
{% if not user.is_authenticated %} {% if not user.is_authenticated %}
<p id="description">Please login to submit image</p> <p id="description">Please login to submit image</p>
<button onclick="location.href='{% url 'login' %}'" id='submit' method="GET" type='button'>Login</button> <a href="{% url 'login' %}?next={{request.path}}" id="submit">Login</a>
{% else %} {% else %}
<p id="description">Choose image for analysis</p> <p id="description">Choose image for analysis</p>
<input type="submit" id="submit" value="Submit"> <input type="submit" id="submit" value="Submit">
@ -71,10 +71,8 @@ document.getElementById('id_image').addEventListener('change', function () {
var user = `{{user.is_authenticated}}` var user = `{{user.is_authenticated}}`
var upload = document.getElementById("id_image") var upload = document.getElementById("id_image")
if (user.toLowerCase()=="false"){ if (user.toLowerCase()=="false"){
console.log('disabled');
upload.disabled=true; upload.disabled=true;
}else if (user.toLowerCase()=="true"){ }else if (user.toLowerCase()=="true"){
console.log("enabled");
upload.disabled=false; upload.disabled=false;
} }
</script> </script>