模型是你的数据的唯一的、权威的信息源。
使用模型:appy应用后 manage.py makemigrations;manage.py migrate (表或表字段有更改时也需要做数据迁移)
字段:
字段类型:
模型中的每个字段都是 Field 子类的某个实例。( django.db.models.fields)
通过字段选项,可以实现对字段的约束,在字段对象时通过关键字参数指定
ORM:objects relationship map 对象关系映射
表名(app名_表名)--------类名
字段--------属性
表记录--------类实例对象
关系的类型包括
若要创建一个递归的关联 —— 对象与自己具有多对一的关系 —— 请用models.ForeignKey(‘self‘)。
members = models.ManyToManyField(Person, through=‘Membership‘, through_fields=(‘group‘, ‘person‘))
元选项:
使用内部的class Meta 定义模型的元数据,可用的参数:
unique_togethe:联合主键;
from django.db import models class Ox(models.Model): horn_length = models.IntegerField() class Meta: ordering = [‘-order_date‘] unique_together = ("driver", "restaurant")
模型的方法:
__str__():返回对象的字符串表达式(unicode格式
get_absolute_url():计算一个对象的URL
from django.db import models class PollManager(models.Manager): def with_counts(self): from django.db import connection cursor = connection.cursor() cursor.execute(""" SELECT p.id, p.question, p.poll_date, COUNT(*) FROM polls_opinionpoll p, polls_response r WHERE p.id = r.poll_id GROUP BY p.id, p.question, p.poll_date ORDER BY p.poll_date DESC""") result_list = [] for row in cursor.fetchall(): p = self.model(id=row[0], question=row[1], poll_date=row[2]) p.num_responses = row[3] result_list.append(p) return result_list class OpinionPoll(models.Model): question = models.CharField(max_length=200) poll_date = models.DateField() objects = PollManager() class Response(models.Model): poll = models.ForeignKey(OpinionPoll) person_name = models.CharField(max_length=50) response = models.TextField()
# First, define the Manager subclass. class DahlBookManager(models.Manager): def get_queryset(self): return super(DahlBookManager, self).get_queryset().filter(author=‘Roald Dahl‘) # Then hook it into the Book model explicitly. class Book(models.Model): title = models.CharField(max_length=100) author = models.CharField(max_length=50) objects = models.Manager() # The default manager. dahl_objects = DahlBookManager() # The Dahl-specific manager. ##Book.objects.all()将返回数据库中所有的图书。而 Book.dahl_objects.all() 只返回作者#是 Roald Dahl 的图书。
当创建对象时,django不会对数据库进行读写操作,调用save()方法才与数据库交互,将对象保存到数据库中
示例化方法一:
from django.db import models class Book(models.Model): title = models.CharField(max_length=100) @classmethod def create(cls, title): book = cls(title=title) # do something with the book return book book = Book.create("Pride and Prejudice")
class BookManager(models.Manager): def create_book(self, title): book = self.create(title=title) # do something with the book return book class Book(models.Model): title = models.CharField(max_length=100) objects = BookManager() book = Book.objects.create_book("Pride and Prejudice")
普通字段:
#方式1 publish_obj=Publish(name="人民出版社",city="北京",email="renMin@163.com") publish_obj.save() # 将数据保存到数据库 #方式2 #返回值publish_obj是添加的记录对象 publish_obj=Publish.objects.create(name="人民出版社",city="北京",email="renMin@163.com")
外键字段:
方式1: publish_obj=Publish.objects.get(nid=1) Book.objects.create(title="金瓶眉",publishDate="2012-12-12",price=665,pageNum=334,publish=publish_obj) 方式2: Book.objects.create(title="金瓶眉",publishDate="2012-12-12",price=665,pageNum=334,publish_id=1)
多对的字段:
book_obj=Book.objects.create(title="追风筝的人",publishDate="2012-11-12",price=69,pageNum=314,publish_id=1) author_yuan=Author.objects.create(name="yuan",age=23,authorDetail_id=1) author_egon=Author.objects.create(name="egon",age=32,authorDetail_id=2) book_obj.authors.add(author_egon,author_yuan) # 将某个特定的 model 对象添加到被关联对象集合中。 ======= book_obj.authors.add(*[]) book_obj.save()
删除对象:
Book.objects.filter(id=1).delete()
#remove(obj1, obj2, ...)从关联的对象集中删除指定的模型对象。
#clear()从关联的对象集中删除所有的对象。
多对多关联的第三张表中的字段也一起删除了,默认的级联删除。
修改对象:
author = models.Author.objects.filter(id=1) author.name = ‘mona‘ author.save()
---------------- update方法直接设定对应属性---------------- models.Book.objects.filter(id=3).update(title="PHP") ##sql: ##UPDATE "app01_book" SET "title" = ‘PHP‘ WHERE "app01_book"."id" = 3; args=(‘PHP‘, 3)
查寻对象----查询集:
查询集表示从数据库中取出来的对象的集合,它可以含有零个、一个或者多个过滤器。
all(),获取一个表中所有对象
all_entries = Entry.objects.all()
filter(**kwargs)返回一个新的查询集,它包含满足查询参数的对象。
Entry.objects.filter(pub_date__year=2006)
F对象: >>> from django.db.models import F >>> Entry.objects.filter(n_comments__gt=F(‘n_pingbacks‘)) #添加 操作符 >>> Entry.objects.filter(rating__lt=F(‘n_comments‘) + F(‘n_pingbacks‘)) #Q对象 list.filter(Q(pk_ _lt=6)) #字典;
链式过滤:
Entry.objects.filter( ... headline__startswith=‘What‘ ... ).exclude( ... pub_date__gte=datetime.date.today() ... ).filter( ... pub_date__gte=datetime(2005, 1, 30) ... )
one_entry = Entry.objects.get(pk=1)
Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3), headline=‘Hello‘) #等同于 SELECT ... WHERE NOT (pub_date > ‘2005-1-3‘ AND headline = ‘Hello‘)
>>> from django.db.models import Count >>> q = Blog.objects.annotate(Count(‘entry‘)) # The name of the first blog >>> q[0].name ‘Blogasaurus‘
Entry.objects.filter(pub_date__year=2005).order_by(‘-pub_date‘, ‘headline‘)
# This list contains a dictionary. >>> Blog.objects.filter(name__startswith=‘Beatles‘).values() [{‘id‘: 1, ‘name‘: ‘Beatles Blog‘, ‘tagline‘: ‘All the latest Beatles news.‘}]
Entry.objects.values_list(‘id‘, ‘headline‘) [(1, ‘First entry‘), ...]
>>> Entry.objects.dates(‘pub_date‘, ‘day‘, order=‘DESC‘) [datetime.date(2005, 3, 20), datetime.date(2005, 2, 20)]
# Hits the database. e = Entry.objects.select_related(‘blog‘).get(id=5) # Doesn‘t hit the database, because e.blog has been prepopulated # in the previous query. b = e.blog
from django.db import models class Topping(models.Model): name = models.CharField(max_length=30) class Pizza(models.Model): name = models.CharField(max_length=50) toppings = models.ManyToManyField(Topping) def __str__(self): # __unicode__ on Python 2 return "%s (%s)" % (self.name, ", ".join(topping.name for topping in self.toppings.all())) Pizza.objects.all().prefetch_related(‘toppings‘) ‘’’ Pizza .__ str __()要求self.toppings.all()它必须查询数据库,因此Pizza.objects .all()将在Pizza QuerySet中的每个项目的Toppings表上运行查询。 Pizza.objects.all().prefetch_related(‘toppings‘) 这意味着检索到的每个Pizza都会执行self.toppings.all();现在每次调用self.toppings.all(),而不是去数据库的项目,它会在预取的QuerySet缓存中找到它们填充在单个查询中。 ‘’‘
extra(select=None, where=None, params=None, tables=None, order_by=None, select_params=None)
Entry.objects.extra(select={‘is_recent‘: "pub_date > ‘2006-01-01‘"})
#select语句
SELECT blog_entry.*, (pub_date > ‘2006-01-01‘) AS is_recent FROM blog_entry;
Entry.objects.extra(where=["foo=‘a‘ OR bar = ‘a‘", "baz = ‘a‘"])
#select语句
SELECT * FROM blog_entry WHERE (foo=‘a‘ OR bar=‘a‘) AND (baz=‘a‘)
only()
Person.objects.defer("age", "biography") Person.objects.only("name")
try: obj = Person.objects.get(first_name=‘John‘, last_name=‘Lennon‘) except Person.DoesNotExist: obj = Person(first_name=‘John‘, last_name=‘Lennon‘, birthday=date(1940, 10, 9)) obj.save() ############### obj, created = Person.objects.get_or_create(first_name=‘John‘, last_name=‘Lennon‘, defaults={‘birthday‘: date(1940, 10, 9)})
try: obj = Person.objects.get(first_name=‘John‘, last_name=‘Lennon‘) for key, value in updated_values.iteritems(): setattr(obj, key, value) obj.save() except Person.DoesNotExist: updated_values.update({‘first_name‘: ‘John‘, ‘last_name‘: ‘Lennon‘}) obj = Person(**updated_values) obj.save() ########################### obj, created = Person.objects.update_or_create( first_name=‘John‘, last_name=‘Lennon‘, defaults=updated_values)
Entry.objects.filter(headline__contains=‘Lennon‘).count()
first()&last():返回结果集的第一个对象, 当没有找到时返回None.
p = Article.objects.order_by(‘title‘, ‘pub_date‘).first()
exists()如果QuerySet 包含任何结果,则返回True,否则返回False。
if some_queryset.exists(): print("There is at least one object in some_queryset")
#它快于下面这样的允许
if some_queryset:
print("There is at least one object in some_queryset")
limit限制查询:
Entry.objects.all()[5:10]
字段查找:(了不起的双下划线)
字段查询是指如何指定SQL WHERE子句的内容. 它们通过查询集的filter(), exclude() and get()的关键字参数指定.
Entry.objects.get(id__exact=14)
Entry.objects.get(headline__contains=‘Lennon‘) #sql语句 SELECT ... WHERE headline LIKE ‘%Lennon%‘
Entry.objects.filter(id__in=[1, 3, 4]) #SELECT ... WHERE id IN (1, 3, 4);
Entry.objects.filter(id__gt=4) #SELECT ... WHERE id > 4;
Entry.objects.filter(headline__istartswith=‘will‘) #SELECT ... WHERE headline ILIKE ‘Will%‘;
import datetime start_date = datetime.date(2005, 1, 1) end_date = datetime.date(2005, 3, 31) Entry.objects.filter(pub_date__range=(start_date, end_date)) SELECT ... WHERE pub_date BETWEEN ‘2005-01-01‘ and ‘2005-03-31‘;
day:对于日期和日期时间字段,具体到某一天的匹配。取一个整数的天数。
Entry.objects.filter(pub_date__year=2005) #SELECT ... WHERE pub_date BETWEEN ‘2005-01-01‘ AND ‘2005-12-31‘;
regex:正则表达式,区分大小写的正则表达式匹配。正则表达式语法是正在使用的数据库后端的语法。iregex:不区分大小写
Entry.objects.get(title__regex=r‘^(An?|The) +‘) #SELECT ... WHERE title REGEXP BINARY ‘^(An?|The) +‘; -- MySQL
查寻相关的类:
Q()对象:Q() 对象 使得定义查询条件然后重用成为可能,使用| (OR) 和 &(AND) 操作符; 否则QuerySets中使用不了OR。
#Q对象可以使用&(and)、|(or)操作符组合起来,当操作符应用在两个Q对象时,会产生一个新的Q对象 list.filter(pk_ _lt=6).filter(bcommet_ _gt=10) list.filter(Q(pk_ _lt=6) | Q(bcommet_ _gt=10)) #使用~(not)操作符在Q对象前表示取反 list.filter(~Q(pk__lt=6)) #可以使用&|~结合括号进行分组,构造做生意复杂的Q对象 #过滤器函数可以传递一个或多个Q对象作为位置参数,如果有多个Q对象,这些参数的逻辑为and #过滤器函数可以混合使用Q对象和关键字参数,所有参数都将and在一起,Q对象必须位于关键字参数的前面
F对象:可以使用模型的字段A与字段B进行比较,如果A写在了等号的左边,则B出现在等号的右边,需要通过F对象构造
list.filter(bread__gte=F(‘bcommet‘))
#F()对象中还可以写作“模型类__列名”进行关联查询
list.filter(isDelete=F(‘heroinfo__isDelete‘))
#对于date/time和数字字段进行运算
list.filter(bpub_date__lt=F(‘bpub_date‘) + timedelta(days=1))
基于对象的跨表查询 :
一对多:
正向查询(按字段:publish):
book_obj=Book.objects.get(nid=1)
print(book_obj.publish) # book_obj.publish 是nid=1的书籍对象关联的出版社对象
反向查询(按表名:book_set)
publish=Publish.objects.get(name="人民出版社") book_list=publish.book_set.all() # 与人民出版社关联的所有书籍对象集合 for book_obj in book_list: print(book_obj.title)
一对一查询:
正向查询
author_egon=Author.objects.get(name="egon") print(author_egon.authorDetail.telephone)
反向查询
# 查询所有住址在北京的作者的姓名 authorDetail_list=AuthorDetail.objects.filter(addr="beijing") for obj in authorDetail_list: print(obj.author.name)
多对多查询:
正向查询(按字段:authors):
# 金瓶眉所有作者的名字以及手机号 book_obj=Book.objects.filter(title="金瓶眉").first() authors=book_obj.authors.all() for author_obj in authors: print(author_obj.name,author_obj.authorDetail.telephone)
反向查询:
# 查询egon出过的所有书籍的名字 author_obj=Author.objects.get(name="egon") book_list=author_obj.book_set.all() #与egon作者相关的所有书籍 for book_obj in book_list: print(book_obj.title)
基于双下划线的跨表查询:
# 正向查询 按字段:publish queryResult=Book.objects.filter(publish__name="人民出版社") .values_list("title","price") # 反向查询 按表名:book queryResult=Publish.objects.filter(name="人民出版社") .values_list("book__title","book__price")
# 练习2: 查询egon出过的所有书籍的名字(多对多) # 正向查询 按字段:authors: queryResult=Book.objects
.filter(authors__name="yuan")
.values_list("title") # 反向查询 按表名:book queryResult=Author.objects
.filter(name="yuan")
.values_list("book__title","book__price")
# 练习3: 查询人民出版社出版过的所有书籍的名字以及作者的姓名 # 正向查询 queryResult=Book.objects
.filter(publish__name="人民出版社")
.values_list("title","authors__name") # 反向查询 queryResult=Publish.objects
.filter(name="人民出版社")
.values_list("book__title","book__authors__age","book__authors__name")
聚合查询:
from django.db.models import Avg, Max, Min >>> from django.db.models import Avg, Max, Min >>> Book.objects.aggregate(Avg(‘price‘), Max(‘price‘), Min(‘price‘)) {‘price__avg‘: 34.35, ‘price__max‘: Decimal(‘81.20‘), ‘price__min‘: Decimal(‘12.99‘)}
#可以连表,可以反向
Publisher.objects.aggregate(oldest_pubdate=Min(‘book__pubdate‘))
聚合和其他查询集字句:
聚合也可以在过滤器中使用。 作用于普通模型字段的任何 filter()(或 exclude()) 都会对聚合涉及的对象进行限制。
使用annotate() 子句时,过滤器有限制注解对象的作用
>>> from django.db.models import Count, Avg >>> Book.objects.filter(name__startswith="Django").annotate(num_authors=Count(‘authors‘))
更多关于聚合的请参考:http://python.usyiyi.cn/documents/django_182/topics/db/aggregation.html
原文:http://www.cnblogs.com/mona524/p/7766065.html