• 用django写个CMS系统


    上一篇介绍过django自带的flatpages,能够做简单的CMS。但是对于我们的真正的工作中的使用意义并不大。还是自己动手写一个吧。

    不用说,一定是先从models开始的:

     1 from django.db import models
     2 
     3 # Create your models here.
     4 
     5 from django.contrib.auth.models import User
     6 from django.db.models import permalink
     7 from markdown import markdown
     8 from django.utils import timezone
     9 from DjangoUeditor.models import UEditorField
    10 
    11 VIEWABLE_STATUS=[3,4]
    12 
    13 
    14 class ViewableManager(models.Manager):
    15     def ge_query_set(self):
    16         default_queryset = super(ViewableManager,self).get_queryset()
    17         return default_queryset.filter(status__in = VIEWABLE_STATUS)
    18 
    19 
    20 class Story(models.Model):
    21     STATUS_CHOICES= (
    22         (1,"Need Edit"),
    23         (2,"Need Approval"),
    24         (3,"Published"),
    25         (4,"Archived"),
    26     )
    27     title = models.CharField(max_length=100)
    28     slug = models.SlugField()
    29     category = models.ForeignKey("Category")
    30     markdown_content = UEditorField('内容', height=300, width=1000,
    31         default=u'', blank=True, imagePath="uploads/images/",
    32         toolbars='besttome', filePath='uploads/files/')
    33     html_content = models.TextField(editable=False)
    34     owner = models.ForeignKey(User)
    35     status = models.IntegerField(choices=STATUS_CHOICES,default=1)
    36     created = models.DateTimeField(auto_now_add=True)
    37     modified= models.DateTimeField(auto_now=True)
    38     class Meta:
    39         ordering =['modified']
    40         verbose_name_plural= '新闻故事'
    41     admin_objects = models.Manager()
    42     objects = ViewableManager()
    43 
    44     def save(self,*args,**kwargs):
    45         self.html_content = markdown(self.makedown_content)
    46         self.modified= timezone.now()
    47         super(Story,self).save(*args,**kwargs)
    48 
    49     @permalink
    50     def get_absolute_url(self):
    51         return ('cms-story',None,{'slug':self.slug})
    52 
    53     def __str__(self):
    54         return self.title
    55 
    56 
    57 class Category(models.Model):
    58     label = models.CharField(max_length=64)
    59     slug = models.SlugField()
    60 
    61     class Meta:
    62         verbose_name_plural="分类"
    63 
    64     def __str__(self):
    65         return self.label

    model中有几个需要注意的地方:

    1、自定义了Story类的manger,这个是为了在使用queryset的时候objects.all()等查询数据库时只显示已经发布或者存档的文章或新闻

    2、修改了markdown_content为UEditorField字段,可能很多小伙伴没见过,表着急,这个后面会解释,可以先改成TextField字段

    3、重写了save方法,在保存数据的时候生成html_content

    接下来是url

    from django.views.generic import ListView,DetailView
    
    from cms.views import category,StoryDetailView,StoryListView,search
    
    
    urlpatterns = [
        url(r'^$',StoryListView.as_view(),name="cms-home"),
        url(r'^story/(?P<slug>[-_w]+)/$',StoryDetailView.as_view(),name="cms-story"),
        url(r'^category/(?P<slug>[-_w]+)/$',category,name="cms-category"),
        url(r'^search/$',search,name="cms-search"),
    ]

    好吧,路由分配系统写完了之后,就该开始写我们的试图了,我这里用了两个通用类试图,可能某些小伙伴不太习惯吧,你写成试图函数也可以的,用我们领导的经典语句:“嗯哼,这都没有关系~~~”。

    from django.shortcuts import render,get_object_or_404,render_to_response
    from django.db.models import Q
    from cms.models import Category,Story
    from django.views.generic import ListView,DetailView
    # Create your views here.
    
    def category(request,slug):
        category_obj = get_object_or_404(Category,slug=slug)
        story_list = Story.objects.filter(category=category_obj)
        heading = "Category:%s"%category_obj.label
        return render(request,'cms/story_list.html',locals())
    
    class StoryListView(ListView):
        model = Story
        template_name = 'cms/story_list.html'
        context_object_name = "story_list"
    
    class StoryDetailView(DetailView):
        model = Story
        template_name = "cms/story_detail.html"
        context_object_name = "story"
    
    def search(request):
        print(request.GET)
        if 'q' in request.GET:
    
            term = request.GET.get('q')
            story_list = Story.objects.filter(Q(title__icontains=term)|Q(makedown_content__icontains=term)).all()
            heading = "检索结果"
            return render(request,"cms/story_list.html",locals())

    看看这些试图都干了些什么吧,展示文章列表,展示分类文章,展示文章详情,一个简单的查询。

    前端页面的代码实在是懒得弄了,简单凑合一下吧

    首先写一个母版base.html 

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>{% block title %}{% endblock %}</title>
        <style>
            body{margin: 15px;
                font-family: "Arial Black";
            }
            h1,h2{background: #aaa;
                padding: 1% 2%;
                margin: 0;
            }
            a{text-decoration: none;
                color: #444;
            }
            .small{
                font-size: 75%;
                color: #777;
            }
            #header{
                font-weight: bold;background: #ccc;padding: 1% 2%;
            }
            #story_body{
                background: #ccc;
                padding: 2%;
            }
            #story_list{
                background: #ccc;
                padding: 1% 1% 1% 2%;
            }
            #story_list li{
                margin: 0.5em 0;
            }
    
        </style>
    </head>
    <body>
            <div id="header">
                <form action="{% url 'cms-search' %}" method="get">
                    <a href="{% url 'cms-home' %}">Home</a>
                    <span style="padding: 0 50px"></span>
                    <label for="q">Search</label><input type="text" name="q"/>
                </form>
            </div>
            {% block content %}{% endblock %}
    </body>
    </html>

    接下来是文章列表的展示了cms/story_list.html

    {% extends "base.html" %}
    {% block title %}
        {{ heading }}
    {% endblock %}
    
    {% block content %}
        {% if heading %}
            <h1>{{ heading }}</h1>
        {% endif %}
        <ul id="story_list">
            {% for story in story_list %}
                <li><a href="{{ story.get_absolute_url }}">{{ story.title }}</a></li>
            {% endfor %}
        </ul>
    {% endblock %}

    最好不要把html中的url写死了,方便你以后的扩展或修改

    接下来是文章详情展示

    {% extends "base.html" %}
    {% block title %}
        {{ story.title }}
    {% endblock %}
    {% block content %}
        <h1>{{ story.title }}</h1>
        <h2><a href="{% url "cms-category" story.category.slug %}">{{ story.category }}</a></h2>
        <div id="story-body">
            {{ story.html_content|safe }}
        <p class="small">{{ story.modified }}</p>
        </div>
    {% endblock %}

    效果图

    最后在来解释一下model中的UEditorField字段,这个是因为我觉得admin后台的text文本框字段太low了,添加了一个富文本编辑器

    实在是太困了,具体的做法以后再细说吧,网上也有很多这种的教程,自己搜一个吧

  • 相关阅读:
    log4j2配置ThresholdFilter,让info文件记录error日志
    Thrift常见异常及原因分析(<i>UPDATING...</i>)
    fastjson序列化出现StackOverflowError
    mysql执行update语句受影响行数是0
    远程Gitlab新建的分支在IDEA里不显示
    rabbitmq延迟队列demo
    利用延迟消息队列取代定时任务
    利用spring实现服务启动就自动执行某些操作的2种方式
    从Joda-Time反观Java语言利弊
    Linux Shell test判断
  • 原文地址:https://www.cnblogs.com/zuoshoushizi/p/8185960.html
Copyright © 2020-2023  润新知