anan commited on
Commit
36f1030
·
1 Parent(s): 8288e80

add social page

Browse files
src/social/__init__.py ADDED
File without changes
src/social/admin.py ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ from django.contrib import admin
2
+ from .models import Post #, Comment
3
+
4
+ admin.site.register(Post)
5
+ # admin.site.register(Comment)
src/social/apps.py ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ from django.apps import AppConfig
2
+
3
+
4
+ class SocialConfig(AppConfig):
5
+ name = 'social'
src/social/forms.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from django import forms
2
+ from .models import Post, Comment
3
+
4
+
5
+ class PostForm(forms.ModelForm):
6
+ body = forms.CharField(
7
+ label='',
8
+ widget=forms.Textarea(
9
+ attrs={'rows': '3',
10
+ 'placeholder': 'Say Something...'}
11
+ ))
12
+
13
+ class Meta:
14
+ model = Post
15
+ fields = ['body']
16
+
17
+ class CommentForm(forms.ModelForm):
18
+ comment = forms.CharField(
19
+ label='',
20
+ widget=forms.Textarea(
21
+ attrs={'rows': '3',
22
+ 'placeholder': 'Say Something...'}
23
+ ))
24
+
25
+ class Meta:
26
+ model = Comment
27
+ fields = ['comment']
src/social/migrations/0001_initial.py ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Generated by Django 3.1.4 on 2020-12-20 00:03
2
+
3
+ from django.conf import settings
4
+ from django.db import migrations, models
5
+ import django.db.models.deletion
6
+ import django.utils.timezone
7
+
8
+
9
+ class Migration(migrations.Migration):
10
+
11
+ initial = True
12
+
13
+ dependencies = [
14
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
15
+ ]
16
+
17
+ operations = [
18
+ migrations.CreateModel(
19
+ name='Post',
20
+ fields=[
21
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
22
+ ('body', models.TextField()),
23
+ ('created_on', models.DateTimeField(default=django.utils.timezone.now)),
24
+ ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
25
+ ],
26
+ ),
27
+ migrations.CreateModel(
28
+ name='Comment',
29
+ fields=[
30
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
31
+ ('comment', models.TextField()),
32
+ ('created_on', models.DateTimeField(default=django.utils.timezone.now)),
33
+ ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
34
+ ('post', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='social.post')),
35
+ ],
36
+ ),
37
+ ]
src/social/migrations/__init__.py ADDED
File without changes
src/social/models.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from django.db import models
2
+ from django.utils import timezone
3
+ from django.contrib.auth.models import User
4
+
5
+
6
+ class Post(models.Model):
7
+ body = models.TextField()
8
+ created_on = models.DateTimeField(default=timezone.now)
9
+ author = models.ForeignKey(User, on_delete=models.CASCADE)
10
+
11
+
12
+ class Comment(models.Model):
13
+ comment = models.TextField()
14
+ created_on = models.DateTimeField(default=timezone.now)
15
+ post = models.ForeignKey('Post', on_delete=models.CASCADE)
16
+ author = models.ForeignKey(User, on_delete=models.CASCADE)
src/social/templates/social/comment_delete.html ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends 'landing/base.html' %}
2
+ {% load crispy_forms_tags %}
3
+
4
+ {% block content %}
5
+ <div class="container">
6
+ <div class="row mt-5">
7
+ <div class="col-md-3 col-sm-6">
8
+ <a href="{% url 'post-detail' object.post.pk %}" class="btn btn-light">Back to Feed</a>
9
+ </div>
10
+ </div>
11
+ <div class="row justify-content-center mt-5">
12
+ <div class="col-md-5 col-sm-12">
13
+ <h5>Are You Sure?</h5>
14
+ <p>You are about to delete this comment, this cannot be undone.</p>
15
+ <form method="POST">
16
+ {% csrf_token %}
17
+ <div class="d-grid gap-2">
18
+ <button type="submit" class="btn btn-danger">Delete</button>
19
+ </div>
20
+ </form>
21
+ </div>
22
+ </div>
23
+ </div>
24
+ {% endblock content %}
src/social/templates/social/post_delete.html ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends 'landing/base.html' %}
2
+ {% load crispy_forms_tags %}
3
+
4
+ {% block content %}
5
+ <div class="container">
6
+ <div class="row mt-5">
7
+ <div class="col-md-3 col-sm-6">
8
+ <a href="{% url 'post-detail' object.pk %}" class="btn btn-light">Back to Feed</a>
9
+ </div>
10
+ </div>
11
+ <div class="row justify-content-center mt-5">
12
+ <div class="col-md-5 col-sm-12">
13
+ <h5>Are You Sure?</h5>
14
+ <p>You are about to delete this post, this cannot be undone.</p>
15
+ <form method="POST">
16
+ {% csrf_token %}
17
+ <div class="d-grid gap-2">
18
+ <button type="submit" class="btn btn-danger">Delete</button>
19
+ </div>
20
+ </form>
21
+ </div>
22
+ </div>
23
+ </div>
24
+ {% endblock content %}
src/social/templates/social/post_detail.html ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends 'landing/base.html' %}
2
+ {% load crispy_forms_tags %}
3
+
4
+ {% block content %}
5
+ <div class="container">
6
+ <div class="row mt-5">
7
+ <div class="col-md-3 col-sm-6">
8
+ <a href="{% url 'post-list' %}" class="btn btn-light">Back to Feed</a>
9
+ </div>
10
+ </div>
11
+ <div class="row justify-content-center mt-3">
12
+ <div class="col-md-5 col-sm-12 border-bottom">
13
+ <p>
14
+ <strong>{{ post.author }}</strong> {{ post.created_on }}
15
+ {% if request.user == post.author %}
16
+ <a href="{% url 'post-edit' post.pk %}" style="color: #333;"><i class="far fa-edit"></i></a>
17
+ <a href="{% url 'post-delete' post.pk %}" style="color: #333;"><i class="fas fa-trash"></i></a>
18
+ {% endif %}
19
+ </p>
20
+ <p>{{ post.body }}</p>
21
+ </div>
22
+ </div>
23
+
24
+ <div class="row justify-content-center mt-3">
25
+ <div class="col-md-5 col-sm-12">
26
+ <h5>Add a Comment!</h5>
27
+ </div>
28
+ </div>
29
+ <div class="row justify-content-center mt-3 mb-5">
30
+ <div class="col-md-5 col-sm-12">
31
+ <form method="POST">
32
+ {% csrf_token %}
33
+ {{ form | crispy }}
34
+ <div class="d-grid gap-2">
35
+ <button class="btn btn-success mt-3">Submit!</button>
36
+ </div>
37
+ </form>
38
+ </div>
39
+ </div>
40
+ {% for comment in comments %}
41
+ <div class="row justify-content-center mt-3 mb-5 border-bottom">
42
+ <div class="col-md-5 col-sm-12">
43
+ <p>
44
+ <strong>{{ comment.author }}</strong> {{ comment.created_on }}
45
+ {% if request.user == comment.author %}
46
+ <a href="{% url 'comment-delete' post.pk comment.pk %}" style="color: #333;"><i class="fas fa-trash"></i></a>
47
+ {% endif %}
48
+ </p>
49
+ <p>{{ comment.comment }}</p>
50
+ </div>
51
+ </div>
52
+ {% endfor %}
53
+ </div>
54
+ {% endblock content %}
src/social/templates/social/post_edit.html ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends 'landing/base.html' %}
2
+ {% load crispy_forms_tags %}
3
+
4
+ {% block content %}
5
+ <div class="container">
6
+ <div class="row mt-5">
7
+ <div class="col-md-3 col-sm-6">
8
+ <a href="{% url 'post-detail' object.pk %}" class="btn btn-light">Back to Feed</a>
9
+ </div>
10
+ </div>
11
+ <div class="row justify-content-center mt-5">
12
+ <div class="col-md-5 col-sm-12">
13
+ <h5>Update Your Post</h5>
14
+ </div>
15
+ </div>
16
+ <div class="row justify-content-center mt-3 mb-5">
17
+ <div class="col-md-5 col-sm-12">
18
+ <form method="POST">
19
+ {% csrf_token %}
20
+ {{ form | crispy }}
21
+ <div class="d-grid gap-2">
22
+ <button class="btn btn-success mt-3">Submit!</button>
23
+ </div>
24
+ </form>
25
+ </div>
26
+ </div>
27
+ </div>
28
+ {% endblock content %}
src/social/templates/social/post_list.html ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends 'landing/base.html' %}
2
+ {% load crispy_forms_tags %}
3
+
4
+ {% block content %}
5
+ <div class="container">
6
+ <div class="row justify-content-center mt-3">
7
+ <div class="col-md-5 col-sm-12">
8
+ <h5>Add a Post!</h5>
9
+ </div>
10
+ </div>
11
+ <div class="row justify-content-center mt-3 mb-5">
12
+ <div class="col-md-5 col-sm-12">
13
+ <form method="POST">
14
+ {% csrf_token %}
15
+ {{ form | crispy }}
16
+ <div class="d-grid gap-2">
17
+ <button class="btn btn-success mt-3">Submit!</button>
18
+ </div>
19
+ </form>
20
+ </div>
21
+ </div>
22
+ {% for post in post_list %}
23
+ <div class="row justify-content-center mt-3">
24
+ <div class="col-md-5 col-sm-12 border-bottom position-relative">
25
+ <p><strong>{{ post.author }}</strong> {{ post.created_on }}</p>
26
+ <p>{{ post.body }}</p>
27
+ <a class="stretched-link" href="{% url 'post-detail' post.pk %}"></a>
28
+ </div>
29
+ </div>
30
+ {% endfor %}
31
+ </div>
32
+ {% endblock content %}
src/social/tests.py ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ from django.test import TestCase
2
+
3
+ # Create your tests here.
src/social/urls.py ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ from django.urls import path
2
+ from .views import PostListView, PostDetailView, PostEditView, PostDeleteView, CommentDeleteView
3
+
4
+ urlpatterns = [
5
+ path('', PostListView.as_view(), name='post-list'),
6
+ path('post/<int:pk>/', PostDetailView.as_view(), name='post-detail'),
7
+ path('post/edit/<int:pk>/', PostEditView.as_view(), name='post-edit'),
8
+ path('post/delete/<int:pk>/', PostDeleteView.as_view(), name='post-delete'),
9
+ path('post/<int:post_pk>/comment/delete/<int:pk>/', CommentDeleteView.as_view(), name='comment-delete'),
10
+ ]
src/social/views.py ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from django.shortcuts import render
2
+ from django.urls import reverse_lazy
3
+ from django.contrib.auth.mixins import UserPassesTestMixin, LoginRequiredMixin
4
+ from django.views import View
5
+ from django.views.generic.edit import UpdateView, DeleteView
6
+ from .models import Post, Comment
7
+ from .forms import PostForm, CommentForm
8
+
9
+
10
+ class PostListView(LoginRequiredMixin, View):
11
+ def get(self, request, *args, **kwargs):
12
+ posts = Post.objects.all().order_by('-created_on')
13
+ form = PostForm()
14
+
15
+ context = {
16
+ 'post_list': posts,
17
+ 'form': form,
18
+ }
19
+ return render(request, 'social/post_list.html', context)
20
+
21
+ def post(self, request, *args, **kwargs):
22
+ posts = Post.objects.all().order_by('-created_on')
23
+ form = PostForm(request.POST)
24
+
25
+ if form.is_valid():
26
+ new_post = form.save(commit=False)
27
+ new_post.author = request.user
28
+ new_post.save()
29
+
30
+ context = {
31
+ 'post_list': posts,
32
+ 'form': form,
33
+ }
34
+ return render(request, 'social/post_list.html', context)
35
+
36
+ class PostDetailView(LoginRequiredMixin, View):
37
+ def get(self, request, pk, *args, **kwargs):
38
+ post = Post.objects.get(pk=pk)
39
+ form = CommentForm()
40
+ comments = Comment.objects.filter(post=post).order_by('-created_on')
41
+
42
+ context = {
43
+ 'post': post,
44
+ 'form': form,
45
+ 'comments': comments,
46
+ }
47
+
48
+ return render(request, 'social/post_detail.html', context)
49
+
50
+ def post(self, request, pk, *args, **kwargs):
51
+ post = Post.objects.get(pk=pk)
52
+ form = CommentForm(request.POST)
53
+
54
+ if form.is_valid():
55
+ new_comment = form.save(commit=False)
56
+ new_comment.author = request.user
57
+ new_comment.post = post
58
+ new_comment.save()
59
+
60
+ comments = Comment.objects.filter(post=post).order_by('-created_on')
61
+
62
+ context = {
63
+ 'post': post,
64
+ 'form': form,
65
+ 'comments': comments,
66
+ }
67
+
68
+ return render(request, 'social/post_detail.html', context)
69
+
70
+ class PostEditView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
71
+ model = Post
72
+ fields = ['body']
73
+ template_name = 'social/post_edit.html'
74
+
75
+ def get_success_url(self):
76
+ pk = self.kwargs['pk']
77
+ return reverse_lazy('post-detail', kwargs={'pk': pk})
78
+
79
+ def test_func(self):
80
+ post = self.get_object()
81
+ return self.request.user == post.author
82
+
83
+ class PostDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
84
+ model = Post
85
+ template_name = 'social/post_delete.html'
86
+ success_url = reverse_lazy('post-list')
87
+
88
+ def test_func(self):
89
+ post = self.get_object()
90
+ return self.request.user == post.author
91
+
92
+ class CommentDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
93
+ model = Comment
94
+ template_name = 'social/comment_delete.html'
95
+
96
+ def get_success_url(self):
97
+ pk = self.kwargs['post_pk']
98
+ return reverse_lazy('post-detail', kwargs={'pk': pk})
99
+
100
+ def test_func(self):
101
+ comment = self.get_object()
102
+ return self.request.user == comment.author