一、project 与app之间的关系
1个project中可包含多个app
eg:包含两个app的project的结构
project:存放对各个app的配置
app:真正的业务代码,包含models和views,以package的形式存在,
容易完整移植到其他project,从而被多个project复用
二、用python代码定义表结构
1、python通过models实现create table的操作:
from django.db import models
class Book(models.Model):
name = models.CharField(max_length=50)
pub_date = models.DateField()
2、python代码定义表结构的好处
1)无需考虑不同数据库平台的兼容性问题,无论是mysql,mongodb,redis
从python代码create table的方式都是一样的
2)开发者专注于python代码,不用再去写sql,减轻大脑负担
3)django框架中有特定的数据类型, eg:email类型,url类型
4)性能考虑:不用每次系统启动或者发起请求都要先检查一下数据库结构,而是
可以根据python代码就知道了目标数据库的结构。
3、缺点
每次修改了python数据库结构后,需要手动修改数据库中的表结构
三、测试models在django中的使用
1、基本准备
1)创建django project和app
2)修改settings.py中的基本设置
模板位置:
TEMPLATE_DIRS = (
os.path.join(BASE_DIR, 'templates'),
)
数据库连接:
复制代码
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'django_db',
'USER': 'root',
'PASSWORD': 'feng',
'HOST': '127.0.0.1',
'PORT': '3306',
}
}
复制代码
仅安装当前使用的app:
复制代码
INSTALLED_APPS = (
# 'django.contrib.admin',
# 'django.contrib.auth',
# 'django.contrib.contenttypes',
# 'django.contrib.sessions',
# 'django.contrib.messages',
# 'django.contrib.staticfiles',
'model_test_app',
)
MIDDLEWARE_CLASSES = (
# 'django.contrib.sessions.middleware.SessionMiddleware',
# 'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
# 'django.contrib.auth.middleware.AuthenticationMiddleware',
# 'django.contrib.messages.middleware.MessageMiddleware',
# 'django.middleware.clickjacking.XFrameOptionsMiddleware',
)
复制代码
执行ctrl+r+syndbc时,只会根据INSTALLED_APPS设置的app来检查
对应的数据库表是否存在,其他没有设置的app不会被检查。
3)此时数据库中的状态(之前有过其他project的测试数据)
2、通过models.py定义表结构
1)models.py中录入以下代码:
复制代码
from django.db import models
class Publisher(models.Model):
name = models.CharField(max_length=30)
address = models.CharField(max_length=50)
city = models.CharField(max_length=60)
state_province = models.CharField(max_length=30)
country = models.CharField(max_length=50)
website = models.URLField()
class Author(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
email = models.EmailField()
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher)
publication_date = models.DateField()
复制代码
以上python定义表结构涉及到的知识点:
a)字段类型:
字符串类型,URL类型,Email类型,Date类型
b)多对多关系:
authors = models.ManyToManyField(Author)
c)外键:
publisher = models.ForeignKey(Publisher)
d)关于主键:
无需显式指明主键,django会自动为每个模型生成一个自增的整数id作为主键
2)通过python在数据库中创建表:
a)检查model的语法和逻辑是否正确:ctrl+r+validate
b)生成建表的sql语句:ctrl+r+sql
复制代码
"D:\DevPlatform\PyCharm 3.1.3\bin\runnerw.exe" C:\Python27\python.exe "D:\DevPlatform\PyCharm 3.1.3\helpers\pycharm\django_manage.py" sql model_test_app D:/ProgramData/python/model_test
BEGIN;
CREATE TABLE `model_test_app_publisher` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`name` varchar(30) NOT NULL,
`address` varchar(50) NOT NULL,
`city` varchar(60) NOT NULL,
`state_province` varchar(30) NOT NULL,
`country` varchar(50) NOT NULL,
`website` varchar(200) NOT NULL
)
;
CREATE TABLE `model_test_app_author` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`first_name` varchar(30) NOT NULL,
`last_name` varchar(40) NOT NULL,
`email` varchar(75) NOT NULL
)
;
CREATE TABLE `model_test_app_book_authors` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`book_id` integer NOT NULL,
`author_id` integer NOT NULL,
UNIQUE (`book_id`, `author_id`)
)
;
ALTER TABLE `model_test_app_book_authors` ADD CONSTRAINT `author_id_refs_id_206f10ad` FOREIGN KEY (`author_id`) REFERENCES `model_test_app_author` (`id`);
CREATE TABLE `model_test_app_book` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`title` varchar(100) NOT NULL,
`publisher_id` integer NOT NULL,
`publication_date` date NOT NULL
)
;
ALTER TABLE `model_test_app_book` ADD CONSTRAINT `publisher_id_refs_id_f51d29ce` FOREIGN KEY (`publisher_id`) REFERENCES `model_test_app_publisher` (`id`);
ALTER TABLE `model_test_app_book_authors` ADD CONSTRAINT `book_id_refs_id_6f49ea9b` FOREIGN KEY (`book_id`) REFERENCES `model_test_app_book` (`id`);
COMMIT;
Process finished with exit code 0
复制代码
此处多生成了一张表:model_test_app_book_authors,用于描述多对多关系
c)同步sql语句到数据库: ctrl+r+syncdb
运行之后数据库中的情况:
说明:1、实际上可以修改自动生成表名的规则
2、重复执行ctrl+r+syndbc是安全的,不会生成重复的表也不会冲掉旧数据
3、只会根据INSTALLED_APPS设置的app来检查对应的数据库表是否存在
3、基本数据访问
views.py
复制代码
#coding:utf-8
from django.shortcuts import render
from django.shortcuts import render_to_response
from model_test_app.models import Publisher
# Create your views here.
def db_op(request):
#删除
#Publisher.objects.filter(name='Apress').delete()
Publisher.objects.all().delete()
#新增
p1 = Publisher(name='Apress', address='2855 Telegraph Avenue',
city='Berkeley', state_province='CA', country='U.S.A.',
website='http://www.apress.com/')
p1.save()
p2 = Publisher.objects.create(name="O'Reilly",
address='10 Fawcett St.', city='Cambridge',
state_province='MA', country='U.S.A.',
website='http://www.oreilly.com/')
#更新
pub=Publisher.objects.get(name='Apress')
pub.country='China'
pub.save()
#查询
publisher_list = Publisher.objects.all()
for publisher in publisher_list:
print publisher.name,publisher.country
return render_to_response('db_op.html', locals())
复制代码
db_op.html:
复制代码
<!DOCTYPE html>
<html>
<head>
<title>数据库操作</title>
</head>
<body>
<p>操作结果:</p>
<p>
<ul>
{% for publisher in publisher_list %}
<li>{{ publisher.name }}, {{publisher.country}}</li>
{% endfor %}
</ul>
</p>
</body>
</html>
复制代码
执行结果:
页面:
后台输出:
4、模型中的__unicode__()方法:
用于自定义输出“模型”的字符串内容,类似于java中的toString方法
views.py中的输出操作:
复制代码
def db_op(request):
#查询
publisher_list = Publisher.objects.all()
print publisher_list
return render_to_response('db_op.html', locals())
复制代码
未添加__unicode__()方法时:
增加了__unicode__()方法时:
复制代码
from django.db import models
class Publisher(models.Model):
name = models.CharField(max_length=30)
address = models.CharField(max_length=50)
city = models.CharField(max_length=60)
state_province = models.CharField(max_length=30)
country = models.CharField(max_length=50)
website = models.URLField()
#def __unicode__(self):
#return self.name
def __unicode__(self):
return u'%s, %s'%(self.name,self.country)
复制代码
5、关于update操作中的p.save()
并不是只更新修改过的那个字段,所有的字段都会被更新
6、django中实现where条件
1)查询中对字段进行过滤
复制代码
def db_op(request):
#查询
publisher_list = Publisher.objects.filter(name='Apress',country='China')
print publisher_list
return render_to_response('db_op.html', locals())
复制代码
执行结果:
2)like关键词在django中的实现
复制代码
def db_op(request):
#查询
publisher_list = Publisher.objects.filter(name__contains='eil')
#publisher_list = Publisher.objects.all()
print publisher_list
return render_to_response('db_op.html', locals())
复制代码
相当于:where name like '%eil%'
执行结果:
3)get方法获取单条记录:
a)恰好返回1条记录时
复制代码
def db_op(request):
try:
pub=Publisher.objects.get(name__contains='eil')
except:
print '获取单条记录发生异常'
else:
print pub.name
return render_to_response('db_op.html', locals())
复制代码
b)返回两条记录时
复制代码
def db_op(request):
try:
pub=Publisher.objects.get(name__contains='e')
except:
print '获取单条记录发生异常'
else:
print pub.name
return render_to_response('db_op.html', locals())
复制代码
c)没有记录返回时
复制代码
def db_op(request):
try:
pub=Publisher.objects.get(name__contains='eeeeeee')
except:
print '获取单条记录发生异常'
else:
print pub.name
return render_to_response('db_op.html', locals())
复制代码
4)排序
复制代码
def db_op(request):
#升序
publisher_list=Publisher.objects.order_by("name","country")
print publisher_list
#降序
publisher_list2=Publisher.objects.order_by("-name","country")
print publisher_list2
return render_to_response('db_op.html', locals())
复制代码
执行结果:
模型中指定默认排序规则:
复制代码
class Publisher(models.Model):
name = models.CharField(max_length=30)
address = models.CharField(max_length=50)
city = models.CharField(max_length=60)
state_province = models.CharField(max_length=30)
country = models.CharField(max_length=50)
website = models.URLField()
def __unicode__(self):
return u'%s, %s'%(self.name,self.country)
class Meta:
ordering = ['-name']
复制代码
复制代码
def db_op(request):
publisher_list=Publisher.objects.all()
print publisher_list
return render_to_response('db_op.html', locals())
复制代码
执行结果:
5)where和order by同时使用
复制代码
def db_op(request):
publisher_list=Publisher.objects.filter(name="Apress").order_by("name")
print publisher_list
return render_to_response('db_op.html', locals())
复制代码
6)limit的实现
复制代码
def db_op(request):
#返回单个记录
pub=Publisher.objects.order_by("name")[0]
print pub
#返回记录列表
publisher_list=Publisher.objects.order_by("name")[0:100]
print publisher_list
return render_to_response('db_op.html', locals())
复制代码
执行结果:
7)更新记录中的某些字段,而不是所有字段
使用结果集QuerySet的update()方法,而不是p.save()
复制代码
def db_op(request):
#返回记录列表
affectRowCount=Publisher.objects.filter(name__contains='e').update(country='Japan')
print affectRowCount
publisher_list=Publisher.objects.all()
print publisher_list
return render_to_response('db_op.html', locals())
复制代码
执行结果:
8)删除一些记录,而不是单条记录
使用 使用结果集QuerySet的delete()方法,而不是先get单条p,再p.delete()
复制代码
def db_op(request):
#返回记录列表
affectRowCount=Publisher.objects.filter(name='Apress').delete()
print affectRowCount
publisher_list=Publisher.objects.all()
print publisher_list
return render_to_response('db_op.html', locals())
复制代码