From f8c8cfba0c244cb9ea6b7633ac916da51154b9a6 Mon Sep 17 00:00:00 2001 From: chaos <381810956@qq.com> Date: Sun, 18 Apr 2021 18:40:02 +0800 Subject: [PATCH 1/2] =?UTF-8?q?Create=20=E7=AC=AC=E5=8D=81=E5=85=AD?= =?UTF-8?q?=E5=91=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../\347\254\254\345\215\201\345\205\255\345\221\250/.keep" | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 "\347\254\254\344\272\214\346\234\237\350\256\255\347\273\203\350\220\245/2\347\217\255/2\347\217\255_chaos/\347\254\254\345\215\201\345\205\255\345\221\250/.keep" diff --git "a/\347\254\254\344\272\214\346\234\237\350\256\255\347\273\203\350\220\245/2\347\217\255/2\347\217\255_chaos/\347\254\254\345\215\201\345\205\255\345\221\250/.keep" "b/\347\254\254\344\272\214\346\234\237\350\256\255\347\273\203\350\220\245/2\347\217\255/2\347\217\255_chaos/\347\254\254\345\215\201\345\205\255\345\221\250/.keep" new file mode 100644 index 00000000..e69de29b -- Gitee From 27018a0d0986a5f867e0fb054740e3249cb65670 Mon Sep 17 00:00:00 2001 From: chaos <381810956@qq.com> Date: Sun, 18 Apr 2021 18:41:26 +0800 Subject: [PATCH 2/2] django comments and restful api --- .../admin.py" | 17 ++ .../apps.py" | 5 + .../models.py" | 32 +++ .../serializers.py" | 20 ++ .../views.py" | 209 ++++++++++++++++++ 5 files changed, 283 insertions(+) create mode 100644 "\347\254\254\344\272\214\346\234\237\350\256\255\347\273\203\350\220\245/2\347\217\255/2\347\217\255_chaos/\347\254\254\345\215\201\345\205\255\345\221\250/admin.py" create mode 100644 "\347\254\254\344\272\214\346\234\237\350\256\255\347\273\203\350\220\245/2\347\217\255/2\347\217\255_chaos/\347\254\254\345\215\201\345\205\255\345\221\250/apps.py" create mode 100644 "\347\254\254\344\272\214\346\234\237\350\256\255\347\273\203\350\220\245/2\347\217\255/2\347\217\255_chaos/\347\254\254\345\215\201\345\205\255\345\221\250/models.py" create mode 100644 "\347\254\254\344\272\214\346\234\237\350\256\255\347\273\203\350\220\245/2\347\217\255/2\347\217\255_chaos/\347\254\254\345\215\201\345\205\255\345\221\250/serializers.py" create mode 100644 "\347\254\254\344\272\214\346\234\237\350\256\255\347\273\203\350\220\245/2\347\217\255/2\347\217\255_chaos/\347\254\254\345\215\201\345\205\255\345\221\250/views.py" diff --git "a/\347\254\254\344\272\214\346\234\237\350\256\255\347\273\203\350\220\245/2\347\217\255/2\347\217\255_chaos/\347\254\254\345\215\201\345\205\255\345\221\250/admin.py" "b/\347\254\254\344\272\214\346\234\237\350\256\255\347\273\203\350\220\245/2\347\217\255/2\347\217\255_chaos/\347\254\254\345\215\201\345\205\255\345\221\250/admin.py" new file mode 100644 index 00000000..9f1203d5 --- /dev/null +++ "b/\347\254\254\344\272\214\346\234\237\350\256\255\347\273\203\350\220\245/2\347\217\255/2\347\217\255_chaos/\347\254\254\345\215\201\345\205\255\345\221\250/admin.py" @@ -0,0 +1,17 @@ +from django.contrib import admin +from .models import Article +from .models import Category,Tag + + +class CategoryInline(admin.TabularInline): + model = Category + +class TagInline(admin.TabularInline): + model = Tag + +class ArticleAdmin(admin.ModelAdmin): + inlines = [CategoryInline, TagInline] + list_display = ['title', 'create_time'] + +# Register your models here. +admin.site.register(Article, ArticleAdmin) \ No newline at end of file diff --git "a/\347\254\254\344\272\214\346\234\237\350\256\255\347\273\203\350\220\245/2\347\217\255/2\347\217\255_chaos/\347\254\254\345\215\201\345\205\255\345\221\250/apps.py" "b/\347\254\254\344\272\214\346\234\237\350\256\255\347\273\203\350\220\245/2\347\217\255/2\347\217\255_chaos/\347\254\254\345\215\201\345\205\255\345\221\250/apps.py" new file mode 100644 index 00000000..225ff244 --- /dev/null +++ "b/\347\254\254\344\272\214\346\234\237\350\256\255\347\273\203\350\220\245/2\347\217\255/2\347\217\255_chaos/\347\254\254\345\215\201\345\205\255\345\221\250/apps.py" @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class BlogConfig(AppConfig): + name = 'blog' diff --git "a/\347\254\254\344\272\214\346\234\237\350\256\255\347\273\203\350\220\245/2\347\217\255/2\347\217\255_chaos/\347\254\254\345\215\201\345\205\255\345\221\250/models.py" "b/\347\254\254\344\272\214\346\234\237\350\256\255\347\273\203\350\220\245/2\347\217\255/2\347\217\255_chaos/\347\254\254\345\215\201\345\205\255\345\221\250/models.py" new file mode 100644 index 00000000..81d79739 --- /dev/null +++ "b/\347\254\254\344\272\214\346\234\237\350\256\255\347\273\203\350\220\245/2\347\217\255/2\347\217\255_chaos/\347\254\254\345\215\201\345\205\255\345\221\250/models.py" @@ -0,0 +1,32 @@ +from django.db import models +from mdeditor.fields import MDTextField + + +# Create your models here. +class Article(models.Model): + id = models.AutoField(primary_key=True) + title = models.CharField(max_length=200) + text = MDTextField() + url = models.CharField(max_length=200) + update_time = models.DateTimeField(auto_now=True) + create_time = models.DateTimeField(auto_now_add=True) + + class Meta: + db_table = "article" + + def __str__(self): + return f"
" + + +class Category(models.Model): + article = models.ForeignKey(Article, on_delete=models.CASCADE) + name = models.CharField(max_length=200) + slug = models.CharField(max_length=200) + uri = models.CharField(max_length=200) + + +class Tag(models.Model): + article = models.ForeignKey(Article, on_delete=models.CASCADE) + name = models.CharField(max_length=200) + slug = models.CharField(max_length=200) + uri = models.CharField(max_length=200) \ No newline at end of file diff --git "a/\347\254\254\344\272\214\346\234\237\350\256\255\347\273\203\350\220\245/2\347\217\255/2\347\217\255_chaos/\347\254\254\345\215\201\345\205\255\345\221\250/serializers.py" "b/\347\254\254\344\272\214\346\234\237\350\256\255\347\273\203\350\220\245/2\347\217\255/2\347\217\255_chaos/\347\254\254\345\215\201\345\205\255\345\221\250/serializers.py" new file mode 100644 index 00000000..3fb8e158 --- /dev/null +++ "b/\347\254\254\344\272\214\346\234\237\350\256\255\347\273\203\350\220\245/2\347\217\255/2\347\217\255_chaos/\347\254\254\345\215\201\345\205\255\345\221\250/serializers.py" @@ -0,0 +1,20 @@ +from rest_framework import serializers +from .models import Article + + +class ArticleSerializer(serializers.ModelSerializer): + class Meta: + model = Article + # 可以只填充我们使用到的字段 + fields = ("title", "text", "url", "create_time") + + +""" +>>> from blog.models import Article +>>> from blog.serializers import ArticleSerializer +>>> import json + +>>> article_array = Article.objects.all() +>>> se_articles = ArticleSerializer(article_array, many=True) +>>> json_articles = json.dumps(se_articles.data) +""" \ No newline at end of file diff --git "a/\347\254\254\344\272\214\346\234\237\350\256\255\347\273\203\350\220\245/2\347\217\255/2\347\217\255_chaos/\347\254\254\345\215\201\345\205\255\345\221\250/views.py" "b/\347\254\254\344\272\214\346\234\237\350\256\255\347\273\203\350\220\245/2\347\217\255/2\347\217\255_chaos/\347\254\254\345\215\201\345\205\255\345\221\250/views.py" new file mode 100644 index 00000000..1a660dfd --- /dev/null +++ "b/\347\254\254\344\272\214\346\234\237\350\256\255\347\273\203\350\220\245/2\347\217\255/2\347\217\255_chaos/\347\254\254\345\215\201\345\205\255\345\221\250/views.py" @@ -0,0 +1,209 @@ +from django.shortcuts import render +from .models import Article, Category, Tag +from .serializers import ArticleSerializer +from django.views.generic import TemplateView +from django.core.cache import cache +from django.core import serializers +from django.http import JsonResponse +from django.db import transaction +import json +import math +import markdown +import time +from datetime import datetime +from rest_framework.views import APIView + + +# Create your views here. +class IndexView(TemplateView): + template_name = "new_index.html" + + def get(self, request, *args, **kwargs): + article_list = Article.objects.order_by("-create_time") + for article in article_list: + article.pub_date = article.create_time.strftime("%m-%d") + article.length = len(article.text) + article.read_time = math.ceil(len(article.text)/180) if article.text else 0 + article.categories = article.category_set.values() + article.tags = article.tag_set.values() + + context = { + "article_list": article_list, + } + return self.render_to_response(context) + +class DetailView(TemplateView): + template_name = "new_details.html" + + def get(self, request, *args, **kwargs): + article = Article.objects.get(url=request.path) + content = "" + for line in article.text.split("\n"): + content += line.strip(" ") if "```" in line else line + content += "\n" + article.content = markdown.markdown(content, extensions=[ + 'markdown.extensions.extra', + 'markdown.extensions.codehilite', + 'markdown.extensions.toc', + ]) + + select_sql = f"select * from {Article._meta.db_table} where id < {article.id} order by id desc limit 1" + raw_query_set = Article.objects.raw(select_sql) + try: + next_article = raw_query_set[0] + pre_article = raw_query_set[-1] + context = { + "pre_article": pre_article, + "article": article, + "next_article": next_article, + } + except IndexError: + context = { + "article": article, + } + return self.render_to_response(context) + +class ArchiveView(TemplateView): + template_name = "archive.html" + + """ + 需要将对象转换为json存到redis缓存中, 然后从redis缓存中获取json数据, 再反序列化为对象 + """ + def get(self, request, *args, **kwargs): + # 先从缓存中查找 + redis_key = "archive_cache" + redis_value = cache.get(redis_key) + if redis_value: + print("hit cache") + serializer_archives = json.loads(redis_value) + archive_list = [] + article_count = 0 + for archive in serializer_archives: + # 为了模板可以正常渲染, 需要将article反序列化为对象 + archive_list.append({ + "year": archive['year'], + "article_list": [obj.object for obj in serializers.deserialize('json', archive['article_list'])] + }) + article_count += len(archive['article_list']) + + context = { + "archive_list": archive_list, + "article_count": article_count + } + else: + article_list = Article.objects.all() + + archive_dict = {} + for article in article_list: + year = article.create_time.strftime("%Y") + archive_dict.setdefault(year, {"year": year, "article_list": []}) + archive_dict[year]['article_list'].append(article) + + context = { + "archive_list": archive_dict.values(), + "article_count": len(article_list) + } + + # 把刚才的文章添加到缓存 + serializer_archives = [] + for archive in archive_dict.values(): + serializer_archives.append({ + "year": archive['year'], + "article_list": serializers.serialize("json", archive['article_list']) + }) + cache.set(redis_key, json.dumps(serializer_archives)) + cache.expire(redis_key, 30) + + return self.render_to_response(context) + +class ArticleApiView(APIView): + def get(self, request, *args, **kwargs): + """ + article?limit_num=2 + :param args: + :param kwargs: + :return: + """ + limit_num = request.GET.get("limit_num") + if limit_num: + article_array = Article.objects.all()[:int(limit_num)] + else: + article_array = Article.objects.all() + se_article_array = ArticleSerializer(article_array, many=True) + return JsonResponse({ + "status": 200, + "data": se_article_array.data + }, safe=False) + + def post(self, request, *args, **kwargs): + """ + 添加文章的时候, 需要带上category和tag的信息 + 只要article, category, tag有一方报错的时候, 当前文章都算添加失败. + 所以我们应该适用事务进行包装 + :param request: + :param args: + :param kwargs: + :return: + """ + try: + message = {"status": 200} + with transaction.atomic(): + title = request.POST['title'] + text = request.POST['text'] + categories = json.loads(request.POST['categories']) + tags = json.loads(request.POST['tags']) + + article_data = { + "title": title, + "text": text, + "url": f"/{time.strftime('%Y/%m/%d')}/{title}.html" + } + se_article = ArticleSerializer(data=article_data) + se_article.is_valid() + article = se_article.create(se_article.data) + article.save() + + for category in categories: + cate = Category( + name=category['name'], + slug=category['slug'], + uri=f"/categories/{category['slug']}/" + ) + cate.article = article + cate.save() + + for tag in tags: + tag = Tag( + name=tag['name'], + slug=tag['slug'], + uri=f"/tags/{tag['slug']}/" + ) + tag.article = article + tag.save() + except: + message = {"status": 500, "reason": "添加文章失败"} + finally: + response = JsonResponse(message, safe=False) + response['Access-Control-Allow-Origin'] = "*" + response['Access-Control-Allow-Headers'] = "*" + response['Access-Control-Allow-Methods'] = "OPTIONS, POST, GET" + return response + + def put(self, request, article_id): + update_article = Article.objects.get(article_id) + data = ArticleSerializer(data=request.data) + if data.is_valid(): + data.save() + return JsonResponse({ + "status": 200, + "reason": f"更新文章{update_article}成功", + }) + else: + return JsonResponse({"reason": f"更新文章{update_article}失败"}) + + def delete(self, request, article_id): + Article.objects.get(id=article_id).delete() + return JsonResponse({ + "status": 200, + "reason": "删除文件成功", + }) \ No newline at end of file -- Gitee