上一篇介绍过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了,添加了一个富文本编辑器
实在是太困了,具体的做法以后再细说吧,网上也有很多这种的教程,自己搜一个吧