django从0到1搭建网站

曾经有人说我前端很水,那么在这一系列文章中我打算把先后端融合在一块儿来作一次网站的全面重构,但愿能够把刚刚入行的同窗带上正途php

 

请尊重原创,转载请注明来源网站www.shareditor.com以及原始连接地址html

聊聊工程

现在,数据科学家已经逐渐取代如今的“软件工程师”成为IT行业的主流职业,和“全民都在聊人工智能”同样,可能所有IT工做者都要每天研究算法、琢磨模型、跑数据、调参数、跑数据、调参数,那些被淘汰的“软件工程师”会真的成为民工同样的行业,可是我以为任何算法都离不开工程实现,再好的模型没有底层架构的支撑和上层产品应用的展示也没法发挥做用,因此对于一个技术人士,不擅长工程终难把能力发挥到极致。随着中国和国外前沿科技的接轨,未来必定是小创业团队成为主流,一个小创业团队更喜欢算法+工程的全能型人才,跟着我一块儿学习进步,你未来也许就会是其中一个。前端

 

聊聊重构

提及重构,不少人都有感慨,由于只有当遇到比较大的问题的时候才会考虑重构,好比技术人员流动大致使代码中风格百出,百花齐放,无用代码一大堆不敢删,奇葩逻辑遍地皆是却没有一行注释、一篇文档。在这种无奈状况下,咱们不得已选择了重构,寄但愿于解决全部问题,但每每代价比收益高出一个数量级,不少人由于重构被迫出局。但重构这件事情是一件必经之路,任何一个产品从诞生到成熟都会经历几回重构,由于没有人能在最初的时候就预示到最终的逻辑(若是能预示那何须有最初呢),就算像BAT这样成熟的公司,他们内部的系统也是平均两年作一次重构。回过头来讲一下个人网站重构的初衷:1)我也是不断成长的,做为一个想作全栈的工程师来讲,新思路总想去尝试;2)不少关注个人网友以为我以前写的教程总有意犹未尽的感受,但愿能深刻写一点;3)php终究不是世界上最好的语言(此处可能引起战争),用来用去以为仍是迁移python为好,也和咱们的机器学习知识作个融合;python

 

技术栈选择

首先说语言。我曾经说过,语言只是工具,每门语言都有它存在的理由,它擅长用在什么地方就用在什么地方,不擅长的不要勉强,不歧视、不在一棵树上吊死、哪一个行就上哪一个。后端语言我选择python,由于python是社区最活跃的语种之一且呈上升趋势,另外也是大数据与人工智能方向的主流语言。web框架我选择django,由于它更专业更强大,扩展性强,社区也更活跃。前端框架我选择直接用django模板渲染,没有选择angular等前端框架,由于seo不友好mysql

 

服务端容器选择

在tomcat、apache httpd、nginx等web服务器下游,须要部署python的应用服务器容器,我选择uwsgi,它相似于nginx,经过一个守护进程把不一样的http请求转交给子进程并发处理,而且支持多线程的方式,性能较高,更重要的,django会自动帮咱们生成wsgi的配置,自然对uwsgi友好nginx

 

总结

开篇就讲这么多,主要仍是得看后面个人重构过程,咳咳!出发!git

http://www.shareditor.com/blogshow/?blogId=126github

安装开发和运行的基本环境

首先,python是必须的,咱们选择python2.7,没有安装能够根据不一样的操做系统安装,若是是rhel或centos能够用yum  install python,若是是ubuntu能够用apt-get install python,若是是mac能够用brew install python,若是以上都不行能够直接下官方包安装(https://www.python.org/downloads/)web

而后,安装django相关组件(当前最新版是1.11):算法

pip install django

安装web容器:

pip install uwsgi

小技巧:若是使用pip install安装库比较慢,能够用豆瓣的镜像,方法相似下面:

pip install django -i http://pypi.douban.com/simple --trusted-host pypi.douban.com

 

建立开源代码库

在github中建立仓库shareditor,并在本地建立空仓库提交

github库在:https://github.com/warmheartli/shareditor

本地仓库以下:

[lichuang@localhost:~/Developer/shareditor $] ls README.md [lichuang@localhost:~/Developer/shareditor $] pwd /Users/lichuang/Developer/shareditor

 

建立django工程

在安装django时已经自动帮咱们安装了django-admin工具,执行以下命令自动建立一个完整的工程目录(其中最后一个参数是工程目录,倒数第二个参数是工程名):

django-admin startproject shareditor /Users/lichuang/Developer/shareditor

这时可以找到自动建立的manage.py文件(一个工具脚本,不须要修改),和工程总目录shareditor(里面包含了配置文件settings.py、总路由配置urls.py、wsgi协议配置文件wsgi.py)

下面咱们在这个工程里建立咱们网站app:

django-admin startapp web

咱们看到它自动建立了web目录,而且自动帮咱们组织了一些文件,包括:

admin.py:数据库表的后台管理类通常定义在这里

apps.py:这个app的配置信息,这个文件通常不动

migrations目录:存储数据库迁移相关的临时文件,不须要动

models.py:和数据库对应的model类通常定义在这里

tests.py:自动化脚本

views.py:视图层脚本,我通常会把控制逻辑写到这里

这些文件全都看不懂也没有关系,到如今为止,咱们的网站已经能够运行了,执行:

python manage.py runserver

咱们能够看到一些提示,直接访问http://127.0.0.1:8000/就能够访问网页了,以下:

上面的页面是django展现的默认页面,下面咱们稍做修改来看看django框架是怎么按照咱们的指示工做的

 

helloworld

修改web/views.py,增长以下函数:

from django.http import HttpResponse def index(request): return HttpResponse('Hello World!')

这仅仅是定义一个函数,然并卵

请尊重原创,转载请注明来源网站www.shareditor.com以及原始连接地址

咱们来修改一下咱们的路由规则,修改shareditor/urls.py,把内容改为:

from web import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^$', views.index) ]

下面咱们从新执行python manage.py runserver,并打开浏览器看看是否是看到了高大上的Hello World!

 

让网站更专业

上面执行的python manage.py runserver实际上只是django的一个用于开发和调试的方法,它只是一个进程一个线程在运行,没法支持网站的高并发访问,下面咱们介绍一下如何部署一个专业的网站。

首先咱们配置好咱们的web容器,在shareditor目录下建立uwsgi.ini,内容以下:

[uwsgi] chdir = /Users/lichuang/Developer/shareditor http = 127.0.0.1:8080 http-keepalive = 1 module = shareditor.wsgi:application master = true processes = 4 daemonize = /Users/lichuang/Developer/shareditor/logs/uwsgi.log disable-logging = 1 buffer-size = 16384 harakiri = 5 post-buffering = 8192 post-buffering-bufsize = 65536 pidfile = /Users/lichuang/Developer/shareditor/logs/uwsgi.pid enable-threads = true single-interpreter = true

这里的目录要随着你部署的目录作相应修改

由于logs目录还不存在,因此咱们手工mkdir建立一个

下面执行启动命令:

uwsgi --ini shareditor/uwsgi.ini

这时咱们能够查看一下logs/uwsgi.log文件,若是没有异常信息说明网站已经部署成功了,咱们ps ux|grep uwsgi看一下进程:

lichuang 13390   0.4  0.0  2425088    300 s004  S+   10:19下午   0:00.00 grep --color uwsgi lichuang 13307 0.0 0.0 2491336 924 ?? S 10:18下午 0:00.00 uwsgi --ini shareditor/uwsgi.ini lichuang 13306 0.0 0.0 2491336 2540 ?? S 10:18下午 0:00.00 uwsgi --ini shareditor/uwsgi.ini lichuang 13305 0.0 0.0 2491336 2520 ?? S 10:18下午 0:00.00 uwsgi --ini shareditor/uwsgi.ini lichuang 13304 0.0 0.0 2491336 2484 ?? S 10:18下午 0:00.00 uwsgi --ini shareditor/uwsgi.ini

能够看到启动了4个进程,其中一个守护进程用来接收和分发请求,3个子进程(对应配置文件里的processes = 4)用来处理请求

这时咱们打开浏览器访问:http://127.0.0.1:8080/又能看到Hello World!了

 

高可用性部署(新手可略过)

另外为了让咱们的网站具备高可用性(高可用就是挂掉一台机器不影响服务),一台机器启动服务还不行,咱们至少要部署两台彻底对等的web服务来同时提供服务,那么用户在浏览器里访问时到底访问的是哪一个机器呢?这里有两种实现方案,一种是配置DNS记录,同一个域名对应多个ip,那么当一个ip不可用时浏览器会自动尝试另外的ip,还有一种方法就是经过稳定的代理服务器(如nginx、apache httpd等)来配置成一个负载均衡代理,对外暴露的一个ip,对内链接到多台web服务器

http://www.shareditor.com/blogshow/?blogId=127

建立和连接数据库

首先,咱们须要有一个mysql的服务,你能够选择本身安装启动一个mysql服务,我选择了阿里云的云数据库RDS(和本地搭建没有区别,收费但不贵),我建立了一个数据库名叫db_shareditor(若是本地搭建的mysql,执行命令是create database db_shareditor)

下面咱们配置咱们的网站工程来链接这个数据库,修改shareditor/settings.py里的DATABASE改为以下:

DATABASES = {
    'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'db_shareditor', 'USER': 'username', 'PASSWORD': 'password', 'HOST': 'hostip', 'PORT': '3306', 'OPTIONS': { 'sql_mode': 'traditional', } } }

这里的USER、PASSWORD、HOST、PORT都配置成你本身的,而后咱们来检测一下数据库配置是否正确

[lichuang@localhost:~/Developer/shareditor $] python manage.py check System check identified no issues (0 silenced).

看到这样的信息说明咱们的配置没有问题,不然会抛出异常,这时咱们根据异常信息再追查问题

 

建立model并自动生成数据库表

这里解释一下什么是model,model就是数据库表在内存里的数据结构,好比某个数据库表有A和B两个字段,那么它对应的model通常也会写成A和B两个成员,这样咱们在代码里操做model的实例就是在操做数据库

每一个model的设计都须要精心打磨,咱们首先建立一个BlogPost的model,修改web/models.py,增长以下类定义:

class BlogPost(models.Model): title = models.CharField(max_length=255, verbose_name='文章标题') body = models.TextField(verbose_name='文章内容') create_time = models.DateTimeField(verbose_name='建立时间')

这个类实际上定义了一个数据库的结构,下面咱们用django工具来自动根据这个结构定义生成对应的数据库表,执行:

python manage.py migrate

这时咱们再看一下数据库多出了这些数据库表

auth_group
auth_group_permissions
auth_permission
auth_user
auth_user_groups
auth_user_user_permission
django_admin_log
django_content_type django_migrations django_session

这里比较奇怪的是怎么多出了这么一批数据而没有找到咱们的blogpost呢?这是由于settings.py里的INSTALLED_APPS默认安装了一些其余的玩意,而并无安装咱们的web这款app,好,那如今咱们暂时先保留默认安装的app(之后有用),把咱们的web添加进去,以下:

INSTALLED_APPS = [
    'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes' 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'web', ]

如今咱们从新生成migrate文件并建立数据库表,执行:

python manage.py makemigrations
python manage.py migrate

这时再看数据库表多出了web_blogpost(django会自动用app名字小写加下划线加model名的小写来做为数据库表的名字,实际上数据库表名咱们也是能够本身来配置的,感兴趣本身google一下吧)

 

建立有关联关系的数据库表

咱们的每篇文章都会有一个类别(subject,如大数据、全栈技术等),每一个类别会对应多篇文章,也就是1对多的关系,那么咱们能够利用django的models里的外键类型来关联,以下:

class Subject(models.Model): name = models.CharField(max_length=255, verbose_name='类别名称') introduce = models.CharField(max_length=255, verbose_name='类别简介') image = models.ImageField(verbose_name='类别图片') class BlogPost(models.Model): title = models.CharField(max_length=255, verbose_name='文章标题') body = models.TextField(verbose_name='文章内容') create_time = models.DateTimeField(verbose_name='建立时间') subject = models.ForeignKey(Subject, verbose_name='类别', null=True)

咱们从新执行:

python manage.py makemigrations
python manage.py migrate

这时再看数据库表多出了web_subject,同时web_blogpost也自动多出了一个subject_id字段

有人问了,这用不用外键有什么关系呢,手工写好一个subject_id字段,而后在代码逻辑里就把这个字段做为查询subject表的key不就好了吗?看来该是介绍IDE的时候了,我来给你们介绍一款棒棒的开发工具PyCharm,具体安装方法本身去百度,我如今装的是PyCharm 2017.1.4版本,记得必定要配置好Project Interpreter为系统里安装好django的那个python环境

下面见证奇迹的时刻到了,用PyCharm打开咱们上面的shareditor工程,并打开views.py文件,咱们来编辑以下一段代码:

个人天啊!好强大有木有!当咱们输入几个字母前缀的时候,它会把咱们用外键关联的类的各类方法都给咱们列出来,不再用苦逼的查文档了

 

建立多对多关系的数据库表

咱们的每篇文章都会有多个标签(tag, 如:从0到1搭建我的网站、本身动手作聊天机器人等),每一个标签会对应多篇文章,也就是多对多的关系,那么咱们能够利用django的models里的ManyToMany类型来关联,咱们添加Tag类以下:

class Tag(models.Model): name = models.CharField(max_length=255, verbose_name='标签名称')

并为BlogPost类添加以下成员:

tags = models.ManyToManyField(Tag, verbose_name='标签')

咱们从新执行:

python manage.py makemigrations
python manage.py migrate

这时再看数据库表多出了web_tag和web_blogpost_tag两个表,这里的web_blogpost_tag其实是一个关系表,也就是说,BlogPost类多了tags成员,但web_blogpost表里并无多任何字段,但当咱们在PyCharm中输入tags前缀的时候依然会看到相关提示

 

总结

这一节咱们介绍了数据库表和model之间的关系,以及一对多、多对多关系的使用,下一节咱们来继续讨论利用model对数据库作读写

http://www.shareditor.com/blogshow/?blogId=128

django-admin的帐户管理

当咱们直接打开http://127.0.0.1:8000/admin时,虽然可以看到管理后台登录界面,可是咱们没有帐号密码是没法登录的,须要咱们初始化一个超级用户,那么方法如何呢?咱们能够经过执行python manager.py输出的提示来找到createsuperuser这个命令,执行:

python manage.py createsuperuser

按照提示输入帐号、邮箱、密码,而后再次进入http://127.0.0.1:8000/admin就能够登录了

登录进入后咱们看到了Group和Users两个管理项,这实际上对应着数据库里的auth_group和auth_user表,在Users里能看到咱们刚刚建立的超级用户,在这里咱们能够添加新的用户,并为不一样用户配置不一样权限

 

配置admin管理数据库

还记得上一节咱们建立的三个Model及其数据库表吗?BlogPost、Subject、Tag,那么怎么才能在django-admin管理后台管理这三个表的内容呢?

修改web/admin.py,添加以下内容:

from django.contrib import admin from .models import BlogPost class BlogPostAdmin(admin.ModelAdmin): list_display = ('title', 'create_time', 'subject', 'tags') admin.site.register(BlogPost, BlogPostAdmin)

从新登录http://127.0.0.1:8000/admin管理页面,咱们看到:

点进去能够看到文章的管理页面,由于咱们在BlogPost这个model里设置的subject和tags字段不能够为空,所以咱们须要提早添加类别和标签,下面咱们再完善一下Subject和Tags的管理类,以下:

class SubjectAdmin(admin.ModelAdmin): list_display = ('name',) class TagAdmin(admin.ModelAdmin): list_display = ('name',) admin.site.register(Subject, SubjectAdmin) admin.site.register(Tag, TagAdmin)

这时咱们再尝试在管理页面新建一个Subject、一个Tag、一个BlogPost吧,建好以后能够在后台数据库直接查看到数据已经写到了数据库中

 

管理界面的定制化

爱漂亮的同窗可能会发现后台管理界面还不够漂亮和友好,好比页面顶部写的“Django administrator”能不能换成“SharEDITor管理后台”,好比管理首页里的“WEB”能不能改为“网站”,“Blog posts”能不能改为“文章”,另外咱们在新建BlogPost的时候,类别和标签这两项里写的是“Subject object”和"Tag object",都不知道具体信息,下面咱们来各个击破作一下定制

首先咱们修改web/models.py,为Subject类添加以下成员:

class Meta: verbose_name_plural = '类别' def __unicode__(self): return self.name

再为Tag类添加以下成员:

class Meta: verbose_name_plural = '标签' def __unicode__(self): return self.name

再为BlogPost类添加以下成员:

class Meta: verbose_name_plural = '文章' def __unicode__(self): return self.title

解释一下,这里的verbose_name_plural就是在这个结构在管理页面里的展现名称,__unicode__就是这个结构里每个对象的展现形式,不用多说,直接看一下你的管理页面的效果就知道了

管理页面总标题由于是django-admin自身的内容,所以作定制有些复杂些,此处新手能够略过

请尊重原创,转载请注明来源网站www.shareditor.com以及原始连接地址

在根目录下建立以下目录templates/admin,并新建base_site.html文件,内容以下:

{% extends "admin/base.html" %} {% load i18n %} {% block title %}{{ title }} | {% trans 'SharEDITor后台管理' %}{% endblock %} {% block branding %} <h1 id="site-name">{% trans 'SharEDITor后台管理' %}</h1> {% endblock %} {% block nav-global %}{% endblock %}

修改shareditor/settings.py文件,在TEMPLATES  =>  DIRS配置项中添加'templates',这样就能够自动找到模板目录了,实际上这里的admin/base_site.html是重写了django-admin的源码。从新打开后台管理界面看下效果吧

 

图片管理(高级内容,新手略过)

咱们在新建一个类别的时候要为image字段选择一张图片,咱们看到图片实际上上传到了根目录下。这种方式存在一些问题:1)若是要在网站中展现这张图片须要为其单独指定路由;2)若是网站多机部署没法实时同步数据;3)若是图片很大,会耗费不少带宽,响应慢

为了解决如上问题,咱们引入阿里云的对象存储OSS服务(收费,但不贵,这里不是帮阿里云打广告,可是阿里云确实作的比较好),它的优势是有CDN加速,也就是不一样地域都有镜像,访问快,并且价格低廉,可比一样的网络带宽便宜多了

OSS的使用请见官方文档,我这里直接贴代码,懂的能够参考,不懂的能够直接用

首先要在阿里云的OSS中建立一个Bucket,如shareditor-shareditor,读写权限必定要选择“公共读”

其次要安装oss2库,执行:

pip install oss2

而后在咱们代码的根目录建立commons目录(用于放置全部公共组件),并在其中建立一个空的__init__.py(做为lib的目录都要有这个文件,不然没法import),并建立ossutils.py文件,内容以下:

# -*- coding: utf-8 -*- import oss2 import time AccessKeyId = '你的AccessKey' AccessKeySecret = '你的AccessKey密码' Endpoint = 'oss-cn-beijing.aliyuncs.com' InternalEndpoint = 'oss-cn-beijing-internal.aliyuncs.com' def upload_oss(bucket_name, file_name, bytes_content): """ :param bucket_suffix: 区分测试环境和线上环境 :param file_name: 会自动添加时间戳 :param bytes_content: 二进制的文件内容 :return: 外网能够访问的url """ auth = oss2.Auth(AccessKeyId, AccessKeySecret) bucket = oss2.Bucket(auth, Endpoint, bucket_name) file_path = 'dynamic/' + str(int(time.time())) + '_' + file_name result = bucket.put_object(file_path, bytes_content) if result.status == 200: return 'http://' + bucket_name + '.oss-cn-beijing.aliyuncs.com/' + file_path else: return None

下面咱们重载Subject的image的上传逻辑,修改web/admin.py,引入ossuitls:

from commons.ossutils import upload_oss

声明BucketName变量下面会用到:

BucketName = 'shareditor-shareditor'

修改SubjectAdmin类,添加以下方法:

def save_model(self, request, obj, form, change): if 'image' in request.FILES: image_name = request.FILES['image'].name image_content = request.FILES['image'].read() url = upload_oss(BucketName, image_name, image_content) if url: obj.image = url super(SubjectAdmin, self).save_model(request, obj, form, change)

这时咱们从新修改一个类目,从新上传图片,咱们发现图片已经再也不保存到本地文件了,而在阿里云的OSS里找到了上传的文件,而在咱们的数据库里存储了这个图片在阿里云OSS中的url,能够直接访问

 

总结

有关admin管理后台的内容以上这些基本够用了,剩下的就是根据你的业务逻辑去设计本身的表结构,发挥自身的主动性啦

 

http://www.shareditor.com/blogshow/?blogId=129

相关文章
相关标签/搜索