2019-08-05 第七章Django高级实战 开发企业级问答网站

  • 2019-05-19 开始学习第六章,现在才开始编辑第七章.我真的好拖延啊.
    7-1 文章模块models.py设计
  • python manage.py startapp articles
  • zanhu/artivles/models.py
from django.db import models
from six import python_2_unicode_compatible


@python_2_unicode_compatible
class Article(models.Model):
    STATUS = (("D", "Draft"), ("P", "Published"))

    title = models.CharField(max_length=255, null=False, unique=True, verbose_name='标题')
    user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, related_name="author", on_delete=models.SET_NULL, verbose_name='作者')
    image = models.ImageField(upload_to='articles_pictures/%Y/%m/%d/', verbose_name='文章图片')
    slug = models.SlugField(max_length=80, null=True, blank=True, verbose_name='(URL)别名')
    status = models.CharField(max_length=1, choices=STATUS, default='D', verbose_name='动态')  # 默认存入草稿箱
    content = models.TextField(verbose_name='内容')
    edited = models.BooleanField(default=False, verbose_name='是否可编辑')
    created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间')

    class Meta:
        verbose_name = '文章'
        verbose_name_plural = verbose_name
        ordering = ("created_at",)

    def __str__(self):
        return self.title

7-2 使用python-slugify和django-taggit

  • python-slugify 网址显示题目的拼音.

7-3 models.py中自定义QuerySet

from django.db import models
from six import python_2_unicode_compatible
from slugify import slugify
from taggit.managers import TaggableManager
from django.conf import settings

@python_2_unicode_compatible
class ArticleQuerySet(models.query.QuerySet):
    """自定义QuerySet,提高模型类的可用性"""

    def get_published(self):
        """返回已发表的文章"""
        return self.filter(status="P")

    def get_drafts(self):
        """返回草稿箱的文章"""
        return self.filter(status="D")

    def get_counted_tags(self):
        """统计所有已发布的文章中,每一个标签的数量(大于0的)"""
        tag_dict = {}
        query = self.filter(status='P').annotate(tagged=Count('tags')).filter(tags__gt=0)
        for obj in query:
            for tag in obj.tags.names():
                if tag not in tag_dict:
                    tag_dict[tag] = 1

                else:
                    tag_dict[tag] += 1
        return tag_dict.items()

@python_2_unicode_compatible
class Article(models.Model):
    STATUS = (("D", "Draft"), ("P", "Published"))

    title = models.CharField(max_length=255, null=False, unique=True, verbose_name='标题')
    user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, related_name="author", on_delete=models.SET_NULL, verbose_name='作者')
    image = models.ImageField(upload_to='articles_pictures/%Y/%m/%d/', verbose_name='文章图片')
    slug = models.SlugField(max_length=80, null=True, blank=True, verbose_name='(URL)别名')
    status = models.CharField(max_length=1, choices=STATUS, default='D', verbose_name='动态')  # 默认存入草稿箱
    content = models.TextField(verbose_name='内容')
    edited = models.BooleanField(default=False, verbose_name='是否可编辑')
    tags = TaggableManager(help_text='多个标签使用,(英文)隔开', verbose_name='标签')
    created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间')
    objects = ArticleQuerySet.as_manager()

    class Meta:
        verbose_name = '文章'
        verbose_name_plural = verbose_name
        ordering = ("created_at",)

    def __str__(self):
        return self.title

    def save(self, *args, **kwargs):
        if not self.slug:
            # 根据作者和标题生成文章在URL中的别名
            self.slug = slugify(self.title)
        super(Article, self).save(*args, **kwargs)
  • zhanhu/config/setting/base.py
THIRD_PARTY_APPS = [
    "crispy_forms",
    "allauth",
    "allauth.account",
    "allauth.socialaccount",
    "rest_framework",
    "sorl.thumbnail",
    "taggit",
]
LOCAL_APPS = [
    'users.apps.UsersConfig',
    'news.apps.NewsConfig',
    'articles.apps.ArticlesConfig',
    # Your stuff: custom apps go here
]

7-4 完成文章列表页开发

  • articles/views.py
from django.contrib.auth.mixins import LoginRequiredMixin
from django.shortcuts import render

# Create your views here.
from django.views.generic import ListView

from dacall.articles.models import Article


class ArticlesListView(LoginRequiredMixin, ListView):
    """已发布的文章列表"""
    model = Article
    paginate_by = 10
    context_object_name = "articles"
    template_name = "articles/article_list.html"  # 可省略

    def get_context_data(self, *args, **kwargs):
        context = super(ArticlesListView, self).get_context_data(*args, **kwargs)
        context['popular_tags'] = Article.objects.get_counted_tags()
        return context

    def get_queryset(self, **kwargs):
        return Article.objects.get_published()
  • /articles/urls.py
#!/usr/bin/python3
# -*- coding:utf-8 -*-
# __author__ = '__Jack__'

from django.urls import path

from zanhu.articles import views

app_name = 'articles'  # Django > 2.0,这样模板中可以使用"{% url 'articles:list' %}","articles"是总urls.py中定义的namespace

urlpatterns = [
    path('', views.ArticlesListView.as_view(), name='list'),
    path('write-new-article/', views.CreateArticleView.as_view(), name='write_new'),
    path('drafts/', views.DraftsListView.as_view(), name='drafts'),
    path('edit//', views.EditArticleView.as_view(), name='edit_article'),
    path('/', views.DetailArticleView.as_view(), name='article'),
]

  • config/urls.py
from django.conf import settings
from django.urls import include, path
from django.conf.urls.static import static
from django.views.generic import TemplateView
from django.views import defaults as default_views

from dacall.news.views import NewsListView

urlpatterns = [
    path('', NewsListView.as_view(), name='home'),



    # User management
    path("users/", include("dacall.users.urls", namespace="users")),
    path("accounts/", include("allauth.urls")),

    path('news/', include('dacall.news.urls', namespace='news')),
    path('articles/', include('dacall.articles.urls', namespace='articles')),
    # Your stuff: custom urls includes go here
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

if settings.DEBUG:
    # This allows the error pages to be debugged during development, just visit
    # these url in browser to see how these error pages look like.
    urlpatterns += [
        path(
            "400/",
            default_views.bad_request,
            kwargs={"exception": Exception("Bad Request!")},
        ),
        path(
            "403/",
            default_views.permission_denied,
            kwargs={"exception": Exception("Permission Denied")},
        ),
        path(
            "404/",
            default_views.page_not_found,
            kwargs={"exception": Exception("Page not Found")},
        ),
        path("500/", default_views.server_error),
    ]
    if "debug_toolbar" in settings.INSTALLED_APPS:
        import debug_toolbar

        urlpatterns = [path("__debug__/", include(debug_toolbar.urls))] + urlpatterns

  • /templates/base.html
{% load static compress thumbnail %}


    
    
    
    {% block title %}赞乎{% endblock title %}
    
    
    

    
    

    {% compress css %}
        
        
        
        
        
        
        {% block css %}{% endblock css %}
    {% endcompress %}




{% if messages %} {% for message in messages %}
{{ message }}
{% endfor %} {% endif %} {% block content %}{% endblock content %}
{% compress js %} {% block js %}{% endblock js %} {% endcompress %}

7-5 用户发表文章与保存草稿

  • forms.py
from django import forms


from dacall.articles.models import Article


class ArticleForm(forms.ModelForm):
    # status = forms.CharField(widget=forms.HiddenInput())  # 隐藏
    # edited = forms.BooleanField(widget=forms.HiddenInput(), required=False, initial=False)  # 隐藏
    # content = MarkdownxFormField()

    class Meta:
        model = Article
        fields = ["title", "content", "image"]

  • url
    path('write-new-article/', views.CreateArticleView.as_view(), name='write_new'),
    path('drafts/', views.DraftsListView.as_view(), name='drafts'),
    path('edit//', views.EditArticleView.as_view(), name='edit_article'),

  • views.py

class DraftsListView(ArticlesListView):
    """草稿箱文章列表"""

    def get_queryset(self, **kwargs):
        # 当前用户的草稿
        return Article.objects.filter(user=self.request.user).get_drafts()




class CreateArticleView(LoginRequiredMixin, CreateView):
    """创建文章"""
    model = Article
    message = "您的文章已创建成功!"  # Django框架中的消息机制
    form_class = ArticleForm
    template_name = 'articles/article_create.html'

    def form_valid(self, form):
        form.instance.user = self.request.user
        return super(CreateArticleView, self).form_valid(form)

    def get_success_url(self):
        """创建成功后跳转"""
        messages.success(self.request, self.message)  # 消息传递给下一次请求
        return reverse_lazy('articles:list')

7-6 实现Markdown编辑与实时预览

  • 安装markdownx
  • settting/base.py
THIRD_PARTY_APPS = [
    "crispy_forms",
    "allauth",
    "allauth.account",
    "allauth.socialaccount",
    "rest_framework",
    "sorl.thumbnail",
    "taggit",
    "markdownx",
]
  • 总url.py
    # 第三方应用
    # path('comments/', include('django_comments.urls')),
    path('markdownx/', include('markdownx.urls')),
  • forms
from django import forms

from markdownx.fields import MarkdownxFormField

from dacall.articles.models import Article


class ArticleForm(forms.ModelForm):
    status = forms.CharField(widget=forms.HiddenInput())  # 隐藏
    edited = forms.BooleanField(widget=forms.HiddenInput(), required=False, initial=False)  # 隐藏
    content = MarkdownxFormField()

    class Meta:
        model = Article
        fields = ["title", "content", "image", "tags", "status", "edited"]

pipenv install django-markdownx 没有成功

后来是 pip install django-markdownx成功的.

python manage.py makemigrations
python manage.py migrate  
python manage.py collectstatic 


  • python manage.py collectstatic 这步骤

7-7 通用类视图CreateView源码详解
7-8 用户浏览文章内容

class DetailArticleView(LoginRequiredMixin, DetailView):
    """文章详情"""
    model = Article
    template_name = 'articles/article_detail.html'
    path('/', views.DetailArticleView.as_view(), name='article'),

7-9 django-contrib-comments实现评论文章
7-10 用户编辑文章
7-11 通用类视图UpdateView源码详解
7-12 Django Template Language语法精讲
7-13 Django Template Language语法精讲
7-14 模型类和视图的测试用例
7-15 本章总结与课后作业.

你可能感兴趣的:(2019-08-05 第七章Django高级实战 开发企业级问答网站)