zoukankan      html  css  js  c++  java
  • 用Django框架开发一个简单的企业网站

    创建框架

    django-admin startproject testdj    # 创建一个Django项目
    
    cd testdj
    
    python manage.py startapp my_app    # 创建一个app    

     配置文件

    在urls.py下添加app的路径

    from django.contrib import admin
    from django.urls import path, re_path, include
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        re_path(r'^', include('my_app.urls')),
    ]

    在app目录下新建urls.py ,用于配置这个app下所有的路由

    from django.urls import path, re_path
    from my_app import views
    
    urlpatterns = [
        re_path(r'^', views.index),
    ]

    在app内的views.py文件中写一个index处理函数

    from django.shortcuts import render, HttpResponse
    
    
    def index(request):
        return HttpResponse('你好啊')

    在项目目录下的settings.py内添加创建的app

    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'my_app',  # 新加入的一行
    ]

    测试一下

    python manage.py runserver 0.0.0.0:8000

    查看网页

    加入数据库

    新创建一个名叫my_app的mysql数据库,之后开启MySQL服务并在settings.py内配置数据库连接信息

    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',  # 数据库引擎
            'NAME': 'my_app',  # 数据库名,事先要创建
            'USER': 'root',  # 数据库用户名
            'PASSWORD': '123456',  # 密码
            'HOST': 'localhost',  # 主机
            'PORT': '3306',  # 数据库使用的端口
        }
    }

    配置好之后,运行manage命令更新数据表,Django会生成一些默认的表(原本是没有一张表的)

    python manage.py migrate

    结果报错

    raise MigrationSchemaMissing("Unable to create the django_migrations table (%s)" % exc)

    原因是:Django2.1不再支持MySQL5.5,必须5.6版本以上

    解决办法二选一:

    (1)Django降级到2.0

    pip install Django==2.0.0 -i https://pypi.douban.com/simple

    (2)MySQL升级

    我选择降级之后再更新表

     auth_user表示是保存后台管理员用户信息的

    现在创建一个超级管理员

    python manage.py createsuperuser

    按照命令行的提示,依次输入用户名,邮箱,密码(两次),其中邮箱可以为空(直接回车跳过)

    数据表中已经可以看到管理员的信息了

     在settings.py指定语音

    LANGUAGE_CODE = 'zh-hans'  # 指定语言(注意不要写错,否则无法启动服务器)
    
    TIME_ZONE = 'Asia/Shanghai'

    运行

    python manage.py runserver  

    打开后台管理平台

    http://127.0.0.1:8000/admin/

    一些简单的后台修改可以在admin.py内设置,例如标题和网页的title:

    from django.contrib import admin
     
    # Register your models here.
    admin.site.site_header = '我的后台管理'
    admin.site.site_title = '后台管理'

     

    如果涉及到更复杂的后台定制,例如模板布局,样式等就需要小折腾一番了,首先修改settings.py:

    TEMPLATES = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            # 优先使用项目模板路径
            'DIRS': [BASE_DIR + "/templates"],
            'APP_DIRS': True,
            'OPTIONS': {
                'context_processors': [
                    'django.template.context_processors.debug',
                    'django.template.context_processors.request',
                    'django.contrib.auth.context_processors.auth',
                    'django.contrib.messages.context_processors.messages',
                ],
            },
        },
    ]

    # 优先使用项目路径
    STATIC_URL = '/static/'
    STATICFILES_DIRS = (os.path.join(BASE_DIR, 'static'),)

    Django默认在当前项目目录static路径下查找静态文件(js,css等),templates路径下查找模板文件(html文件),例如后台的模板页面和样式文件;没有找到文件就会在Django的安装目录下调用。

     把static,templates两个文件夹复制到项目目录下

    加入数据模型类

    后台和数据库已经搞定,现在可以写我们网站的功能了;就写一个最简单的功能,发布企业新闻。打开app内的models.py文件,写两个数据模型类:

    from django.db import models
     
     
    class NewsClass(models.Model):
        name = models.CharField('分类名称', max_length=10)
     
        def __str__(self):
            return self.name
     
        class Meta:
            verbose_name = '资讯类别'
            verbose_name_plural = '资讯类别'
     
     
    class News(models.Model):
        # 默认添加
        # id = models.AutoField(primary_key=True)
        title = models.CharField('文章标题', max_length=30)
        content = models.TextField('文章内容')
        date = models.DateTimeField('发布时间')
        show = models.BooleanField('是否显示')
        news_class = models.ForeignKey(
            NewsClass, verbose_name='文章分类', on_delete=models.CASCADE)
     
        def __str__(self):
            return self.title
     
        class Meta:
            verbose_name = '资讯'
            verbose_name_plural = '资讯'

    关于数据模型类,可以理解为一张数据表,类里面的属性就是表的字段;id字段如果没有特殊要求可以不写,Django会自动创建。为了后台显示美观,这里我给字段和类都设置了中文别名;更多关于django的models模型类的常用数据类型和选项,留个链接https://www.jianshu.com/p/651aa9fe5d1a,有点数据库基础应该不难理解。

    写好数据模型类,运行manage命令,会在app目录migrations/和migrations/__pycache__/路径下各生成一个记录文件:

    python manage.py makemigrations

     运行更新数据表会多出两个

    python manage.py migrate

     对数据模型做了任何修改都要执行上面两个manage命令,同步数据库;如果直接在数据库里修改字段,删除表或者删除了之前的数据模型记录文件,可能会导致python manage.py migrate命令无法从数据模型更新表,不过也没关系,运行下面的命令:

    python manage.py sqlmigrate 'your_app_name' 0001查看框架自动生成的sql语句

    控制台显示0001记录文件转化的sql语句,复制sql语句可以直接在数据库中操作。

    现在有了新闻分类和新闻内容2张数据表,在后台注册这两个数据模型类,这样就能直接通过后台向数据表里添加数据了,打开app内admin.py:

    from web_app.models import *
         
    admin.site.register(News)
    admin.site.register(NewsClass)

    然后python manage.py runserver,打开后台

      点击添加咨询

     这里Django默认的大容量文本字段是通过一个textarea作为输入方式,所以我们还需要引入一个富文本编辑器,这里我推荐KindEditor(http://kindeditor.net/demo.php),配置简单,功能也齐全。

    下载KindEditor,将此静态文件放入static中,

     config.js内容

    KindEditor.ready(function(k) {
        window.editor = k.create('#id_content', {
            resizeType: 1,
            allowPreviewEmoticons: false,
            allowImageRemote: false,
             '700px',
            height: '400px',
        });
    })

    然后打开admin.py写入一个配置类,之后再与相关模型一起注册,然后现在的admin.py文件为

    from django.contrib import admin
    from my_app.models import *
    
    
    class NewsAdmin(admin.ModelAdmin):    # 写一个配置类
        list_display = ('title', 'news_class', 'date', 'show')
    
        class Media:
            # 在管理后台的相关HTML文件中加入js文件
            js = (
                '/static/kindeditor/kindeditor-all-min.js',
                '/static/kindeditor/lang/zh-CN.js',
                '/static/kindeditor/config.js',
            )
    
    
    admin.site.site_header = '我的后台管理'
    admin.site.site_title = '后台管理'
    
    admin.site.register(News, NewsAdmin)  # 与相关模型一起注册(必须写一起才行)
    admin.site.register(NewsClass)

    然后运行网站,打开后台就会发现,那个文本编辑器已经换成我们添加进去的KindEditor了,如下图

    编辑器自带的上传图片和文件选项还不能使用,我们需要配置一个post上传url;首先在项目settings.py内添加两个配置,设置上传文件目录:

    首先在项目settings.py内添加两个配置,设置上传文件目录:

    # 上传设置
    MEDIA_URL = '/static/upload/'
    MEDIA_ROOT = os.path.join(BASE_DIR, 'static/upload')

    在app文件夹内新建一个upload.py处理文件上传:

    import os
    import uuid
    import json
    import datetime
    from django.http import HttpResponse
    from django.conf import settings
     
    # 上传post请求地址
    # http://127.0.0.1:8000/upload_file/?dir=media
     
     
    def upload(request):
     
        # kindeditor图片上传返回数据格式说明:
        # {'error': 1, 'message': '出错信息'}
        # {'error': 0, 'url': '图片地址'}
     
        result = {'error': 1, 'message': '上传失败'}
        # input type="file" 中name属性对应的值为imgFile
        files = request.FILES.get('imgFile', None)
        type = request.GET['dir']  # 获取资源类型
        if files:
            result = process_upload(files, type)
        # 结果以json形式返回
        return HttpResponse(json.dumps(result), content_type='application/json')
     
     
    def is_ext_allowed(type, ext):
        # 根据类型判断是否支持对应的扩展名
        ext_allowed = {}
        ext_allowed['image'] = ['jpg', 'jpeg', 'bmp', 'gif', 'png']
        ext_allowed['flash'] = ['swf', 'flv']
        ext_allowed['media'] = ['swf', 'flv', 'mp3', 'wav', 'wma',
                                'wmv', 'mid', 'avi', 'mpg', 'asf', 'rm', 'rmvb', 'mp4']
        ext_allowed['file'] = ['doc', 'docx', 'xls', 'xlsx', 'ppt',
                               'htm', 'html', 'txt', 'zip', 'rar', 'gz', 'bz2', 'pdf']
        return ext in ext_allowed[type]
     
     
    def get_relative_file_path():
        # 获取相对路径
        dt = datetime.datetime.today()
        relative_path = '%s/%s/' % (dt.year, dt.month)
        absolute_path = os.path.join(settings.MEDIA_ROOT, relative_path)
        print(absolute_path)
        if not os.path.exists(absolute_path):
            os.makedirs(absolute_path)
        return relative_path
     
     
    def process_upload(files, type):
        dir_types = ['image', 'flash', 'media', 'file']
        # 判断是否支持对应的类型
        if type not in dir_types:
            return {'error': 1, 'message': '上传类型不支持[必须是image,flash,media,file]'}
     
        cur_ext = files.name.split('.')[-1]  # 当前上传文件的扩展名
        # 判断是否支持对应的扩展名
        if not is_ext_allowed(type, cur_ext):
            return {'error': 1, 'message': '扩展名不支持 %s类型不支持扩展名%s' % (type, cur_ext)}
     
        relative_path = get_relative_file_path()
        # linux中一切皆文件
        file_name = str(uuid.uuid1()) + '.' + cur_ext
        base_name = os.path.join(settings.MEDIA_ROOT, relative_path)
        # windows中的路径以分隔
        file_full_path = os.path.join(base_name, file_name).replace('\', '/')
        file_url = settings.MEDIA_URL + relative_path + file_name
     
        with open(file_full_path, 'wb') as f:
            if files.multiple_chunks() == False:  # 判断是否大于2.5M
                f.write(files.file.read())
            else:
                for chunk in files.chunks():
                    f.write(chunk)
     
        return {'error': 0, 'url': file_url}

    注意返回的json数据格式不要写错,否则KindEditor编辑器上传会报错。上传的文件我们保存在static/upload目录内,有了上传处理函数后,就可以在app的url.py内配置路由了:

    from web_app import upload as u
     
    # app url 配置
    urlpatterns = [
        re_path(r'^$', views.index),
        re_path(r'^upload_file/$', u.upload, name='upload'),
    ]

    在KindEditor的参数js内(config.js)添加上传url参数:

    // 上传请求路径
    uploadJson: '/upload_file/',

    完整config.js

    KindEditor.ready(function(k) {
        var csrf_token = document.getElementsByName('csrfmiddlewaretoken')[0].value;
        window.editor = k.create('#id_content', {
            resizeType: 1,
            allowPreviewEmoticons: false,
            allowImageRemote: false,
            // 上传请求路径
            uploadJson: '/upload_file/',
             '700px',
            height: '400px',
            // 处理csrf验证
            extraFileUploadParams: {
                csrfmiddlewaretoken: csrf_token
            },
        });
    })

    由于Django自带CSRF验证(有兴趣的同学可以了解下:https://www.jianshu.com/p/a178f08d9389),所以上传图片失败了,但是有2种方法解决:

    •     在settings.py内注释掉'django.middleware.csrf.CsrfViewMiddleware',关闭CSRF验证。
    •     post上传请求头内添加CSRF参数(推荐方法)

    我选择了第一张方法,然后上传图片成功了

     前台数据展现

    views.py内写一个处理函数

    from django.shortcuts import render, HttpResponse
    from my_app.models import *
     
    def news_content(request):
        # http://127.0.0.1:8000/news/?id=1
        id_num = request.GET.get('id')
        context = {}
        try:
            context['News'] = News.objects.get(id=id_num)
            context['title'] = context['News'].title
        except News.DoesNotExist:
            context['News'] = '404'
            context['title'] = '404'
            return render(request, 'my_app/article.html', context)
        return render(request, 'my_app/article.html', context)

    根据url内id参数查询新闻内容,然后返回一个模板文件与dict对象;接着在templates路径下创建我们的html模板文件:

    (这里我用Bootstrap可视化布局系统简单演示一下)

     这些网页布置文件全在templates下的my_app内

    {% include "my_app/head.html" %}
    <div class="container-fluid">
        <div class="row-fluid">
            <div class="span12">
                <h3>{{News.title}}</h3>
                {% autoescape off %}
                {{News.content}}
                {% endautoescape %}
            </div>
        </div>
    </div>
    {% include "my_app/foot.html" %}

    head.html

    <!DOCTYPE html>
    <html lang="en">
     
    <head>
        <meta charset="UTF-8">
        <title>{{title}}</title>
        <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
        <link rel="stylesheet" href="/static/bootstrap/css/bootstrap-combined.min.css">
    </head>
     
    <body>

    url.py中加上路由:

    from django.urls import path, re_path
    from my_app import views
    from my_app import upload as u

    urlpatterns = [
    re_path(r'^$', views.index),
    re_path(r'^news/$', views.news_content),
    re_path(r'^upload_file/$', u.upload, name='upload'),
    ]

  • 相关阅读:
    基于数组的完全二叉树
    二叉树链式存储
    小程序-启动-问题1
    小程序----textarea层叠问题
    小程序中某个页面生成二维码,并下载二维码图片
    vue项目启动后自动在浏览器打开
    给卡片加角标
    布局图片和文字垂直对齐
    小程序npm包管理
    从浏览器输入域名到加载完页面的流程
  • 原文地址:https://www.cnblogs.com/dummersoul/p/12204597.html
Copyright © 2011-2022 走看看