Django小型專案練習:模擬商場儲物櫃
學習Django一週時間了,決定寫一個簡單的東西出來,碰巧最近培訓班老師講MySQL,那就寫個儲存相關的吧,於是定計劃,做一個類似商場儲物櫃的小站點。商場超市都會有給顧客放東西的儲物櫃,點選“存包”就會生成隨機條形碼,然後開啟一個空櫃子(如果有的話),條形碼僅一次有效。我做的站點最終呈現如下:
1.兩個表單,分別用於查詢和插入資料,資料格式均為字串型別。
2.插入資料無限制,在文字框輸入要插入的資料後,點選“新增”按鈕就可以講資料插入資料庫。之後會得到一個16個字元的隨即字串,後面憑藉此字串才能獲得存入資料庫的資料。
3.查詢資料需要輸入驗證碼,這主要是防止有人暴力查詢。如上所述,存資料時生成的 key 僅僅能取出一次資料,重複使用無效。這是通過flag欄位控制的,插入一條資料時,flag預設為1,取出資料後,flag置為0,表示該行資料不可取。
--
這個小專案的實現也是在改來改去的過程中完成的,但是這裡就不描述這個過程了,而是從整體上看如何實現之。
---環境---
OS:kubuntu 17.04
Python:2.7
Django:1.8
---
setp1:pip install --user virtualenv 安裝虛擬環境,虛擬環境中的Python包與作業系統上的Python包是隔離,雖然在我們這個專案中這不是必須的,但是有時候虛擬環境就會很有用,比如我們我們要使用不同版本的Django,就可以把他們放到不同的虛擬環境中了。
setp2:cd ~/my_python/ 進入~/my_python,然後執行 virtualenv my_env --python=python2.7 因為我的系統同時裝了Python3,所以這裡需要使用--python=python2.7指明需要使用哪個版本的python。執行後在~/my_python/下會出現 my_env 目錄。
step3:安裝MySQL-server或者MariaDB-Server,設定使用utf8字符集,skip-name-resolve=yes跳過名稱解析,建立使用者‘root’@‘127.0.0.1’,密碼root,監聽在127.0.0.1的3306埠上。create
database mykey; 建立資料庫。
setp4:cd ~/my_python 後執行 . ./my_env/bin/activate 啟動指令碼進入虛擬環境,後續工作都是在該虛擬環境中做的。pip安裝的模組也是放置在虛擬環境中,這樣的話若是普通使用者通過pip安裝模組,就不需要使用sudo了。
pip install Django==1.8 安裝Django
pip install pillow 安裝pillow模組,用於生成驗證碼圖片
pip install MySQL-python 安裝MySQL驅動模組
step5:下面建立專案和應用, cd ~/my_python/,執行django.py startproject mykey 然後看到~/my_python/下出現新目錄mykey,cd mykey 進入後執行 django.py startapp tools 建立名為tools的應用(一個目錄),這時候在 ~/my_python/mykey 下有2個目錄(mykey,tools)和1個指令碼檔案manage.py
====================== 下面開始寫程式 ========================
<--mykey下settings.py -->
新增剛剛建立的應用tools,同時把預設使用的資料庫從sqlite修改為MySQL,修改後如下:
<-- mykey下urls.py -->
urlpatterns = [
url(r'^$', 'tools.views.index', name='home'), //主頁
url(r'^chk/', 'tools.views.itemchk', name='home'), //點選“查詢”按鈕則提交表單至該url
url(r'^add/', 'tools.views.itemadd', name='home'), //點選“新增”按鈕則提交表單至該url
url(r'^create_code_img/','tools.views.create_code_img',name='home'), //點選驗證碼圖片時提交到該url
]
<-- tools下新建forms.py --> 表單生成
#coding:utf-8
from django import forms
class ChkForm(forms.Form):
a=forms.CharField(label="請輸入您要查詢的key")
class AddForm(forms.Form):
a=forms.CharField(label="請輸入您要新增的info")
<-- tools下models.py --> 在資料庫mykey建立表,名字為 tools_mysecret
from django.db import models
# Create your models here.
class MySecret(models.Model):
key=models.CharField(max_length=16)
info=models.CharField(max_length=256)
flag=models.BooleanField(default='True')
def __unicode__(self):
return self.info
<-- tools下新建rankey.py --> 用於生成16個字元的隨機數
import string
import random
KEY_LEN=16
def base_str():
return (string.letters+string.digits)
def key_gen():
keylist=[random.choice(base_str()) for i in range(KEY_LEN)]
return("".join(keylist))
<-- tools下新建check_code.py --> 用於生成驗證碼圖片
#coding:utf-8
import random
from PIL import Image,ImageDraw,ImageFont,ImageFilter
_letter_cases="abcdefghjkmnpqrstuvwxy"
_upper_cases=_letter_cases.upper()
_numbers=''.join(map(str,range(3,10)))
init_chars=''.join((_letter_cases,_upper_cases,_numbers))
def create_validate_code(size=(120,30),
chars=init_chars,
img_type="png",
mode="RGB",
bg_color=(255,255,255),
fg_color=(255,0,255),
font_size=18,
font_type="Hack-Bold.ttf",
length=4,
draw_lines=True,
n_line=(1,2),
draw_points=True,
point_chance=2):
width,height=size
img=Image.new(mode,size,bg_color)
draw=ImageDraw.Draw(img)
def get_chars():
return random.sample(chars,length)
def create_lines():
line_num=random.randint(*n_line)
for i in range(line_num):
begin=(random.randint(0,size[0]),random.randint(0,size[1]))
end=(random.randint(0,size[0]),random.randint(0,size[1]))
draw.line([begin,end],fill=(0,0,0))
def create_points():
chance=min(100,max(0,int(point_chance)))
for w in range(width):
for h in range(height):
tmp=random.randint(0,100)
if tmp>100-chance:
draw.point((w,h),fill=(0,0,0))
def create_strs():
c_chars=get_chars()
strs=' %s ' % ' '.join(c_chars)
font=ImageFont.truetype(font_type,font_size)
font_width,font_height=font.getsize(strs)
draw.text(((width-font_width)/3,(height-font_height)/3),strs,font=font,fill=fg_color)
return ''.join(c_chars)
if draw_lines:
create_lines()
if draw_points:
create_points()
strs=create_strs()
params = [1 - float(random.randint(1, 2)) / 100,
0,
0,
0,
1 - float(random.randint(1, 10)) / 100,
float(random.randint(1, 2)) / 500,
0.001,
float(random.randint(1, 2)) / 500
]
img=img.transform(size,Image.PERSPECTIVE,params)
img=img.filter(ImageFilter.EDGE_ENHANCE_MORE)
return img,strs
<-- tools下views.py -->
#coding:utf-8
from io import BytesIO
from django.shortcuts import render
from django.http import HttpResponse
from django.db.models.query import *
from .forms import ChkForm,AddForm
from .models import MySecret
from .rankey import key_gen
from .check_code import *
def index(request):
chk_form=ChkForm()
add_form=AddForm()
return render(request,'index.html',{'form1':chk_form,'form2':add_form})
def itemchk(request):
if request.method == 'POST':
chk_form=ChkForm(request.POST)
if chk_form.is_valid():
a=chk_form.cleaned_data['a']
post_check_code=request.POST.get('check_code')
session_check_code=request.session['check_code']
if post_check_code.lower()==session_check_code.lower():
try:
secitem=MySecret.objects.get(key=a)
if secitem.flag==1:
MySecret.objects.filter(key=a).update(flag=0)
return HttpResponse(unicode(secitem.info))
else:
return HttpResponse(str('該key已取出'))
except MySecret.DoesNotExist:
return HttpResponse(str('該key不存在'))
else:
return HttpResponse(str('驗證碼錯誤'))
else:
return HttpResponse(str('key不能為空'))
def itemadd(request):
if request.method == 'POST':
add_form=AddForm(request.POST)
if add_form.is_valid():
a=add_form.cleaned_data['a']
mykey=key_gen()
# b=add_form.cleaned_data['b']
# MySecret.objects.create(key=a,info=b)
MySecret.objects.create(key=mykey,info=a)
return HttpResponse(str('請牢記您的key:'+mykey))
def create_code_img(request):
f=BytesIO()
img,code=create_validate_code()
request.session['check_code']=code
img.save(f,'png')
return HttpResponse(f.getvalue(),content_type="image/png")
==========
cd ~/my_python/mykey/tools,建立templates目錄 mkdir templates
cd templates 建立index.html 內容如下:
<-- index.html -->
<form action='/chk/' method='post'>
{% csrf_token %}
{{ form1 }}
<div class="row">
<div class="col-xs-7">
<input type="text" class="form-control" name="check_code" id="check_code" placeholder="請輸入驗證碼">
</div>
<div class="col-xs-5">
<img id="check_code_img" src="/create_code_img/" onclick="javascript:window.location.reload();"/>
</div>
</div>
<input type="submit" value="查詢">
</form>
<form action='/add/' method='post'>
{% csrf_token %}
{{ form2 }}
<input type="submit" value="新增">
</form>
結下來連線資料庫建立表
cd ~/my_python/mykey/
./manage.py makemigrations
./manage.py migrate
./manage.py runserver 執行webserver,通過瀏覽器訪問 127.0.0.1:8000