Django从零搭建CMS(内容管理)系统

本教程分为三部分:思路、详细步骤、开发步骤,从上往下看,便于理解;

思路:

  • 1.准备开发环境
  • 2.学习基本的Django基础知识、搭建简单的polls系统
  • 3.确定练手题材,比如我确定了做个家用的菜谱
  • 4.寻找合适的html模板
  • 5.根据网站需要添加学习添加新的数据类型,比如添加图片上传、添加富文本编辑
  • 6.Windows下部署Django(Apache+mod_wsgi)
  • 7.linux下部署Django(todo)

注意:没有接触过Django但是接触过python的情况下,完成前6步,大概需要2天的时间。

Django常用命令:
简单启动:python manage.py runserver
创建应用:python manage.py startapp xxx
检查app并创建相应的表:python manage.py migrate
激活model-生成sql:python manage.py makemigrations food
激活model-执行sql:python manage.py sqlmigrate food 0001
激活model-再次执行:python manage.py migrate

详细步骤

1.准备开发环境

主要涉及pythonCharm的安装、python3的安装,自己找教程搞定;

2.学习基本的Django基础知识、搭建简单的polls系统

参考官方文档:https://docs.djangoproject.com/zh-hans/2.1/
完成快速入门部分的学习,基本就能了解django的工作原理,各个文件的作用,并搭建一个简单的投票系统;

image.png

3.确定练手题材

根据第2步中学习的知识,自己做一个全新的网站。第一个网站不要太难,建议选择CMS(内容管理系统),我在选择的是家用菜谱。

功能需求:
- 管理后台可以新增、修改、删除菜单
- 编辑好的菜单,可以在页面显示
- 菜单参考饭店的二维码点餐目录:全部菜单、主食、素材、汤等

非功能性需求:
- 界面简洁美观,最好能自适应

二期拓展:
- 菜单可以评论
- 添加日历,记录当然的菜品或事件
- 优化后端界面操作等(xadmin)

4.寻找合适的html模板

我自己没有非常好的前端基础,如果从零写一套美观的界面,非常耗时且不能保证效果。所以我希望使用已有的前端模板,整合到Django中,略做调整就可以使用。
后来我从网上找了适合自己题材的模板:http://sc.chinaz.com/tag_moban/Html.html
下图是我选用的模板(链接:http://sc.chinaz.com/moban/180521171540.htm):

image.png

将模板整合到项目相应app的templates中去:


image.png

5.根据网站需要添加新的数据类型Ueditor、ImageField

菜单的内容肯定是图文的,所以我整合了Ueditor
    content = UEditorField('内容', height=300, width=800, max_length=1024000000000,
                           default=u'', blank=True, imagePath="food/ueditor/images/",
                           toolbars='besttome', filePath='food/ueditor/files/')

菜单的索引页需要一张封面图片,所以我添加了图片上传功能;
    show_pic = models.ImageField('照片', upload_to="food/ueditor/images/", blank=True, null=True)

6.Windows下部署Django(Apache+mod_wsgi)

在自己的电脑上部署一个局域网内的菜谱系统;

开发步骤

1.根据详细步骤-2走完之后,你的系统里面已经有一个叫polls的应用,可以添加问题、选项、可以投票;

image.png

2.创建我自己的应用food

2.1.创建food应用

python manage.py startapp food

2.2.确定文章内容的字段、确定model Article,只有一个model,刚开始所有的类型都用CharField

create_time、update_time、title、sub_title、article_type、author、key_word、show_pic、content

2.3.检查app并创建相应的表

python manage.py migrate

2.4.激活model

settings.py中添加:'food.apps.FoodConfig',
准备sql:python manage.py makemigrations food
执行sql:python manage.py sqlmigrate food 0001
再次执行:python manage.py migrate

2.5.管理后台中编译一条记录,然后再让它在页面中显示,可以显示title就可以了
2.6.修改model Article的字段-show_pic

首先将封面照片show_pic = models.CharField(max_length=50, null=True)
改为show_pic = models.ImageField('照片', upload_to="food/ueditor/images/", blank=True, null=True)
改完之后要做以下操作,才能生效(每次改完model都要这么执行):
激活model-生成sql:python manage.py makemigrations food
激活model-执行sql:python manage.py sqlmigrate food 0002
激活model-再次执行:python manage.py migrate

这里要注意settings中的static_url/static_root/media_url/media_root要先设置好
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

文件上传后,会根据media_url和models.ImageField中的upload_to,确定图片的保存路径,如图:

image.png

2.7.上传的文件需要正常显示,必须设置好url:

    # 媒体文件想要通过ip地址访问到静态文件要做如下配置
    url(r'^media/(?P.*)$', serve, {"document_root": settings.MEDIA_ROOT}, name='media')

2.8.修改model Article的字段-content
2.8.1)下载DjangoUeditor:
python3: https://github.com/twz915/DjangoUeditor3/ (直接下载zip)

2.8.2)在项目的根目录新建extra_apps文件夹并将我们下载好的zip文件解压,
打开后找到 DjangoUeditor将DjangoUeditor直接拷贝到我们项目的extra_apps中,如图:

image.png

2.8.3)在settings.py文件中添加两行代码:如下

  sys.path.insert(0, os.path.join(BASE_DIR, 'apps'))
  sys.path.insert(0, os.path.join(BASE_DIR, 'extra_apps'))

2.8.4)通过pycharm 选中extra_apps文件夹点击鼠标右键选中菜单mark directory as 选择 sources root就可以变成上面的蓝色文件夹目录就可以了。

2.8.5)变成蓝色文件夹后就可以在settings.py 的INSTALLED_APPS中引入DjangoUeditor,如下:

INSTALLED_APPS = [
   'polls.apps.PollsConfig',
   'food.apps.FoodConfig',

   'django.contrib.admin',
   'django.contrib.auth',
   'django.contrib.contenttypes',
   'django.contrib.sessions',
   'django.contrib.messages',
   'django.contrib.staticfiles',
   'DjangoUeditor',
]

2.8.6)在的settings同级的urls.py中添加ueditor:

    path('ueditor/', include('DjangoUeditor.urls')),

2.8.7) 将content改成Ueditor

 content = UEditorField('内容', height=300, width=800, max_length=1024000000000,
                           default=u'', blank=True, imagePath="food/ueditor/images/",
                           toolbars='besttome', filePath='food/ueditor/files/')

改完之后要做以下操作,才能生效(每次改完model都要这么执行):
激活model-生成sql:python manage.py makemigrations food
激活model-执行sql:python manage.py sqlmigrate food 0002
激活model-再次执行:python manage.py migrate

2.8.8)问题:Ueditor的图片不展示
因为img的src 没有域名,确保DjangoUeditor中的views.py244行,数据返回的格式正确,如图:

image.png

2.9.Html迁移相关问题
注意1目录分布


image.png

注意2css的相对路径


注意3左侧li选中active效果

               
  • 全部菜单
  • 2.10.相关代码参考
    2.10.1food应用下的models

    import datetime
    from django.db import models
    # Create your models here.
    from django.utils import timezone
    from DjangoUeditor.models import UEditorField
    class Article(models.Model):
        create_time = models.DateTimeField('创建时间')
        update_time = models.DateTimeField('更新时间')
    
        title = models.CharField(max_length=100, null=True)
        sub_title = models.CharField(max_length=100, null=True)
        article_type = models.CharField(max_length=50, null=True)
        author = models.CharField(max_length=50, null=True)
        key_word = models.CharField(max_length=50, null=True)
        # show_pic = models.CharField(max_length=50, null=True)
        # show_pic = models.ImageField(upload_to="icons", height_field='url_height', width_field='url_width')
        show_pic = models.ImageField('照片', upload_to="food/ueditor/images/", blank=True, null=True)
    
        content = UEditorField('内容', height=300, width=800, max_length=1024000000000,
                               default=u'', blank=True, imagePath="food/ueditor/images/",
                               toolbars='besttome', filePath='food/ueditor/files/')
    
        def show_pic_url(self):
            if self.show_pic and hasattr(self.show_pic, 'url'):
                return self.show_pic.url
            else:
                return '/media/default/user.jpg'
    
        def __str__(self):
            return self.title
    
        def was_published_recently(self):
            now = timezone.now()
            return now - datetime.timedelta(days=1) <= self.update_time <= now
    
        was_published_recently.admin_order_field = 'update_time'
        was_published_recently.boolean = True
        was_published_recently.short_description = 'Published recently?'
    

    2.10.2food应用下的urls.py

    
    from food import views
    from food.views import page_not_found
    
    app_name = 'food'
    urlpatterns = [
        path('', views.IndexView.as_view(), name='index'),
        path('staple_food', views.StapleFoodView.as_view(), name='staple_food'),
        path('half', views.HalfOfMeat.as_view(), name='half'),
        path('big', views.BigMeat.as_view(), name='big'),
        path('vegetable', views.Vegetable.as_view(), name='vegetable'),
        path('soup', views.Soup.as_view(), name='soup'),
        path('cold', views.Cold.as_view(), name='cold'),
        path('/', views.DetailView.as_view(), name='detail'),
    ]
    
    
    # 定义错误跳转页面
    # handler403 = permission_denied
    handler404 = page_not_found
    # handler500 = page_error
    

    2.10.3food应用下的views.py

    # Create your views here.
    from django.shortcuts import render
    from django.views import generic
    from food.models import Article
    
    class IndexView(generic.ListView):
        template_name = 'food/index.html'
        context_object_name = 'latest_article_list'
    
        def get_queryset(self):
            """Return the last five published questions."""
            print(Article.objects.all())
            return Article.objects.all()
            # return Article.objects.filter(update_time__lte=timezone.now()).order_by('-update_time')[:5]
    
    class DetailView(generic.DetailView):
        model = Article
        template_name = 'food/detail.html'
    
    class StapleFoodView(generic.ListView):
        template_name = 'food/index.html'
        context_object_name = 'latest_article_list'
    
        def get_queryset(self):
            """Return the last five published questions."""
            print(Article.objects.all())
            return Article.objects.filter(article_type__contains="staple")
    
    class HalfOfMeat(generic.ListView):
        template_name = 'food/index.html'
        context_object_name = 'latest_article_list'
    
        def get_queryset(self):
            """Return the last five published questions."""
            print(Article.objects.all())
            return Article.objects.filter(article_type__contains="half")
    
    class BigMeat(generic.ListView):
        template_name = 'food/index.html'
        context_object_name = 'latest_article_list'
    
        def get_queryset(self):
            """Return the last five published questions."""
            print("大荤:")
            print(Article.objects.filter(article_type__contains="big"))
            return Article.objects.filter(article_type__contains="big")
    
    # 素菜
    class Vegetable(generic.ListView):
        template_name = 'food/index.html'
        context_object_name = 'latest_article_list'
    
        def get_queryset(self):
            """Return the last five published questions."""
            print(Article.objects.all())
            return Article.objects.filter(article_type__contains="vegetable")
    
    # 凉菜
    class Cold(generic.ListView):
        template_name = 'food/index.html'
        context_object_name = 'latest_article_list'
    
        def get_queryset(self):
            """Return the last five published questions."""
            print(Article.objects.all())
            return Article.objects.filter(article_type__contains="cold")
    
    # 汤
    class Soup(generic.ListView):
        template_name = 'food/index.html'
        context_object_name = 'latest_article_list'
    
        def get_queryset(self):
            """Return the last five published questions."""
            print(Article.objects.all())
            return Article.objects.filter(article_type__contains="soup")
    
    # 全局403、404、500错误自定义页面显示
    def page_not_found(request):
        return render(request, 'food/404.html')
    def page_error(request):
        return render(request, '500.html')
    def permission_denied(request):
        return render(request, '403.html')
    

    2.10.4food应用下的admin.py

    from django.contrib import admin
    
    # Register your models here.
    from food.models import Article
    
    
    class ArticleAdmin(admin.ModelAdmin):
        fields = ['create_time', 'update_time', 'title', 'sub_title', 'article_type', 'author', 'key_word', 'show_pic',
                  'content']
        list_display = ('create_time', 'update_time', 'title', 'sub_title', 'article_type', 'author', 'key_word', 'show_pic')
    
    admin.site.register(Article, ArticleAdmin)
    

    3.Windows下部署Django(Apache+mod_wsgi)

    详细步骤参考:https://www.jianshu.com/p/598d8b5fbee6

    注意的问题:
    1.Apache24安装后启动不起来
        1)、在cmd命令行进入Apache24/bin目录下
        2)、执行httpd -t命令
        3)、会看到错误提示:(仅仅是我的情况)AH00526:
     Syntax error on line 34 of F:/Apache/Apache/conf/extra/httpd-ahssl.conf:SSLProtocol: Illegal protocol 'TLSv1.3'
        4)、先进入到这个文件改34行,SSLProtocol -all +TLSv1.2 +TLSv1.3发现怎么改都没有用,看了下他的上一行
        把改成问题解决了
    
    2.mod_wsgi的安装、检查最好在cmd中,否则mod_wsgi-express module-config出现不了3条准确的记录;再pythonCharm的terminal执行只有2条记录;
    3.Django已经安装,而且pythonCharm运行的时候正常,但是windows下部署,apache的错误日志中提示Django未安装:
    windows下部署,注意pythoncharm中安装的django路径可能和python不一样;需要在命令行重新安装;注意安装的时候指定版本;
    

    效果图


    image.png
    image.png

    4.部署到linux

    TODO

    你可能感兴趣的:(Django从零搭建CMS(内容管理)系统)