edisonfeng

一、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())

      执行结果:

      

     ps:不会返回被删除的行数

   参考:http://djangobook.py3k.cn/2.0/chapter05/

分类:

技术点:

相关文章:

  • 2021-12-05
猜你喜欢
  • 2021-08-14
  • 2021-08-19
  • 2021-09-08
  • 2021-12-08
  • 2022-01-18
相关资源
相似解决方案