这里主要是三张表Tag、Category、Post,关于评论,后面再加
安装包
pip install django-model-utils
pip install pillow
pip install django-imagekit
pip install django-uuslug
pip install markdown
from django.db import models
from django.contrib.auth.models import User
from django.db.models import F
from django.urls import reverse
from django.utils import timezone
from django.utils.functional import cached_property
from django.utils.html import strip_tags
from django.utils.translation import gettext_lazy as _
from model_utils import Choices
from model_utils.models import TimeStampedModel
from imagekit.models import ImageSpecField
# Create your models here.
from uuslug import slugify
from blogproject.utils import generate_rich_content
class Category(TimeStampedModel):
id = models.AutoField(primary_key=True)
name = models.CharField(_("name"), max_length=100)
slug = models.SlugField(_("slug"), editable=False, max_length=200, unique=True)
def natural_key(self):
return self.__str__()
def save(self, *args, **kwargs):
self.slug = slugify(self.name)
super(Category, self).save(*args, **kwargs)
def __str__(self):
return self.name
class Tag(TimeStampedModel):
id = models.AutoField(primary_key=True)
name = models.CharField(_("name"), max_length=100)
class Meta:
verbose_name = _("tag")
verbose_name_plural = _("tags")
def natural_key(self):
return self.__str__()
def __str__(self):
return self.name
class Post(models.Model):
STATUS_CHOICES = Choices(
(1, "published", _("published")),
(2, "draft", _("draft")),
(3, "hidden", _("hidden")),
)
author = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
content = models.TextField()
excerpt = models.TextField(_("excerpt"), blank=True)
views = models.PositiveIntegerField(_("views"), default=0, editable=False)
created_time = models.DateTimeField(_("created time"), default=timezone.now)
updated_time = models.DateTimeField(_("created time"), auto_now=True)
likes = models.PositiveIntegerField(default=0)
url_slug = models.SlugField(editable=False, max_length=200)
status = models.PositiveSmallIntegerField(
_("status"), choices=STATUS_CHOICES, default=STATUS_CHOICES.draft
)
tags = models.ManyToManyField(Tag, verbose_name=_("tags"), blank=True)
category = models.ForeignKey(
Category,
on_delete=models.CASCADE,
verbose_name=_("category"),
null=True,
blank=True,
)
class Meta:
verbose_name = _("Posts")
verbose_name_plural = _("Posts")
# ordering = ('-created',)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post:article_detail', args=[self.id])
def save(self, *args, **kwargs):
self.url_slug = slugify(self.title)
super(Post, self).save(*args, **kwargs)
if not self.excerpt:
self.excerpt = strip_tags(self.content)[:150]
if not self.created_time and self.status == self.STATUS_CHOICES.published:
self.created_time = self.created_time
def increase_views(self):
self.__class__.objects.filter(id=self.id).update(views=F("views") + 1)
@property
def body_html(self):
return self.rich_content.get("content", "")
@cached_property
def rich_content(self):
return generate_rich_content(self.content)
@property
def type(self):
return "p"
用到几个自己写的模块
import re
import markdown
from bs4 import BeautifulSoup
from markdown.extensions.toc import TocExtension
from slugify import slugify
def generate_rich_content(value, *, toc_depth=2, toc_url=""):
md = markdown.Markdown(
extensions=[
"markdown.extensions.extra",
"markdown.extensions.codehilite",
"markdown.extensions.admonition",
"markdown.extensions.nl2br",
TocExtension(slugify=slugify, toc_depth=toc_depth),
"pymdownx.magiclink",
"pymdownx.tasklist",
"pymdownx.tilde",
"pymdownx.caret",
]
)
content = md.convert(value)
toc = md.toc
soup = BeautifulSoup(toc, "html.parser")
# must use contents, not children
# if soup.ul.contents:
toc = "".join(map(str, soup.ul.contents)).strip()
if toc_url:
def absolutify(matchobj):
return 'href="{toc_url}{frag}"'.format(
toc_url=toc_url, frag=matchobj.group(1)
)
toc = re.sub('href="(.+)"', absolutify, toc)
return {"content": content, "toc": toc}
from django.conf.urls import url, include
from django.urls import path
from blogproject import views
from rest_framework import routers
from django.views.decorators.csrf import csrf_exempt
app_name = 'blogproject'
urlpatterns = [
url(r'^post/(?P[0-9]+)/(?P[-\w]+)/$', views.post_detail, name='post'),
]
python3 manage.py makemigrations
python3 manage.py migrate
这里如果发生问题的话,把app下migrations里的initial.py和所有迁移记录的py文件都删掉,然后在django-migrations里把对应的初始化initial操作记录删掉,然后重新执行makemigrations和migrate