虚拟环境搭配

安装和配置

安装虚拟环境的命令:

1)sudo pip install virtualenv #安装虚拟环境

2)sudo pip install virtualenvwrapper #安装虚拟环境扩展包

3)编辑家目录下面的.bashrc文件,添加下面两行。

export WORKON_HOME=$HOME/.virtualenvs

source /usr/local/bin/virtualenvwrapper.sh

4)使用source .bashrc使其生效一下。

使用

创建python3虚拟环境:

mkvirtualenv -p python3 bj19  # bj19是虚拟环境名

进入虚拟环境工作:

workon 虚拟环境名

查看机器上有多少个虚拟环境:

workon 空格 + 两个tab键

退出虚拟环境:

deactivate

删除虚拟环境:

rmvirtualenv 虚拟环境名

虚拟环境下安装包的命令:

pip install 包名

注意:不能使用sudo pip install 包名,这个命令会把包安装到真实的主机环境上而不是安装到虚拟环境中。

查看虚拟环境中安装了哪些python包:

pip list
pip freeze

安装django环境:

pip install django==1.8.2

创建项目

建立文件夹

mkdir bj19  # bj19是文件夹名 随便起

进入bj19 创建应用包

python manage.py startapp booktest  # booktest是应用名,可以随便起

更改settings.py设置

# 注册应用
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'booktest', # 注册创建的booktest应用 如果没有这个 创建数据库会报NO changes 错误
)
....
# 模板配置
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')], # 指定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',
],
},
},
]
....
# 数据库配置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', # 指定用什么数据库
'NAME': 'test1', # 指定数据库名
'USER': 'root', # 数据库账号
'PASSWORD': 'mysql', # 数据库密码
'HOST': 'localhost', # 数据库IP 本机用localhost
'PORT': 3306, # 端口
}
}
....
# 本地化配置
LANGUAGE_CODE = 'zh-hans' # 本地化语言 TIME_ZONE = 'Asia/Shanghai' # 本地化时间
....
# 静态资源配置
STATIC_URL = '/static/'
STATICFILES_DIR=[os.path.join(BASE_DIR, 'static')] # 静态资源存放路径

创建模板文件夹 对应应用名在templates创建子目录

创建静态资源文件包

创建数据库test1

create database test1 charset=utf8;

项目中引用pymysql

test1/__init__.py文件中

import pymysql
pymysql.install_as_MySQLdb()

建表

booktest/models.py中

from django.db import models
from datetime import date
# Create your models here.
class BookInfo(models.Model):
'''图书模型类'''
# 书名
# btitle = models.CharField(verbose_name='书名', max_length=20) # verbose_name= 在admin后台显示的标题 max_length=最大长度
btitle = models.CharField('书名', max_length=20) # 如果标题放在第一位 则可以省略verbose_name=
# 出版时间
bpub_date = models.DateField()
# 阅读量
bread = models.IntegerField(default=0) # default 设置默认值
# 评论数
bcomment = models.IntegerField(default=0)
# 是否删除
isDelete = models.BooleanField(default=False) # 定义数据表名称--元选项
class Meta:
# 指定生成的数据表名
db_table = 'bookinfo' class HeroInfo(models.Model):
'''英雄模型类'''
# 姓名
hname = models.CharField('英雄', max_length=20)
# 性别
hgender = models.BooleanField(default=False)
# 功夫
hcomment = models.CharField('功夫', max_length=128)
# 关联书名
hbook = models.ForeignKey('BookInfo')
# 是否删除
isDelete = models.BooleanField(default=False) # 数据表名
class Meta:
db_table = 'heroinfo' class AreaInfo(models.Model):
'''地域模型类'''
# 地名
atitle = models.CharField('地名', max_length=20)
# 自关联pid
aParent = models.ForeignKey('self', null=True, blank=True) # 表名
class Meta:
db_table = 'areainfo'

迁移

python manage.py makemigrations
python manage.py migrate

报错

解决方案:

看一下settings.py文件 apps中有没有添加 booktest

迁移成功

查看数据库

默认值并不在数据库层面生效,而是在django创建对象时生效。

图书表结构

表heroinfo结构如下:

Django框架会根据关系属性生成一个关系字段,并创建外键约束。

测试数据
在数据库命令行中,复制如下语句执行,向booktest_bookinfo表中插入测试数据:

insert into bookinfo(btitle,bpub_date,bread,bcomment,isDelete) values
('射雕英雄传','1980-5-1',12,34,0),
('天龙八部','1986-7-24',36,40,0),
('笑傲江湖','1995-12-24',20,80,0),
('雪山飞狐','1987-11-11',58,24,0);

向booktest_heroinfo表中插入测试数据:

insert into heroinfo(hname,hgender,hbook_id,hcomment,isDelete) values
('郭靖',1,1,'降龙十八掌',0),
('黄蓉',0,1,'打狗棍法',0),
('黄药师',1,1,'弹指神通',0),
('欧阳锋',1,1,'蛤蟆功',0),
('梅超风',0,1,'九阴白骨爪',0),
('乔峰',1,2,'降龙十八掌',0),
('段誉',1,2,'六脉神剑',0),
('虚竹',1,2,'天山六阳掌',0),
('王语嫣',0,2,'神仙姐姐',0),
('令狐冲',1,3,'独孤九剑',0),
('任盈盈',0,3,'弹琴',0),
('岳不群',1,3,'华山剑法',0),
('东方不败',0,3,'葵花宝典',0),
('胡斐',1,4,'胡家刀法',0),
('苗若兰',0,4,'黄衣',0),
('程灵素',0,4,'医术',0),
('袁紫衣',0,4,'六合拳',0);

后台管理

本地化设置已经在settings.py设置好了

创建后台管理账号

python manage.py createsuperuser

运行项目 然后登陆后台

#python manage.py runserver 服务器IP:端口
python manage.py runserver 192.168.121.130:8000

登录后台查看

192.168.121.130:/admin

注册和登录

添加用户表

class AdminInfo(models.Model):
# 管理员
user = models.CharField(max_length=20, unique=True)
# 密码
password = models.CharField(max_length=128)
# 是否删除
isDelete = models.BooleanField(default=False)

创建regist.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="/static/js/jquery-1.12.4.min.js"></script> </head>
<body> <form action="/regist_handle" method="post">
{% csrf_token %}
<lable>账号:</lable>
<input type="text" name="user"><br>
<lable>密码:</lable>
<input type="password" name="password">
<br>
<input type="text" name="verify_code" placeholder="请输入验证码">
<img src="/verify_code" onclick="this.src='/verify_code?'+ Math.random()" alt="" ><br> <-- 点击更换验证码 !-->
<input type="submit" value="注册">
</form>
</body>
</html>

注册及验证码的视图函数views.py

def regist(request):
return render(request, 'booktest/regist.html') def regist_handle(request):
user = request.POST.get('user') # POST或GET要大写
password = request.POST.get('password')
verifycode = request.POST.get('verify_code') if verifycode != request.session['verifycode']:
return HttpResponse('验证码不正确')
u = AdminInfo()
u.user = user
u.password = password
u.save()
return redirect('/login') # 验证码
from PIL import Image, ImageDraw, ImageFont
from django.utils.six import BytesIO
def verify_code(request):
#引入随机函数模块
import random
#定义变量,用于画面的背景色、宽、高
bgcolor = (random.randrange(20, 100), random.randrange(
20, 100), 255)
width = 100
height = 25
#创建画面对象
im = Image.new('RGB', (width, height), bgcolor)
#创建画笔对象
draw = ImageDraw.Draw(im)
#调用画笔的point()函数绘制噪点
for i in range(0, 100):
xy = (random.randrange(0, width), random.randrange(0, height))
fill = (random.randrange(0, 255), 255, random.randrange(0, 255))
draw.point(xy, fill=fill)
#定义验证码的备选值
str1 = 'ABCD123EFGHIJK456LMNOPQRS789TUVWXYZ0'
#随机选取4个值作为验证码
rand_str = ''
for i in range(0, 4):
rand_str += str1[random.randrange(0, len(str1))]
#构造字体对象,ubuntu的字体路径为“/usr/share/fonts/truetype/freefont”
font = ImageFont.truetype('FreeMono.ttf', 23)
#构造字体颜色
fontcolor = (255, random.randrange(0, 255), random.randrange(0, 255))
#绘制4个字
draw.text((5, 2), rand_str[0], font=font, fill=fontcolor)
draw.text((25, 2), rand_str[1], font=font, fill=fontcolor)
draw.text((50, 2), rand_str[2], font=font, fill=fontcolor)
draw.text((75, 2), rand_str[3], font=font, fill=fontcolor)
#释放画笔
del draw
#存入session,用于做进一步验证
request.session['verifycode'] = rand_str
#内存文件操作
buf = BytesIO()
#将图片保存在内存中,文件类型为png
im.save(buf, 'png')
#将内存中的图片数据返回给客户端,MIME类型为图片png
return HttpResponse(buf.getvalue(), 'image/png')

注册路由urls.py

    url(r'regist$', views.regist),
url(r'regist_handle$', views.regist_handle),
url(r'verify_code', views.verify_code),

登录页面login.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/login_check" method="post">
{% csrf_token %}
<lable>账号:</lable>
<input type="text" name="user"><br>
<lable>密码:</lable>
<input type="password" name="password">
<br> <input type="submit" value="登陆">
</form>
</body>
</html>

登录的视图函数views.py

# 登陆页面
def login(request):
return render(request, 'booktest/login.html') # 登陆校验
def login_check(request): user = request.POST.get('user')
password = request.POST.get('password')
userinfo = AdminInfo.objects.filter(user=user) # filter取的是一个questset集 要加get()才能取到值 如果不用filter()用get()取值的话 为空的时候会报错
if not userinfo:
return HttpResponse("无数据")
else:
userinfo = userinfo.get() # QuestSet无法直接读取值 要用get()取值
if user==userinfo.user and password==userinfo.password:
request.session['isLogin'] = True
request.session['user'] = user
return redirect('/index')
else:
return redirect('/login')

注册路由urls.py

    url(r'^login$', views.login),
url(r'^login_check$', views.login_check),

登录校验装饰器views.py

# 校验是否登录,如果没登录返回登录页面
def login_check(func):
def wapper(request, *view_args, **view_kwarga):
if not request.session.has_key('isLogin'):
return redirect('/login')
return func(request, *view_args, **view_kwarga)
return wapper

上传图片

定义模型类models.py

class Uploads(models.Model):
'''图片模型类'''
pic = models.ImageField(upload_to='booktest') # upload_to= 上传到哪个文件夹

设置路径settings.py

UPLOAD_ROOT = os.path.join(BASE_DIR, 'static/upload')  # 没有中括号

上传页面pic_upload.html

在模板中定义上传表单,要求如下:

  • form的属性enctype="multipart/form-data"
  • form的method为post
  • input的类型为file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="upload_handle" method="post" enctype="multipart/form-data">
{% csrf_token %}
<input type="file" name="pic"><br>
<input type="submit" value="上传">
</form>
</body>
</html>

上传和处理的视图函数 views.py

# 上传页面
def pic_upload(request):
return render(request, 'booktest/pic_upload.html') # 上传处理
from django.conf import settings # 为了导入上传路径
def upload_handle(request):
pic = request.FILES.get('pic') # 图片用FILES.get() 接收
print(pic.name)
p = Uploads()
p.pic = 'booktest/%s' % pic.name # 保存到数据库
p.save()
pname = '%s/booktest/%s' % (settings.UPLOAD_ROOT, pic.name)
with open(pname, 'wb') as f: # 写入到指定文件夹
for content in pic.chunks(): # pic.chunks() 一段一段读取
f.write(content)
return HttpResponse('ok')

分页

Paginator类对象的属性:

属性名

说明

num_pages

返回分页之后的总页数

page_range

返回分页后页码的列表

Paginator类对象的方法:

方法名

说明

page(self, number)

返回第number页的Page类实例对象

 

Page类对象的属性:

属性名

说明

number

返回当前页的页码

object_list

返回包含当前页的数据的查询集

paginator

返回对应的Paginator类对象

 

Page类对象的方法:

属性名

说明

has_previous

判断当前页是否有前一页

has_next

判断当前页是否有下一页

previous_page_number

返回前一页的页码

next_page_number

返回下一页的页码

Paginator类实例对象

  • 方法_init_(列表,int):返回分页对象,第一个参数为列表数据,第二个参数为每页数据的条数。
  • 属性count:返回对象总数。
  • 属性num_pages:返回页面总数。
  • 属性page_range:返回页码列表,从1开始,例如[1, 2, 3, 4]。
  • 方法page(m):返回Page类实例对象,表示第m页的数据,下标以1开始。

Page类实例对象

  • 调用Paginator对象的page()方法返回Page对象,不需要手动构造。
  • 属性object_list:返回当前页对象的列表。
  • 属性number:返回当前是第几页,从1开始。
  • 属性paginator:当前页对应的Paginator对象。
  • 方法has_next():如果有下一页返回True。
  • 方法has_previous():如果有上一页返回True。
  • 方法len():返回当前页面对象的个数。

创建视图page_test.html:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>省</h1>
<ul>
{% for p in page %}
<li>{{ p.atitle }}</li>
{% endfor %}
</ul> {#页码#}
{#判断是否有上一页#}
{% if page.has_previous %}
<a href="/page_test/{{ page.previous_page_number }}">《上一页</a>
{% endif %}
{% for pindex in plist %}
{# 判断当前页 撤销当前页a标签#}
{% if pindex == page.number %}
{{ pindex }}
{% else %}
<a href="/page_test/{{ pindex }}">{{ pindex }}</a>
{% endif %}
{% endfor %}
{#判断是否有下一页#}
{% if page.has_next %}
<a href="/page_test/{{ page.next_page_number }}">下一页》</a>
{% endif %}
</body>
</html>

分页的视图函数views.py

from django.core.paginator import Paginator # 分页需导入paginator包
def page_test(request, pindex): # 红字参数与路由要一致
# 查询所有省的名称
prov_list = AreaInfo.objects.filter(aParent__isnull=True)
print(prov_list)
# 分页 每页显示10条内容
provs = Paginator(prov_list,10)
# 如果当前没有传递页码信息,则认为是第一页,这样写是为了请求第一页时可以不写页码
if pindex=='':
pindex = 1
else:
# 通过url匹配的参数都是字符串类型,转换成int类型
pindex = int(pindex)
# 获取第pIndex页的数据
page = provs.page(pindex)
# 获取所有的页码信息
plist = provs.page_range
return render(request, 'booktest/page_test.html', {'page':page, 'plist':plist})

路由urls.py

url(r'page_test/(?P<pindex>\d*)$', views.page_test), # 红字部分要和views.py 中视图函数的形参保持一致

三级联动

创建视图areas.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>省市县选择案例</title>
<script src="/static/js/jquery-1.12.4.min.js"></script>
<script>
$(function () {
// 发起一个ajax请求 /prov,获取所有省级地区的信息
// 获取信息,使用get
// 涉及到信息修改,使用post
$.get('/prov', function (data) {
// 回调函数
// 获取返回的json数据
res = data.data
// 获取prov下拉列表框
prov = $('#prov')
// 变量res数组,获取每一个元素:[地区id, 地区标题]
/*
for(i=0; i<res.length; i++){
id = res[i][0]
atitle = res[i][1] option_str = '<option value="'+id + '">'+ atitle+ '</option>'
// 向prov下拉列表框中追加元素
prov.append(option_str)
}*/
$.each(res, function (index, item) {
id = item[0]
atitle = item[1]
option_str = '<option value="'+id + '">'+ atitle+ '</option>'
// 向prov下拉列表框中追加元素
prov.append(option_str)
})
}) // 绑定prov下拉列表框的change事件,获取省下面的市的信息
$('#prov').change(function () {
// 发起一个ajax请求 /city,获取省下面市级地区的信息
// 获取点击省的id
prov_id=$(this).val()
$.get('/city'+prov_id, function (data) {
// 获取返回的json数据
res = data.data
// 获取city下拉列表框
city = $('#city')
// 清空city下拉列表框
city.empty().append('<option>---请选择市---</option>')
// 获取dis下拉列表框
dis = $('#dis')
// 清空dis下拉列表框
dis.empty().append('<option>---请选择县---</option>')
// 变量res数组,获取每一个元素:[地区id, 地区标题]
// 遍历取值添加到city下拉列表框中
$.each(res, function (index, item) {
id = item[0]
atitle = item[1]
option_str = '<option value="'+id + '">'+ atitle+ '</option>'
// 向city下拉列表框中追加元素
city.append(option_str)
})
})
}) // 绑定city下拉列表框的change事件,获取市下面的县的信息
$('#city').change(function () {
// 发起一个ajax请求 /dis,获取市下面县级地区的信息
// 获取点击市的id
city_id=$(this).val()
$.get('/dis'+city_id, function (data) {
// 获取返回的json数据
res = data.data
// 获取dis下拉列表框
dis = $('#dis')
// 清空dis下拉列表框
dis.empty().append('<option>---请选择县---</option>')
// 变量res数组,获取每一个元素:[地区id, 地区标题]
// 遍历取值添加到dis下拉列表框中
$.each(res, function (index, item) {
id = item[0]
atitle = item[1]
option_str = '<option value="'+id + '">'+ atitle+ '</option>'
// 向dis下拉列表框中追加元素
dis.append(option_str)
})
})
})
})
</script>
</head>
<body>
<select id="prov">
<option>---请选择省---</option>
</select>
<select id="city">
<option>---请选择市---</option>
</select>
<select id="dis">
<option>---请选择县---</option>
</select>
</body>
</html>

视图函数views.py

# /areas
def areas(request):
'''省市县选中案例'''
return render(request, 'booktest/areas.html') # /prov
def prov(request):
'''获取所有省级地区的信息'''
# 1.获取所有省级地区的信息
areas = AreaInfo.objects.filter(aParent__isnull=True) # 2.变量areas并拼接出json数据:atitle id
areas_list = []
for area in areas:
areas_list.append((area.id, area.atitle)) # 3.返回数据
return JsonResponse({'data':areas_list}) def city(request, pid):
'''获取pid的下级地区的信息'''
# 1.获取pid对应地区的下级地区
# area = AreaInfo.objects.get(id=pid)
# areas = area.areainfo_set.all()
areas = AreaInfo.objects.filter(aParent__id=pid) # 2.变量areas并拼接出json数据:atitle id
areas_list = []
for area in areas:
areas_list.append((area.id, area.atitle)) # 3.返回数据
return JsonResponse({'data': areas_list})

路由配置urls.py

    url(r'^areas$', views.areas), # 省市县选中案例
url(r'^prov$', views.prov), # 获取所有省级地区的信息
url(r'^city(\d+)$', views.city), # 获取省下面的市的信息
url(r'^dis(\d+)$', views.city), # 获取市下面的县的信息

创建django项目完整实例的更多相关文章

  1. Django-下载安装-配置-创建django项目-三板斧简单使用

    目录 Django 简介 使用 django 的注意事项 计算机名不能有中文 Django版本问题 django下载安装 在命令行下载安装 在pycharm图形界面下载安装 检验是否安装成功 创建Dj ...

  2. 终端指令操作创建Django项目

    需求:通过Django创建一个用户表和权限表. 用户表包括:用户名,邮箱,密码,管理权限. 权限表包括:普通用户,管理用户,超级用户. 权限表和用户表有一对多的关系,即用户表中的每条数据对应权限表中的 ...

  3. 在Eclipse中创建Django项目

    在以前的分享中,我们是在命令行模式下创建Django项目的,那么,如何在IDE中使用Django呢? 本文将介绍如何在Eclipse中创建Django项目. 首先,新建Django项目mysite,如 ...

  4. Python——Pycharm创建Django项目

    一.Django的官网 地址:https://www.djangoproject.com/download/ 注:LTS表示一直在维护的版本,建议是带LTS的版本 二.Pycharm下载Django ...

  5. 学以致用三十-----pycharm创建django项目忘记添加app

    记忆力有时候真的不是很好.因此有些操作步骤还是记录下来好了. pycharm版本-----2018.2.4 创建django项目 file-----newproject----- 创建的时候,appl ...

  6. Pycharm创建Django项目并访问Django

    Pycharm创建Django项目并访问Django 一.Django插件 如果没有Django插件,需要先安装Django插件. 1,首先点击Default Settings,打开设置页面: 2,打 ...

  7. 第三百零三节,Django框架介绍——用pycharm创建Django项目

    Django框架介绍 Django是一个开放源代码的Web应用框架,由Python写成.采用了MVC的软件设计模式,即模型M,视图V和控制器C.它最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内 ...

  8. eclipse + pydev 创建django项目

    前提条件机器装好python,并装好django插件.(http://blog.csdn.net/lilongjiu/article/details/51405340) 1. 下载eclise Ver ...

  9. 一 Django框架介绍——用pycharm创建Django项目

    Django框架介绍 Django是一个开放源代码的Web应用框架,由Python写成.采用了MVC的软件设计模式,即模型M,视图V和控制器C.它最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内 ...

随机推荐

  1. 【洛谷4482】Border的四种求法(后缀自动机_线段树合并_链分治)

    这题我写了一天后交了一发就过了我好兴奋啊啊啊啊啊啊 题目 洛谷 4482 分析 这题明明可以在线做的,为什么我见到的所有题解都是离线啊 -- 什么时候有机会出一个在线版本坑人. 题目的要求可以转化为求 ...

  2. 【leetcode】590. N-ary Tree Postorder Traversal

    Recurisve: /* // Definition for a Node. class Node { public: int val; vector<Node*> children; ...

  3. gRPC-拦截器简单使用

    概述 gRPC作为通用RPC框架,内置了拦截器功能.包括服务器端的拦截器和客户端拦截器,使用上大同小异.主要作用是在rpc调用的前后进行额外处理. 从客户端角度讲,可以在请求发起前,截取到请求参数并修 ...

  4. Java Web报错:The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path

    问题描述: 我们在用Eclipse进行Java web开发时,可能会出现这样的错误:The superclass javax.servlet.http.HttpServlet was not foun ...

  5. Java字节码扩展

    异常表 代码一: public class Test03 { public void test() { try { InputStream is = new FileInputStream(" ...

  6. vim安装 YCM 过程记录

    YCM(YouComplateMe) 属于Vim中大神级的插件,提供了类似于巨硬爸爸的VS中的代码补全,但是其安装方式也是比较复杂,因此特意写下一篇记录,记录下我自己如何安装这一插件的过程: 检查自己 ...

  7. texlive2019安装

    TeX Live 是 TUG (TeX User Group) 发布并维护的的 TeX 系统,可以称得上是TeX的官方系统,官网为:https://www.tug.org/texlive/ 1.通过最 ...

  8. 2.NET Core设定数据库种子

    1.使用以下代码在 Models 文件夹中创建一个名为 SeedData 的新类: using Microsoft.EntityFrameworkCore;using Microsoft.Extens ...

  9. web API .net - .net core 对比学习-文件目录概述

    个人正在学习.net web Api的相关知识,因此用这一系列博客做一记录. 1. 首先我们分别创建 .net web api 项目和 .net core web api 项目. 2. 我们首先比较一 ...

  10. 在Centos中安装.net core SDK

    在Linux中运行.net core 项目必须要有.net core SDK 环境.之前配置过几次,但由于没有做总结.过了几天又配置的时候 感觉特别陌生,今天就记录一次.net core SDK 的安 ...