Django-model基础

 

  知识预览

  • ORM
  • 创建表
  • 添加表记录
  • 查询表记录
  • 修改表记录
  • 删除表记录

对象关系映射ORM(object relationship mapping)

映射关系:

创建表(建立模型)

实例:我们来假定下面这些概念,字段和关系

作者模型:一个作者有姓名和年龄。

作者详细模型:把作者的详情放到详情表,包含生日,手机号,家庭住址等信息。作者详情模型和作者模型之间是一对一的关系(one-to-one)

出版商模型:出版商有名称,所在城市以及email。

书籍模型: 书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many);一本书只应该由一个出版商出版,所以出版商和书籍是一对多关联关系(one-to-many)。

模型建立如下:

 

 1 class Author(models.Model):
 2     nid = models.AutoField(primary_key=True)
 3     name = models.CharField(max_length=32)
 4     age = models.IntegerField()
 5     # 与AuthorDetail建立一对一的关系
 6     authorDetail = models.OneToOneField(to="AuthorDetail")
 7 
 8 class AuthorDetail(models.Model):
 9     nid = models.AutoField(primary_key=True)
10     birthday = models.DateField()
11     telephone = models.BigIntegerField()
12     addr = models.CharField(max_length=64)
13 
14 class Publish(models.Model):
15     nid = models.AutoField(primary_key=True)
16     name = models.CharField(max_length=32)
17     city = models.CharField(max_length=32)
18     email = models.EmailField()
19 
20 class Book(models.Model):
21     nid = models.AutoField(primary_key=True)
22     title = models.CharField(max_length=32)
23     publishDate = models.DateField()
24     price = models.DecimalField(max_digits=5, decimal_places=2)
25     keepNum = models.IntegerField()
26     commentNum = models.IntegerField()
27     
28     # 与Publish建立一对多的关系,外键字段建立在多的一方
29     publish = models.ForeignKey(to="Publish", to_field="nid")
30 
31     # 与Author表建立多对多的关系,ManyToManyField可以建在两个模型中的任意一个,自动创建第三张表
32     authors = models.ManyToManyField(to='Author')

通过logging可以查看翻译成的sql语句

 1 LOGGING = {
 2     'version': 1,
 3     'disable_existing_loggers': False,
 4     'handlers': {
 5         'console':{
 6             'level':'DEBUG',
 7             'class':'logging.StreamHandler',
 8         },
 9     },
10     'loggers': {
11         'django.db.backends': {
12             'handlers': ['console'],
13             'propagate': True,
14             'level':'DEBUG',
15         },
16     }
17 }  

注意事项:

1、 表的名称myapp_modelName,是根据 模型中的元数据自动生成的,也可以覆写为别的名称  

2、id 字段是自动添加的

3、对于外键字段,Django 会在字段名上添加"_id" 来创建数据库中的列名

4、这个例子中的CREATE TABLE SQL 语句使用PostgreSQL 语法格式,要注意的是Django 会根据settings 中指定的数据库类型来使用相应的SQL 语句。

5、定义好模型之后,你需要告诉Django _使用_这些模型。你要做的就是修改配置文件中的INSTALL_APPSZ中设置,在其中添加models.py所在应用的名称。

6、外键字段 ForeignKey 有一个 null=True 的设置(它允许外键接受空值 NULL),你可以赋给它空值 None 。

字段选项

每个字段有一些特有的参数,例如,CharField需要max_length参数来指定VARCHAR数据库字段的大小。还有一些适用于所有字段的通用参数。 这些参数在文档中有详细定义,这里我们只简单介绍一些最常用的:

 1 (1)null
 2 
 3 如果为True,Django 将用NULL 来在数据库中存储空值。 默认值是 False.
 4 
 5 (1)blank
 6 
 7 如果为True,该字段允许不填。默认为False。
 8 要注意,这与 null 不同。null纯粹是数据库范畴的,而 blank 是数据验证范畴的。
 9 如果一个字段的blank=True,表单的验证将允许该字段是空值。如果字段的blank=False,该字段就是必填的。
10 
11 (2)default
12 
13 字段的默认值。可以是一个值或者可调用对象。如果可调用 ,每有新对象被创建它都会被调用。
14 
15 (3)primary_key
16 
17 如果为True,那么这个字段就是模型的主键。如果你没有指定任何一个字段的primary_key=True,
18 Django 就会自动添加一个IntegerField字段做为主键,所以除非你想覆盖默认的主键行为,
19 否则没必要设置任何一个字段的primary_key=True。
20 
21 (4)unique
22 
23 如果该值设置为 True, 这个数据字段的值在整张表中必须是唯一的
24 
25 (5)choices
26 由二元组组成的一个可迭代对象(例如,列表或元组),用来给字段提供选择项。 如果设置了choices ,默认的表单将是一个选择框而不是标准的文本框,而且这个选择框的选项就是choices 中的选项。
27 
28 这是一个关于 choices 列表的例子:
29 
30 YEAR_IN_SCHOOL_CHOICES = (
31     ('FR', 'Freshman'),
32     ('SO', 'Sophomore'),
33     ('JR', 'Junior'),
34     ('SR', 'Senior'),
35     ('GR', 'Graduate'),
36 )
37 每个元组中的第一个元素,是存储在数据库中的值;第二个元素是在管理界面或 ModelChoiceField 中用作显示的内容。 在一个给定的 model 类的实例中,想得到某个 choices 字段的显示值,就调用 get_FOO_display 方法(这里的 FOO 就是 choices 字段的名称 )。例如:
38 
39 from django.db import models
40 
41 class Person(models.Model):
42     SHIRT_SIZES = (
43         ('S', 'Small'),
44         ('M', 'Medium'),
45         ('L', 'Large'),
46     )
47     name = models.CharField(max_length=60)
48     shirt_size = models.CharField(max_length=1, choices=SHIRT_SIZES)
49 
50 
51 >>> p = Person(name="Fred Flintstone", shirt_size="L")
52 >>> p.save()
53 >>> p.shirt_size
54 'L'
55 >>> p.get_shirt_size_display()
56 'Large'
View Code

更多详见模型字段参考

一旦你建立好数据模型之后,django会自动生成一套数据库抽象的API,可以让你执行关于表记录的增删改查的操作。

添加表记录

普通字段

1 方式1
2 publish_obj=Publish(name="人民出版社",city="北京",email="renMin@163.com")
3 publish_obj.save() # 将数据保存到数据库
4 
5 方式2  返回值publish_obj是添加的记录对象
6 publish_obj=Publish.objects.create(name="人民出版社",city="北京",email="renMin@163.com")

外键字段

1 方式1:
2    publish_obj=Publish.objects.get(nid=1)
3    Book.objects.create(title="金瓶眉",publishDate="2012-12-12",price=665,pageNum=334,publish=publish_obj)
4  
5 方式2:
6    Book.objects.create(title="金瓶眉",publishDate="2012-12-12",price=665,pageNum=334,publish_id=1)  

关键点:book_obj.publish是什么?

解除关系:

1 book_obj.authors.remove()     # 将某个特定的对象从被关联对象集合中去除。    ======   book_obj.authors.remove(*[])
2 book_obj.authors.clear()       #清空被关联对象集合。

class RelatedManager

"关联管理器"是在一对多或者多对多的关联上下文中使用的管理器。它存在于下面两种情况:

ForeignKey关系的“另一边”。像这样:

1 from django.db import models
2  
3 class Reporter(models.Model):
4     # ...
5     pass
6  
7 class Article(models.Model):
8     reporter = models.ForeignKey(Reporter)    

在上面的例子中,管理器reporter.article_set拥有下面的方法。

ManyToManyField关系的两边:

1 class Topping(models.Model):
2     # ...
3     pass
4  
5 class Pizza(models.Model):
6     toppings = models.ManyToManyField(Topping)

这个例子中,topping.pizza_set 和pizza.toppings都拥有下面的方法。

add(obj1[, obj2, ...])

把指定的模型对象添加到关联对象集中。

例如:

1 b = Blog.objects.get(id=1)
2 e = Entry.objects.get(id=234)
3 b.entry_set.add(e) # Associates Entry e with Blog b.

在上面的例子中,对于ForeignKey关系,e.save()由关联管理器调用,执行更新操作。然而,在多对多关系中使用add()并不会调用任何 save()方法,而是由QuerySet.bulk_create()创建关系。

create(**kwargs)

创建一个新的对象,保存对象,并将它添加到关联对象集之中。返回新创建的对象:

1 b = Blog.objects.get(id=1)
2 e = b.entry_set.create(
3 headline='Hello',
4 body_text='Hi',
5 pub_date=datetime.date(2005, 1, 1)
6 )
7  
8 # No need to call e.save() at this point -- it's already been saved.

这完全等价于(不过更加简洁于):

1 b = Blog.objects.get(id=1)
2 e = Entry(
3 blog=b,
4 headline='Hello',
5 body_text='Hi',
6 pub_date=datetime.date(2005, 1, 1)
7 )
8 e.save(force_insert=True)

要注意我们并不需要指定模型中用于定义关系的关键词参数。在上面的例子中,我们并没有传入blog参数给create()。Django会明白新的 Entry对象blog 应该添加到b中。

remove(obj1[, obj2, ...])

从关联对象集中移除执行的模型对象:

1 b = Blog.objects.get(id=1)
2 e = Entry.objects.get(id=234)
3 b.entry_set.remove(e) # Disassociates Entry e from Blog b.

对于ForeignKey对象,这个方法仅在null=True时存在。

clear()

从关联对象集中移除一切对象。

1 b = Blog.objects.get(id=1)
2 b.entry_set.clear()

注意这样不会删除对象 —— 只会删除他们之间的关联。

就像 remove() 方法一样,clear()只能在 null=True的ForeignKey上被调用。

注意

对于所有类型的关联字段,add()、create()、remove()和clear()都会马上更新数据库。换句话说,在关联的任何一端,都不需要再调用save()方法。

直接赋值:

通过赋值一个新的可迭代的对象,关联对象集可以被整体替换掉。

1 new_list = [obj1, obj2, obj3]
2 e.related_set = new_list

如果外键关系满足null=True,关联管理器会在添加new_list中的内容之前,首先调用clear()方法来解除关联集中一切已存在对象的关联。否则, new_list中的对象会在已存在的关联的基础上被添加。

查询表记录

查询相关API

 1 all():            #查询所有结果
 2 
 3 filter(**kwargs):    #它包含了与所给筛选条件相匹配的对象
 4 
 5 get(**kwargs):        #返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有多会抛出错误
 6 
 7 exclude(**kwargs):    #它包含了与所给筛选条件不匹配的对象
 8 
 9 values(*field):            #返回一个ValuesQuerySet---一个特殊的QuerySet,运行后得到的并不是一系列model的实例化对象,而是一个可迭代的字典序列
10 
11 values_list(*field):       #它与values()非常相似,它返回的是一个元祖序列,values返回的是一个字典序列
12 
13 order_by(*field):            #对查询结果排序
14 
15 reverse():                        #对查询结果反向排序
16 
17 distinct():                        #从返回结果中剔除重复记录
18 
19 count():                            #返回数据库中匹配查询(QuerySet)的对象数量
20 
21 first():                                #返回第一条记录
22 
23 last():                                #返回最后一条记录
24 
25 exists():                            #如果QuerySet包含数据,就返回True,否则返回False
26 
27 注意!!!区分object与queryset的区别。

双下划线之单表查询

1 models.table1.objects.filter(id__lt=10,id__gt=1)    #获取id大于1且小于10的数据
2 models.table1.objects.filter(id__in[11,22,33])      #获取id等于11、22、33的数据
3 models.table1.objects.exclue(id__in[11,22,33])      #获取id不等于11、22、33的数据
4 models.table1.objects.filter(name__contains="ven")  #获取nanme中包含ven的数据,区分大小写
5 models.table1.objects.filter(name__contains="ven")  #获取nanme中包含ven的数据,不区分大小写
6 models.table1.objects.filter(id__range=[1,2])       #范围
 1 版权归作者所有,任何形式转载请联系作者。
 2 作者:petanne(来自豆瓣)
 3 来源:https://www.douban.com/note/301166150/
 4 
 5 __exact        精确等于 like 'aaa'
 6  __iexact    精确等于 忽略大小写 ilike 'aaa'
 7  __contains    包含 like '%aaa%'
 8  __icontains    包含 忽略大小写 ilike '%aaa%',但是对于sqlite来说,contains的作用效果等同于icontains。
 9 __gt    大于
10 __gte    大于等于
11 __lt    小于
12 __lte    小于等于
13 __in     存在于一个list范围内
14 __startswith   以...开头
15 __istartswith   以...开头 忽略大小写
16 __endswith     以...结尾
17 __iendswith    以...结尾,忽略大小写
18 __range    在...范围内
19 __year       日期字段的年份
20 __month    日期字段的月份
21 __day        日期字段的日
22 __isnull=True/False
更多查询方法

 

 

参考文献

 

posted @ 2017-10-26 01:31  Justin067  阅读(79)  评论(0编辑  收藏  举报
TOP