django 模型
一、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()) 复制代码