Kaynağa Gözat

完成了回到顶部按钮,粘性目录,底部页脚的美化,等,并且完成了多级评论功能,删除了数据库等数据

Shellmiao 4 yıl önce
ebeveyn
işleme
674e4274e7
31 değiştirilmiş dosya ile 368 ekleme ve 292 silme
  1. 2 1
      MyBlog/MyBlog/settings.py
  2. 0 32
      MyBlog/article/migrations/0001_initial.py
  3. 0 18
      MyBlog/article/migrations/0002_articlepost_total_views.py
  4. 0 28
      MyBlog/article/migrations/0003_auto_20210128_1001.py
  5. 0 20
      MyBlog/article/migrations/0004_articlecolumn_tags.py
  6. 0 20
      MyBlog/article/migrations/0005_articlepost_tags.py
  7. 0 17
      MyBlog/article/migrations/0006_remove_articlecolumn_tags.py
  8. 0 18
      MyBlog/article/migrations/0007_articlepost_avatar.py
  9. 0 0
      MyBlog/article/migrations/__init__.py
  10. 0 34
      MyBlog/comment/migrations/0001_initial.py
  11. 0 20
      MyBlog/comment/migrations/0002_auto_20210126_2310.py
  12. 0 19
      MyBlog/comment/migrations/0003_auto_20210130_1958.py
  13. 0 0
      MyBlog/comment/migrations/__init__.py
  14. 23 3
      MyBlog/comment/models.py
  15. 1 0
      MyBlog/comment/urls.py
  16. 20 2
      MyBlog/comment/views.py
  17. BIN
      MyBlog/db.sqlite3
  18. BIN
      MyBlog/media/article/20210129/541332.jpg
  19. BIN
      MyBlog/media/article/20210130/1030509.jpg
  20. BIN
      MyBlog/media/article/20210130/923425.jpg
  21. BIN
      MyBlog/media/avatar/20210123/157767.jpg
  22. 38 0
      MyBlog/static/csrf.js
  23. 7 0
      MyBlog/static/sticky_sidebar/jquery.sticky-sidebar.min.js
  24. 124 23
      MyBlog/templates/article/detail.html
  25. 9 6
      MyBlog/templates/article/list.html
  26. 61 0
      MyBlog/templates/back_to_top_func.html
  27. 27 3
      MyBlog/templates/base.html
  28. 55 0
      MyBlog/templates/comment/reply.html
  29. 1 1
      MyBlog/templates/footer.html
  30. 0 27
      MyBlog/userprofile/migrations/0001_initial.py
  31. 0 0
      MyBlog/userprofile/migrations/__init__.py

+ 2 - 1
MyBlog/MyBlog/settings.py

@@ -41,8 +41,9 @@ INSTALLED_APPS = [
     'comment',
     'taggit',
     'ckeditor',
+    'mptt',
 ]
-
+X_FRAME_OPTIONS = 'SAMEORIGIN'
 MIDDLEWARE = [
     'django.middleware.security.SecurityMiddleware',
     'django.contrib.sessions.middleware.SessionMiddleware',

+ 0 - 32
MyBlog/article/migrations/0001_initial.py

@@ -1,32 +0,0 @@
-# Generated by Django 3.1.1 on 2021-01-21 14:36
-
-from django.conf import settings
-from django.db import migrations, models
-import django.db.models.deletion
-import django.utils.timezone
-
-
-class Migration(migrations.Migration):
-
-    initial = True
-
-    dependencies = [
-        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
-    ]
-
-    operations = [
-        migrations.CreateModel(
-            name='ArticlePost',
-            fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('title', models.CharField(max_length=100)),
-                ('body', models.TextField()),
-                ('created', models.DateTimeField(default=django.utils.timezone.now)),
-                ('updated', models.DateTimeField(default=django.utils.timezone.now)),
-                ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
-            ],
-            options={
-                'ordering': ('-created',),
-            },
-        ),
-    ]

+ 0 - 18
MyBlog/article/migrations/0002_articlepost_total_views.py

@@ -1,18 +0,0 @@
-# Generated by Django 3.1.1 on 2021-01-23 10:37
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('article', '0001_initial'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='articlepost',
-            name='total_views',
-            field=models.PositiveIntegerField(default=0),
-        ),
-    ]

+ 0 - 28
MyBlog/article/migrations/0003_auto_20210128_1001.py

@@ -1,28 +0,0 @@
-# Generated by Django 3.1.1 on 2021-01-28 02:01
-
-from django.db import migrations, models
-import django.db.models.deletion
-import django.utils.timezone
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('article', '0002_articlepost_total_views'),
-    ]
-
-    operations = [
-        migrations.CreateModel(
-            name='ArticleColumn',
-            fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('title', models.CharField(blank=True, max_length=100)),
-                ('created', models.DateTimeField(default=django.utils.timezone.now)),
-            ],
-        ),
-        migrations.AddField(
-            model_name='articlepost',
-            name='column',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='article', to='article.articlecolumn'),
-        ),
-    ]

+ 0 - 20
MyBlog/article/migrations/0004_articlecolumn_tags.py

@@ -1,20 +0,0 @@
-# Generated by Django 3.1.1 on 2021-01-28 03:55
-
-from django.db import migrations
-import taggit.managers
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('taggit', '0003_taggeditem_add_unique_index'),
-        ('article', '0003_auto_20210128_1001'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='articlecolumn',
-            name='tags',
-            field=taggit.managers.TaggableManager(blank=True, help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags'),
-        ),
-    ]

+ 0 - 20
MyBlog/article/migrations/0005_articlepost_tags.py

@@ -1,20 +0,0 @@
-# Generated by Django 3.1.1 on 2021-01-28 07:42
-
-from django.db import migrations
-import taggit.managers
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('taggit', '0003_taggeditem_add_unique_index'),
-        ('article', '0004_articlecolumn_tags'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='articlepost',
-            name='tags',
-            field=taggit.managers.TaggableManager(blank=True, help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags'),
-        ),
-    ]

+ 0 - 17
MyBlog/article/migrations/0006_remove_articlecolumn_tags.py

@@ -1,17 +0,0 @@
-# Generated by Django 3.1.1 on 2021-01-28 10:31
-
-from django.db import migrations
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('article', '0005_articlepost_tags'),
-    ]
-
-    operations = [
-        migrations.RemoveField(
-            model_name='articlecolumn',
-            name='tags',
-        ),
-    ]

+ 0 - 18
MyBlog/article/migrations/0007_articlepost_avatar.py

@@ -1,18 +0,0 @@
-# Generated by Django 3.1.1 on 2021-01-28 12:02
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('article', '0006_remove_articlecolumn_tags'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='articlepost',
-            name='avatar',
-            field=models.ImageField(blank=True, upload_to='article/%Y%m%d/'),
-        ),
-    ]

+ 0 - 0
MyBlog/article/migrations/__init__.py


+ 0 - 34
MyBlog/comment/migrations/0001_initial.py

@@ -1,34 +0,0 @@
-# Generated by Django 3.1.1 on 2021-01-26 09:45
-
-from django.conf import settings
-from django.db import migrations, models
-import django.db.models.deletion
-import django.utils.timezone
-
-
-class Migration(migrations.Migration):
-
-    initial = True
-
-    dependencies = [
-        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
-        ('article', '0002_articlepost_total_views'),
-    ]
-
-    operations = [
-        migrations.CreateModel(
-            name='CommentPost',
-            fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('body', models.TextField()),
-                ('created', models.DateTimeField(default=django.utils.timezone.now)),
-                ('updated', models.DateTimeField(default=django.utils.timezone.now)),
-                ('total_views', models.PositiveIntegerField(default=0)),
-                ('article', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='comment', to='article.articlepost')),
-                ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='comment', to=settings.AUTH_USER_MODEL)),
-            ],
-            options={
-                'ordering': ('-created',),
-            },
-        ),
-    ]

+ 0 - 20
MyBlog/comment/migrations/0002_auto_20210126_2310.py

@@ -1,20 +0,0 @@
-# Generated by Django 3.1.1 on 2021-01-26 15:10
-
-from django.conf import settings
-from django.db import migrations
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
-        ('article', '0002_articlepost_total_views'),
-        ('comment', '0001_initial'),
-    ]
-
-    operations = [
-        migrations.RenameModel(
-            old_name='CommentPost',
-            new_name='Comment',
-        ),
-    ]

+ 0 - 19
MyBlog/comment/migrations/0003_auto_20210130_1958.py

@@ -1,19 +0,0 @@
-# Generated by Django 3.1.1 on 2021-01-30 11:58
-
-import ckeditor.fields
-from django.db import migrations
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('comment', '0002_auto_20210126_2310'),
-    ]
-
-    operations = [
-        migrations.AlterField(
-            model_name='comment',
-            name='body',
-            field=ckeditor.fields.RichTextField(),
-        ),
-    ]

+ 0 - 0
MyBlog/comment/migrations/__init__.py


+ 23 - 3
MyBlog/comment/models.py

@@ -4,18 +4,38 @@ from django.utils import timezone
 
 from article.models import ArticlePost
 from ckeditor.fields import RichTextField
+from mptt.models import MPTTModel, TreeForeignKey
 
 
-class Comment(models.Model):
+class Comment(MPTTModel):
     user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='comment')
     article = models.ForeignKey(ArticlePost, on_delete=models.CASCADE, related_name='comment')
     body = RichTextField()
     created = models.DateTimeField(default=timezone.now)  # 使用timezone.now()时 进行数据迁移会,有警告
     updated = models.DateTimeField(default=timezone.now)
     total_views = models.PositiveIntegerField(default=0)
+    # mptt树形结构
+    parent = TreeForeignKey(
+        'self',
+        on_delete=models.CASCADE,
+        null=True,
+        blank=True,
+        related_name='children'
+    )
+    # 记录二级评论回复给谁,str
+    reply_to = models.ForeignKey(
+        User,
+        null=True,
+        blank=True,
+        on_delete=models.CASCADE,
+        related_name='replyers'
+    )
 
-    class Meta:
-        ordering = ('-created',)
+    # class Meta:
+    #    ordering = ('-created',)
+
+    class MPTTMeta:
+        order_insertion_by = ['created']
 
     def __str__(self):
         return self.body[:20]

+ 1 - 0
MyBlog/comment/urls.py

@@ -5,4 +5,5 @@ app_name = 'comment'
 
 urlpatterns = [
     path('post_comment/<int:article_id>', views.post_comment, name='post_comment'),
+    path('post_comment/<int:article_id>/<int:parent_comment_id>', views.post_comment, name='comment_reply'),
 ]

+ 20 - 2
MyBlog/comment/views.py

@@ -4,10 +4,11 @@ from django.contrib.auth.decorators import login_required
 
 from article.models import ArticlePost
 from .forms import CommentPost
+from .models import Comment
 
 
 @login_required(login_url='/user/login')
-def post_comment(request, article_id):
+def post_comment(request, article_id, parent_comment_id=None):
     article = get_object_or_404(ArticlePost, id=article_id)
     if request.method == 'POST':
         comment_form = CommentPost(data=request.POST)
@@ -15,9 +16,26 @@ def post_comment(request, article_id):
             new_comment_form = comment_form.save(commit=False)
             new_comment_form.article = article
             new_comment_form.user = request.user
+            # 二级回复
+            if parent_comment_id:
+                parent_comment = Comment.objects.get(id=parent_comment_id)
+                # 若回复层级超过二级,则转换为二级
+                new_comment_form.parent_id = parent_comment.get_root().id
+                # 被回复人
+                new_comment_form.reply_to = parent_comment.user
+                new_comment_form.save()
+                return HttpResponse('200 OK')
             new_comment_form.save()
             return redirect(article)
         else:
             return HttpResponse('表单有错误,请重新填写')
+    elif request.method == 'GET':
+        comment_form = CommentPost()
+        context = {
+            'comment_form': comment_form,
+            'article_id': article_id,
+            'parent_comment_id': parent_comment_id
+        }
+        return render(request, 'comment/reply.html', context)
     else:
-        return HttpResponse('发表评论仅接受POST请求')
+        return HttpResponse('发表评论仅接受GET/POST请求')

BIN
MyBlog/db.sqlite3


BIN
MyBlog/media/article/20210129/541332.jpg


BIN
MyBlog/media/article/20210130/1030509.jpg


BIN
MyBlog/media/article/20210130/923425.jpg


BIN
MyBlog/media/avatar/20210123/157767.jpg


+ 38 - 0
MyBlog/static/csrf.js

@@ -0,0 +1,38 @@
+$(document).ajaxSend(function (event, xhr, settings) {
+    function getCookie(name) {
+        var cookieValue = null;
+        if (document.cookie && document.cookie != '') {
+            var cookies = document.cookie.split(';');
+            for (var i = 0; i < cookies.length; i++) {
+                var cookie = jQuery.trim(cookies[i]);
+                // Does this cookie string begin with the name we want?
+                if (cookie.substring(0, name.length + 1) == (name + '=')) {
+                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
+                    break;
+                }
+            }
+        }
+        return cookieValue;
+    }
+
+    function sameOrigin(url) {
+        // url could be relative or scheme relative or absolute
+        var host = document.location.host; // host + port
+        var protocol = document.location.protocol;
+        var sr_origin = '//' + host;
+        var origin = protocol + sr_origin;
+        // Allow absolute or scheme relative URLs to same origin
+        return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
+            (url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
+            // or any other URL that isn't scheme relative or absolute i.e relative.
+            !(/^(\/\/|http:|https:).*/.test(url));
+    }
+
+    function safeMethod(method) {
+        return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
+    }
+
+    if (!safeMethod(settings.type) && sameOrigin(settings.url)) {
+        xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
+    }
+});

Dosya farkı çok büyük olduğundan ihmal edildi
+ 7 - 0
MyBlog/static/sticky_sidebar/jquery.sticky-sidebar.min.js


+ 124 - 23
MyBlog/templates/article/detail.html

@@ -6,11 +6,13 @@
 {% block content %}
     <div class="container">
         <div class="row">
-            <div class="col-3 mt-4">
-                <h4><strong>目录</strong></h4>
-                <hr>
-                <div>
-                    {{ tor|safe }}
+            <div class="col-3 mt-4 sidebar" id="sidebar">
+                <div class="sidebar__inner">
+                    <h4><strong>目录</strong></h4>
+                    <hr>
+                    <div>
+                        {{ tor|safe }}
+                    </div>
                 </div>
             </div>
             <div class="col-9">
@@ -84,22 +86,76 @@
                     </h5>
                     <br>
                 {% endif %}
+                {% load mptt_tags %}
                 <h4>共有{{ comments.count }}条评论</h4>
-                <div>
-                    {% for comment in comments %}
-                        <hr>
-                        <p>
-                            <strong style="color: pink">
-                                {{ comment.user }}
-                            </strong>于
-                            <span style="color: green">
-                        {{ comment.created|date:"Y-m-d H:i:s" }}
-                    </span>时评论道:
-                        </p>
-                        <pre style="font-family: inherit;font-size: 1em;">
-                    {{ comment.body|safe }}
-                </pre>
-                    {% endfor %}
+                <div class="row">
+                    <!-- 遍历树形结构 -->
+                    {% recursetree comments %}
+                        <!-- 给 node 取个别名 comment -->
+                        {% with comment=node %}
+                            <div class="{% if comment.reply_to %}
+                                            offset-1 col-11
+                                        {% else %}
+                                            col-12
+                                        {% endif %}">
+                                <hr>
+                                <p>
+                                    <strong style="color: pink">
+                                        {{ comment.user }}
+                                    </strong>
+                                    {% if comment.reply_to %}
+                                        <i class="far fa-arrow-alt-circle-right"
+                                           style="color: cornflowerblue;"
+                                        ></i>
+                                        <strong style="color: pink">
+                                            {{ comment.reply_to }}
+                                        </strong>
+                                    {% endif %}
+                                </p>
+                                <div>{{ comment.body|safe }}</div>
+                                <div>
+                                    <span style="color: gray">
+                                        {{ comment.created|date:"Y-m-d H:i" }}
+                                    </span>
+                                    <!-- 加载 modal 的按钮 -->
+                                    {% if user.is_authenticated %}
+                                        <button type="button"
+                                                class="btn btn-light btn-sm text-muted"
+                                                onclick="load_modal({{ article.id }}, {{ comment.id }})">
+                                            回复
+                                        </button>
+                                    {% else %}
+                                        <a class="btn btn-light btn-sm text-muted"
+                                           href="{% url 'userprofile:login' %}">
+                                            回复
+                                        </a>
+                                    {% endif %}
+                                </div>
+                                <!-- Modal -->
+                                <div class="modal fade"
+                                     id="comment_{{ comment.id }}"
+                                     tabindex="-1"
+                                     role="dialog"
+                                     aria-labelledby="CommentModalCenter"
+                                     aria-hidden="true">
+                                    <div class="modal-dialog modal-dialog-centered modal-lg" role="document">
+                                        <div class="modal-content" style="height: 480px">
+                                            <div class="modal-header">
+                                                <h5 class="modal-title" id="exampleModalCenterTitle">
+                                                    回复 {{ comment.user }}:</h5>
+                                            </div>
+                                            <div class="modal-body" id="modal_body_{{ comment.id }}"></div>
+                                        </div>
+                                    </div>
+                                </div>
+                                {% if not comment.is_leaf_node %}
+                                    <div class="children">
+                                        {{ children }}
+                                    </div>
+                                {% endif %}
+                            </div>
+                        {% endwith %}
+                    {% endrecursetree %}
                 </div>
             </div>
         </div>
@@ -117,10 +173,55 @@
         }
     </script>
     <script src="{% static 'ckeditor/ckeditor/plugins/prism/lib/prism/prism_patched.min.js' %}"></script>
+    <!-- 粘性侧边栏样式 -->
+    <style>
+        .sidebar {
+            will-change: min-height;
+        }
+
+        .sidebar__inner {
+            transform: translate(0, 0);
+            transform: translate3d(0, 0, 0);
+            will-change: position, transform;
+        }
+    </style>
     <link rel="stylesheet" href="{% static 'prism/prism.css' %}">
 {% endblock content %}
 {% block script %}
-<script>
-    $(".django-ckeditor-widget").removeAttr('style');
-</script>
+    <!--二级回复-->
+    <script>
+        // 加载 modal
+        function load_modal(article_id, comment_id) {
+            let modal_body = '#modal_body_' + comment_id;
+            let modal_id = '#comment_' + comment_id;
+
+            // 加载编辑器
+            if ($(modal_body).children().length === 0) {
+                let content = '<iframe src="/comment/post_comment/' +
+                    article_id +
+                    '/' +
+                    comment_id +
+                    '"' +
+                    ' frameborder="0" style="width: 100%; height: 100%;" id="iframe_' +
+                    comment_id +
+                    '"></iframe>';
+                $(modal_body).append(content);
+            }
+            ;
+
+            $(modal_id).modal('show');
+        }
+    </script>
+
+    <!--侧边栏-->
+    <script>
+        $(".django-ckeditor-widget").removeAttr('style');
+    </script>
+    <script src="{% static 'sticky_sidebar/jquery.sticky-sidebar.min.js' %}"></script>
+    <script type="text/javascript">
+        $('#sidebar').stickySidebar({
+            topSpacing: 20,
+            bottomSpacing: 20,
+        });
+    </script>
 {% endblock script %}

+ 9 - 6
MyBlog/templates/article/list.html

@@ -98,14 +98,17 @@
                     <p>
                         <!--附加消息-->
                         <span style="color: green;">
-                        {{ article.total_views }}浏览&nbsp;&nbsp;&nbsp;
-                    </span>
+                            <i class="fas fa-eye" style="color: lightskyblue;"></i>
+                            {{ article.total_views }}浏览&nbsp;&nbsp;&nbsp;
+                        </span>
                         <span style="color: blue;">
-                        {{ article.created|date:'Y-m-d' }}发布&nbsp;&nbsp;&nbsp;
-                    </span>
+                            <i class="fas fa-comments" style="color: yellowgreen;"></i>
+                            {{ article.created|date:'Y-m-d' }}发布&nbsp;&nbsp;&nbsp;
+                        </span>
                         <span style="color: darkred;">
-                        {{ article.updated|date:'Y-m-d' }}更新
-                    </span>
+                            <i class="fas fa-clock" style="color: pink;"></i>
+                            {{ article.updated|date:'Y-m-d' }}更新
+                        </span>
                     </p>
                     <hr>
                 </div>

+ 61 - 0
MyBlog/templates/back_to_top_func.html

@@ -0,0 +1,61 @@
+<button type="button" id="BackTop" class="toTop-arrow" style="z-index: 100;"></button>
+
+<script>
+    //向上滚动的函数
+    $(function () {
+        $('#BackTop').click(function () {
+            $('html,body').animate({scrollTop: 0}, 500);
+        });
+        $(window).scroll(function () {
+            if ($(this).scrollTop() > 300) {
+                $('#BackTop').fadeIn(300);
+            } else {
+                $('#BackTop').stop().fadeOut(300);
+            }
+        }).scroll();
+    })
+</script>
+
+<style>
+    /* 按钮边框的大小、位置、样式 */
+    .toTop-arrow {
+        width: 3.5rem;
+        height: 3.5rem;
+        padding: 0;
+        margin: 0;
+        border: 0;
+        border-radius: 33%;
+        opacity: 0.7;
+        background: black;
+        cursor: pointer;
+        position: fixed;
+        right: 1.5rem;
+        bottom: 1.5rem;
+        display: none;
+    }
+
+    /* 绘制按钮中的向上箭头 */
+    .toTop-arrow::before, .toTop-arrow::after {
+        width: 31px;
+        height: 7px;
+        border-radius: 3px;
+        background: orange;
+        position: absolute;
+        content: "";
+    }
+
+    .toTop-arrow::before {
+        transform: rotate(-45deg) translate(0, -50%);
+        left: 0.4rem;
+    }
+
+    .toTop-arrow::after {
+        transform: rotate(45deg) translate(0, -50%);
+        right: 0.4rem;
+    }
+
+    /* 取消点击按钮时的聚焦 */
+    .toTop-arrow:focus {
+        outline: none;
+    }
+</style>

+ 27 - 3
MyBlog/templates/base.html

@@ -9,18 +9,42 @@
         {% endblock %}
     </title>
     <link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
-<link rel="stylesheet" href="{% static 'md_css/monokai.css' %}">
+    <link rel="stylesheet" href="{% static 'md_css/monokai.css' %}">
+    <link
+            rel="stylesheet"
+            href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.14.0/css/all.min.css"
+    >
 </head>
 <body>
 {% include "header.html" %}
-{% block content %}
-{% endblock %}
+
+<div id="wrapper">
+    {% block content %}
+    {% endblock content%}
+    <div id="push"></div>
+</div>
 {% include "footer.html" %}
 <script src="{% static 'jQuery/jquery-3.5.1.js' %}"></script>
 <script src="{% static 'layer/layer.js' %}"></script>
 <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1-lts/dist/umd/popper.min.js"></script>
 <script src="{% static 'bootstrap/js/bootstrap.min.js' %}"></script>
+{% include 'back_to_top_func.html' %}
 {% block script %}
 {% endblock script %}
+<style>
+    html, body {
+        height: 100%;
+        margin: 0;
+    }
+
+    #wrapper {
+        min-height: 100%;
+        margin-bottom: -60px;
+    }
+
+    #footer, #push {
+        height: 60px;
+    }
+</style>
 </body>
 </html>

+ 55 - 0
MyBlog/templates/comment/reply.html

@@ -0,0 +1,55 @@
+{% load static %}
+<!DOCTYPE html>
+<html lang="zh-cn">
+<head>
+    <meta charset="utf-8">
+    <link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
+</head>
+<body>
+<form
+        action="."
+        method="POST"
+        id="reply_form"
+>
+    {% csrf_token %}
+    <div class="form-group">
+        <div id="test">
+            {{ comment_form.media }}
+            {{ comment_form.body }}
+        </div>
+    </div>
+</form>
+<!-- 提交按钮 -->
+<button onclick="confirm_submit({{ article_id }}, {{ parent_comment_id }})" class="btn btn-primary">发送</button>
+
+<script src="{% static 'jQuery/jquery-3.5.1.js' %}"></script>
+<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1-lts/dist/umd/popper.min.js"></script>
+<script src="{% static 'bootstrap/js/bootstrap.min.js' %}"></script>
+
+<!-- csrf token -->
+<script src="{% static 'csrf.js' %}"></script>
+
+<script>
+    $(function () {
+        $(".django-ckeditor-widget").removeAttr('style');
+    });
+
+    function confirm_submit(article_id, comment_id) {
+        // 从 ckeditor 中取值
+        let content = CKEDITOR.instances['id_body'].getData();
+        // 调用 ajax 与后端交换数据
+        $.ajax({
+            url: '/comment/post_comment/' + article_id + '/' + comment_id,
+            type: 'POST',
+            data: {body: content},
+            // 成功回调
+            success: function (e) {
+                if (e === '200 OK') {
+                    parent.location.reload();
+                }
+            }
+        })
+    }
+</script>
+</body>
+</html>

+ 1 - 1
MyBlog/templates/footer.html

@@ -3,7 +3,7 @@
 <div>
     <br><br><br>
 </div>
-<footer class="py-3 bg-dark">
+<footer class="py-3 bg-dark" id="footer">
     <div class="container">
         <p class="m-0 text-center text-white">Copyright &copy; blog.shellmiao.com 2021</p>
     </div>

+ 0 - 27
MyBlog/userprofile/migrations/0001_initial.py

@@ -1,27 +0,0 @@
-# Generated by Django 3.1.1 on 2021-01-21 14:36
-
-from django.conf import settings
-from django.db import migrations, models
-import django.db.models.deletion
-
-
-class Migration(migrations.Migration):
-
-    initial = True
-
-    dependencies = [
-        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
-    ]
-
-    operations = [
-        migrations.CreateModel(
-            name='Profile',
-            fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('phone', models.CharField(blank=True, max_length=20)),
-                ('avatar', models.ImageField(blank=True, upload_to='avatar/%Y%m%d/')),
-                ('bio', models.TextField(blank=True, max_length=500)),
-                ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='profile', to=settings.AUTH_USER_MODEL)),
-            ],
-        ),
-    ]

+ 0 - 0
MyBlog/userprofile/migrations/__init__.py


Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor