【详解】Python专题开发

使用Python从脚本到专题开发,才知道为什么会有人说Python大法好,别的都去死!

因为相较于JAVA,开发起来要爽太多,方方面面……


【需求】

1. 本例,因为着急上线一个新的活动版块,所以使用Python来开发管理后台。

2. 功能很简单,增删改查都实现即可。

3. 显示部分要有分页。


【Python专题分析】

Python专题(内部这么叫),就是使用Python来开发一个网站。也就是Python Web应用开发。

项目结构如图所示:

【详解】Python专题开发_第1张图片

目录结构从最大的文件夹开始,从上往下走------

moyoyo_zt文件夹和manage.py文件,前者是工程代码所在,后者是运行工程关键文件。

moyoyo_zt文件夹又分三个部分,硬代码所在文件夹jisumai,前台页面代码templates,其他四个文件__init__.py、settings.py、urls.py、wsgi.py。

也就是说,除了我们比较熟悉的硬代码和前台页面代码,就剩下5个文件需要格外注意:manage.py、__init__.py、settings.py、urls.py、wsgi.py。

我们一个个阐述。

【manage.py】

我们运行工程的时候运行的就是这个Python文件。

#!/usr/bin/env python
import os
import sys

if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "moyoyo_zt.settings")

    from django.core.management import execute_from_command_line

    execute_from_command_line(sys.argv)
 

使用 Django 时, 你必须告诉它你使用的是哪个 settings . 要做到这一点,使用环境变量DJANGO_SETTINGS_MODULE.


【__init__.py】

空文件。

存在该文件是因为:一个包是一个带有特殊文件 __init__.py 的目录。

__init__.py 文件定义了包的属性和方法。其实它可以什么也不定义;可以只是一个空文件,但是必须存在。

如果 __init__.py 不存在,这个目录就仅仅是一个目录,而不是一个包,它就不能被导入或者包含其它的模块和嵌套包。

也就是说,目录下的.py文件需要import引入包的时候,就需要在目录中有这样一个__init__.py

所以我们可以看到,在jisumai 的目录下也有这样一个__init__文件

【详解】Python专题开发_第2张图片


【settings.py】

这个文件包含了所有有关这个Django项目的配置信息

均大写:   TEMPLATE_DIRS , DATABASE_NAME , 等.

最重要的设置是 ROOT_URLCONF,它将作为 URLconf 告诉 Django 在这个站点中那些 Python的模块将被用到。

不过这里我们的这一项放到了urls.py文件中

ROOT_URLCONF = 'moyoyo_zt.urls'   

使用 Django 时, 你必须告诉它你使用的是哪个 settings .


【urls.py】

定义了链接相关

from django.conf.urls import patterns, include, url

from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
    # Examples:
    #url(r'^$', 'moyoyo_zt.views.home', name='home'),
    #url(r'^blog/', include('blog.urls')),

    url(r'^jisumai/', include('moyoyo_zt.jisumai.urls')),
)


【wsgi.py】

wsgi(Python Web Server Gateway Interface)服务器网关接口,

是Python语言定义的web服务器和web服务程序或者框架之间的一种简单而通用的接口。

import os
import sys
sys.path.append("/usr/local/django_apps/moyoyo_zt/")
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "moyoyo_zt.settings")

from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()


大致了解了Python专题的工程结构,其实可以看出,Python专题依然是典型的MVC模式,前台页面,后台代码,数据库,配置文件。。。

其实和springmvc挺像的,但是简单了许多!


接下来正式开始开发,以实际开发的时间顺序来进行阐述----------


【新建数据库】

因为是新的模块,什么都没有。

最核心的数据需要有一个存放的地方,所以先要建立数据库!~

创建数据库的语句需要学会手写,因为Navicat这样的软件只能在windows环境下使用,远程的Linux服务器根本没有新建数据库的软件和界面。

这种情况下,就需要手写SQL语句来对数据库进行操作与更改。


新建数据库并添加索引的语句:

 
  
CREATE TABLE QUICK_SELLING_GOODS(
    ID  int(11) NOT NULL AUTO_INCREMENT,
    SELLING_GOODS_ID  int(11) NOT NULL ,
    NAME  varchar(100) NOT NULL ,
    GAME_NAME  varchar(100) NOT NULL ,
    ORI_PRICE  int(11) NOT NULL ,
    COMMENTS  varchar(500) NOT NULL ,
    DETAILS  varchar(100) NOT NULL ,
    STATUS  smallint(6) NULL ,
    PRIMARY KEY (ID)
)ENGINE=INNODB DEFAULT CHARSET=utf8;
CREATE INDEX IX_QUICK_SELLING_GOODS_SELLING_GOODS_ID on QUICK_SELLING_GOODS (SELLING_GOODS_ID) 

【说明】
1. 尽量手写
2. 建表语句后加一条
 
  
ENGINE=INNODB DEFAULT CHARSET=utf8;
指定编码格式
3. SELLING_GOODS_ID需要加索引。
语句的写法是:
 
  
CREATE INDEX IX_QUICK_SELLING_GOODS_SELLING_GOODS_ID on QUICK_SELLING_GOODS (SELLING_GOODS_ID) 
其中
 
  
 
  
IX_QUICK_SELLING_GOODS_SELLING_GOODS_ID
是索引名,命名规则是IX_数据库名_字段名。(IX是INDEX的缩写)
这样命名使索引名唯一。


运行.sql为扩展名的SQL文件来建立数据表。


【修改数据库】

遇到需要修改数据库的情况。(字段DETAILS长度不够,需要从100扩展到500)

SQL修改语句如下:

ALTER TABLE QUICK_SELLING_GOODS MODIFY COLUMN DETAILS  varchar(500) not null;

原先是这样写的:
ALTER TABLE QUICK_SELLING_GOODS MODIFY COLUMN DETAILS  varchar(500);
发现这样写会把DETAILS的非空属性改了。
所以要补上not null。



【django工程增删改查 之 查】
也就是把数据库的中数据显示在页面上。

前端页面:backend.html
显示部分代码如下:

width=1000 height=500 border="1">
  bgcolor="lightgrey" height=10>
                                                
        {% for sellinggoods in goodslist %}
                                                                                    {% endfor %}

width=150>商品ID width=500>商品名称 width=100>游戏名称 width=100>原价 width=150>操作
{{sellinggoods.SELLING_GOODS_ID}} {{sellinggoods.NAME}} {{sellinggoods.GAME_NAME}} {{sellinggoods.ORI_PRICE}}   href="javascript:void(0)" οnclick="javascript:gotochange({{sellinggoods.SELLING_GOODS_ID}})">修改   href="javascript:void(0)" οnclick="javascript:confirm_del({{sellinggoods.SELLING_GOODS_ID}})">删除

用一个table来显示所有内容。
关键部分的循环遍历显示,与java的原理其实是一样的。只不过语法不同而已!

{% for sellinggoods in goodslist %}
{{sellinggoods.SELLING_GOODS_ID}}
{% endfor %}

回顾一下Java中的这部分代码

			
       
         
         ${message.username}
         ${message.content}
         ${message.reply}
    
使用的是forEach标签。


后端代码:
使用Java实现显示数据时,后端代码是这样的结构。
【详解】Python专题开发_第3张图片

即,典型的MVC架构模式。
而Python中这部分代码的架构是这样的:
【详解】Python专题开发_第4张图片
红框是显示功能需要的部分。

我们一一说明:
__init__.py 依然是空文件,作用不再赘述。
models.py 中定义了数据类,即,把要显示的数据封装成类,方便在代码中传递。
from django.db import models

class SellingGoods(models.Model):
    ID = models.AutoField(primary_key=True)
    SELLING_GOODS_ID = models.IntegerField()
    NAME = models.CharField(max_length=100)
    GAME_NAME = models.CharField(max_length=100)
    ORI_PRICE = models.IntegerField()
    COMMENTS = models.CharField(max_length=500)
    DETAILS = models.CharField(max_length=100)
    STATUS = models.IntegerField()

    class Meta: 
        db_table = "QUICK_SELLING_GOODS"

urls.py 相当于java中的controller-action-config.xml
【详解】Python专题开发_第5张图片

from django.conf.urls import patterns, include, url
from moyoyo_zt.jisumai.views import *

from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
    # Examples:
    # url(r'^blog/', include('blog.urls')),

    url(r'^$',index),
    url(r'^index',index),
    url(r'^details',details),
    url(r'^backend',backend),
    url(r'^delete',delete),
    url(r'^gotoadd',gotoadd),
    url(r'^add',add),
    url(r'^gotochange',gotochange),
    url(r'^change',change),
    url(r'^writedate',writedate),
    url(r'^readdate.post',readdate),
)
就是链接与方法的对应配置。

views.py 相当于Java中的那些Controller,各种业务代码都在这里。
显示部分的代码
def backend(request):
    '''进入管理后台首页'''
       params = {}
       goodslist=SellingGoods.objects.all()
       params['goodslist'] = goodslist
       c = Context(params)
       return TemplateResponse(request, "jisumai/backend.html", c, content_type)


如此,就可以实现显示数据的功能了!
为什么没有数据库连接相关代码呢?因为数据库的连接早在settings.py中就已经写好了。

有这么清晰简单的代码结构,使用python开发的效率当然很高。


【分页的实现】
显示完数据之后,就是将数据分页显示。
Python中实现分页更加简单,几乎是安装零件一样的。
因为Django提供了一个分页器类Paginator(django.core.paginator.Paginator),可以很容易的实现分页的功能。

前端代码:
id="page" class="page"> {{ goodslist.number }}/{{goodslist.paginator.num_pages }}     {% if goodslist.has_previous %} href="backend?pageNo={{goodslist.previous_page_number}}" class="w50">上一页 {%else%} class="notFlip w50">class="gray">上一页 {% endif %} {% autoescape off %}{{pageHtml}}{% endautoescape %}     {% if goodslist.has_next %} class="w50" href="backend?pageNo={{goodslist.next_page_number}}">下一页 {%else%} class="notFlip w50">class="gray">下一页 {% endif %}


views.py 后端代码
from django.core.paginator import Paginator
paginator = Paginator(goodslist, 3)
goodslist = paginator.page(pn)
只需要把这三行代码写进去就可以了。

params = {}
goodslist=SellingGoods.objects.all()
paginator = Paginator(goodslist, 3)
goodslist = paginator.page(pn)
params['goodslist'] = goodslist
其实整体看,就像在返回的goodslist上加了分页功能似的。

【django工程增删改查 之 删】

添加删除商品的功能。

后端代码其实很简单
def delete(request):
    '''删除商品操作'''
    id = request.GET.get('id')
    p = SellingGoods.objects.get(SELLING_GOODS_ID=id)
    p.delete()
    return HttpResponseRedirect('backend.html')
就是把商品id传过去。
然后通过id取到那一条信息,
p.delete()删除!

【确认对话框的使用】
前端涉及到了确认对话框的使用:点击删除链接时,跳出确认删除对话框。

href="javascript:void(0)" οnclick="javascript:confirm_del({{sellinggoods.SELLING_GOODS_ID}})">删除
function confirm_del(id){
    if(confirm("确认删除商品"+id+"?")){
        del(id);
    }
}
function del(id){
    window.location.href="delete?id="+id;
}

使用js来实现。确认后通过window.location.href来跳转,把id带过去。

【注意关键字delete】
写确认删除的js时,遇到个问题。
js不生效。
后来发现是js函数名使用了关键字delete!要特别注意一下!


【学会调试js】

关键字delete错误造成的后果就是js没有任何反应。

分析这种问题的正确思路应该是:

js没有反应;js有错误或者js相关代码有错误;调试js;F12火狐浏览器控制台


观察js部分有没有什么错误。然后进入调试界面

【详解】Python专题开发_第6张图片

就像这样,可以开始调试js。


【django工程增删改查 之 增】

 代码如下,按执行顺序backend.html 
  
href="javascript:void(0)" οnclick="javascript:gotoadd()">添加新商品

function gotoadd(){
    window.open("gotoadd","newwindow","height=450px,width=750px,left=350px,top=200px,menubar=no,status=no,scrollbars=no");
}

views.py
def gotoadd(request):
    '''添加商品对话框'''
    params={}
    c=Context(params)
    return TemplateResponse(request, "jisumai/add_new_goods.html", c, content_type)

add_new_goods.html
html>
lang="en">

    charset="UTF-8">
    </span><span style="font-family:'宋体';">极速卖管理后台</span><span style="color:#e8bf6a;">


    

添加新商品

action="add" method="post"> border="0" cellpadding="0" cellspacing="0">
align="left" nowrap>商品ID: align="left" nowrap>type="text" name="gid"/>
align="left" nowrap>商品名称: align="left" nowrap>type="text" name="name" style="width:500px"/>
align="left" nowrap>游戏名称: align="left" nowrap>type="text" name="gamename"/>
align="left" nowrap>原价: align="left" nowrap> οnkeyup="value=value.replace(/[^\d]/g,'') " onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/g,''))" type="text" name="oriprice"/>
align="left" nowrap>点评: align="left" nowrap>
align="left" nowrap>详情: align="left" nowrap>
colspan="2" align="center"> type="submit" name="submit" value="添加"/> type="reset" name="reset" value="取消"/>
这里使用

views.py
def add(request):
    '''添加商品'''
    gid = request.POST.get('gid', '')
    name = request.POST.get('name', '')
    gamename = request.POST.get('gamename', '')
    oriprice = request.POST.get('oriprice', '')
    comments = request.POST.get('comments', '')
    details = request.POST.get('details', '')
    if gid=='' or oriprice=='' or name=='' or gamename=='' or comments=='' or details=='':
        params={}
        c=Context(params)
        return TemplateResponse(request, "jisumai/add_error.html", c, content_type)
    a = Goods(SELLING_GOODS_ID=gid, NAME=name, GAME_NAME=gamename, ORI_PRICE=oriprice, COMMENTS=comments, DETAILS=details)
    a.save()
    params={}
    c=Context(params)
    return TemplateResponse(request, "jisumai/add_success.html", c, content_type)
该方法是添加商品的核心方法。
我们可以看到,通过post方式提交的表单内容,先一一拿到。
然后组装成a,
a.save()。提交到了数据库!

Java中实现增加的功能,是把拿到的内容赋给一个值,然后层层提交到DAO层,通过增加的SQL语句insert,添加到数据库。


add_success.html
html>
lang="en">

    charset="UTF-8">
    </span><span style="font-family:'宋体';">极速卖管理后台</span><span style="color:#e8bf6a;">


    

添加成功!


需要手动关闭跳出来的窗口。

【添加商品页面窗口】
为了方便使用,把添加页面做成窗口。
关键部分代码是:
function gotoadd(){
    window.open("gotoadd","newwindow","height=450px,width=750px,left=350px,top=200px,menubar=no,status=no,scrollbars=no");
}
 
  

效果如下:【详解】Python专题开发_第7张图片 

这种跳出窗口的方式就是很多新闻门户网站使用的。

选定某些内容可以分享到新浪微博,然后就会跳出这样的窗口,分享成功后需要自行关闭。

【表单提交 forms.py】

因为涉及到了表单提交,所以后台代码需要写一个forms.py。

forms.py定义了提交的数据封装类,即,提交了什么。

from django.db import models

class Goods(models.Model):
    SELLING_GOODS_ID = models.IntegerField()
    NAME = models.CharField(max_length=100)
    GAME_NAME = models.CharField(max_length=100)
    ORI_PRICE = models.IntegerField()
    COMMENTS = models.CharField(max_length=500)
    DETAILS = models.CharField(max_length=100)

    class Meta:
        db_table = "QUICK_SELLING_GOODS"

然后在views.py中导入
from moyoyo_zt.jisumai.forms import Goods
具体的add方法中:
【详解】Python专题开发_第8张图片
 
  
 
  
 
  

【django工程增删改查 之 改】

依然是跳出对话窗口,然后提交,提示成功后自行关闭。

与增加商品相同的部分不赘述。

流程如下:

views.py

def gotochange(request):
    '''修改商品对话框'''
    params={}
    id = request.GET.get('id')
    goods=SellingGoods.objects.get(SELLING_GOODS_ID=id)
    params['goods']=goods
    c=Context(params)
    return TemplateResponse(request, "jisumai/change_new_goods.html", c, content_type)

点击修改时把id传到后台,取出该条商品的信息。


change_new_goods.html

html>
lang="en">

    charset="UTF-8">
    </span><span style="font-family:'宋体';">极速卖管理后台</span><span style="color:#e8bf6a;">


    

修改商品

action="change" method="post"> border="0" cellpadding="0" cellspacing="0">
align="left" nowrap>商品ID: align="left" nowrap>type="text" name="gid" readonly="true" value="{{goods.SELLING_GOODS_ID}}" />
align="left" nowrap>商品名称: align="left" nowrap>type="text" name="name" style="width:500px" value="{{goods.NAME}}"/>
align="left" nowrap>游戏名称: align="left" nowrap>type="text" name="gamename" value="{{goods.GAME_NAME}}"/>
align="left" nowrap>原价: align="left" nowrap>type="text" name="oriprice" value="{{goods.ORI_PRICE}}"/>
align="left" nowrap>点评: align="left" nowrap>
align="left" nowrap>详情: align="left" nowrap>
colspan="2" align="center"> type="submit" name="submit" value="修改"/>
显示该条商品信息,可以进行修改


views.py

核心方法如下:

def change(request):
    '''修改商品操作'''
    gid = request.POST.get('gid')
    p = Goods.objects.get(SELLING_GOODS_ID=gid)
    p.NAME = request.POST.get('name')
    p.GAME_NAME = request.POST.get('gamename')
    p.ORI_PRICE = request.POST.get('oriprice')
    p.COMMENTS = request.POST.get('comments')
    p.DETAILS = request.POST.get('details')
    p.save()
    params={}
    c=Context(params)
    return TemplateResponse(request, "jisumai/change_success.html", c, content_type)
把修改结果提交,直接按id保存p.save(),就可以成功更新数据库中的数据。


【django项目中ajax的使用】

需求:

后台修改活动时间时,

【详解】Python专题开发_第9张图片

前端的倒计时时间实时变化,

【详解】Python专题开发_第10张图片

实时变化就是不需要刷新页面,能够更新倒计时的时间。即,需要用到ajax。


实现思路:

把修改时间写到一个txt文件中,如event_date.txt。

倒计时随时通过读取txt中的  时间字符串  来计算。

后台修改活动时间时,修改的字符串更新到这个txt文件中。

如此,涉及到了txt文件的读写。这个我们写了很多脚本之后已经很熟练了。。


实现方法:

1.  把后台提交的时间写到txt文件中

backend.html

活动时间: type="text" id="eventdate" name="eventdate" value="{{eventdate}}"> type="submit" name="submit" value="修改"/>

views.py

def writedate(request):
    '''修改活动时间'''
    eventdate = request.POST.get('eventdate')
    f=open('C:\\moyoyo_zt\\moyoyo_zt\\jisumai\\event_date.txt', 'w')
    f.write(eventdate)
    f.close()
    return HttpResponseRedirect('backend.html?eventdate='+eventdate)

点击修改按钮以后,时间已经写入了event_date.txt。

2. 点击修改以后页面需要作出的反应

    点击了修改按钮,页面刷新,并把刚刚提交的时间字符串显示在输入框中。

   【重定向带参数的注意点】

     重定向到backend.html。意思就是要重走一遍backend方法。

    

def backend(request):
    '''进入管理后台首页'''
    pn = request.GET.get("pageNo", "1")
    eventdate = request.GET.get("eventdate", "")
    if eventdate == "":
        f = open('C:\\moyoyo_zt\\moyoyo_zt\\jisumai\\event_date.txt', 'r')
        eventdate=f.readline()
        f.close()
    params = {}
    goodslist=SellingGoods.objects.all()
    paginator = Paginator(goodslist, 3)
    goodslist = paginator.page(pn)
    params['goodslist'] = goodslist
    params['eventdate'] = eventdate
    c = Context(params)
    return TemplateResponse(request, "jisumai/backend.html", c, content_type)
从该方法中我们可以看到,

如果eventdate输入框中没有数值时,就去读取txt文件中的值然后写入

如果修改eventdate,即输入框中原来有一个值时,直接把这个新值  重新提交到html就可以了。


之前遇到过的问题是writedate方法中最后的重定向链接带参数,无法在后台首页显示修改后的时间字符串。

原因就是虽然提交到了html页面,但是没有走backend方法,所以才不显示的。


也就是说,前台页面的数据显示,都需要后台来进行支持。每一个数据都是,如果没有后台的支持,前台就只是死的页面,

不会有数据的更新变化。


3.ajax的实现方法

   直接上代码

   index.html中的js代码

window.setInterval(
	    function(){
	      $.ajax({
			type: "POST",
			url: "readdate.post",
			data:"",
			success: function(data) {
				var y=data.split('-')[0]
				var m=data.split('-')[1]
				var d=data.split('-')[2]
				ShowCountDown(y,m,d,'divdown1');
			}
		});
	    },
	    interval);//倒计时结束日期
     views.py中的读取方法

def readdate(request):
    '''读取活动时间'''
    f=open('C:\\moyoyo_zt\\moyoyo_zt\\jisumai\\event_date.txt', 'r')
    eventdate=f.readline()
    f.close()
    return HttpResponse(eventdate)
    urls.py中配置

【详解】Python专题开发_第11张图片

这样就成功使用ajax实现了倒计时的实时更新。


【Python中文件的绝对路径】

应当是这样的

C:\\moyoyo_zt\\moyoyo_zt\\jisumai\\event_date.txt
双反斜杠。


【HTML设置输入框为只读属性】

修改商品时,我们不希望修改某些数值的时候,可以把输入框的属性设置为只读。

type="text" name="gid" readonly="true" value="{{goods.SELLING_GOODS_ID}}" />
即,readonly属性。


【日期控件的使用】

效果图如下:

【详解】Python专题开发_第12张图片

即输入时间字符串时,通过点击控件日历来输入,用户不需要自己敲字儿了。。


实现方法:

backend.html中,

引入如下css和js

rel="stylesheet" type="text/css" media="all" href="http://res.moyoyo.com/upload/jisumai/css/calendar-miles.css" title="win2k-cold-1" />


写入如下js:

js中指定了inputField为eventdate,即

活动时间: type="text" id="eventdate" name="eventdate" value="{{eventdate}}">
是id还是name呢?

应该是id吧。

如此,就可以顺利使用日期控件了。


你可能感兴趣的:(43,Python专题开发)