ps: 看了昆汀塔伦蒂诺的新片,Django原来d不发音啊,所以应该念“姜戈”(类似jungle的发音)。
无论是RoR还是Django,甚至颇具野心的前端框架EmberJs.data,将ORM集成于框架之中并赋予方便存储的API,大大提高了开发效率。不像Java世界中的Hibernate弄了个HQL查询语言,Django这里利用动态语言的优势,令CRUD语义更加自然(EJB3.0中JPA其实也有类似的意思)。当然你还是可以用纯粹的sql直接操作。
https://docs.djangoproject.com/en/dev/ref/models/instances/
这里先跳过如何用django.Models对数据库建模。假设已经存在下列ORM对象定义,Blog<-(一对一)->Entry<-(一对多)->Author。
class Blog(models.Model): name = models.CharField(max_length=100) tagline = models.TextField() def __unicode__(self): return self.name class Author(models.Model): name = models.CharField(max_length=50) email = models.EmailField() def __unicode__(self): return self.name class Entry(models.Model): blog = models.ForeignKey(Blog) headline = models.CharField(max_length=255) body_text = models.TextField() pub_date = models.DateField() mod_date = models.DateField() authors = models.ManyToManyField(Author) n_comments = models.IntegerField() n_pingbacks = models.IntegerField() rating = models.IntegerField() def __unicode__(self): return self.headline
from blog.models import Blog, Entry, Author blog = Blog(name='Beatles Blog', tagline='All the latest Beatles news.') blog.save() entry = Entry.objects.get(pk=1) blog = Blog.objects.get(name="Beatles Blog") entry.blog = blog # ForeignKey entry.save() john = Author.objects.create(name="John") paul = Author.objects.create(name="Paul") george = Author.objects.create(name="George") ringo = Author.objects.create(name="Ringo") entry.authors.add(john, paul, george, ringo) # ManyToManyField all_author = Author.objects.all() blog.delete() Entry.objects.filter(pub_date__year=2007).update(headline='Everything is the same') Entry.objects.all().update(n_pingbacks=F('n_pingbacks') + 1)
如果查询所有对象,使用all()就行。
Entry.objects.filter( headline__startswith='What' ).exclude( pub_date__gte=datetime.date.today() ).filter( pub_date__gte=datetime(2005, 1, 30) )
### 查询结果要同时满足两个条件的交集 Blog.objects.filter(entry__headline__contains='Lennon', entry__pub_date__year=2008)
### 查询结果是分别满足两个条件的并集 Blog.objects.filter(entry__headline__contains='Lennon').filter(entry__pub_date__year=2008)
### SELECT * FROM blog_entry WHERE pub_date <= '2006-01-01'; Entry.objects.filter(pub_date__lte='2006-01-01')
### SELECT ... WHERE id = 14; Blog.objects.get(id=14)
### SELECT ... WHERE headline LIKE '%Lennon%'; Entry.objects.get(headline__contains='Lennon')
Entry.objects.filter(blog__name__exact='Beatles Blog') Blog.objects.filter(entry__authors__name='Lennon') Blog.objects.filter(entry__authors__isnull=False, entry__authors__name__isnull=True)
Entry.objects.all()[5:8]
from django.db.models import F from datetime import timedelta Entry.objects.filter(n_comments__gt=F('n_pingbacks') * 2) Entry.objects.filter(rating__lt=F('n_comments') + F('n_pingbacks')) Entry.objects.filter(authors__name=F('blog__name')) Entry.objects.filter(mod_date__gt=F('pub_date') + timedelta(days=3)) F('somefield').bitand(16)
from django.db.models import Q ### SELECT * from polls WHERE question LIKE 'Who%' AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06') Poll.objects.get( Q(question__startswith='Who'), Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)) )
将pk设为None后保存,即可生成新记录。如果对象有继承关系,还要将pk和id都设为None才行。
blog = Blog(name='My blog', tagline='Blogging is easy') blog.save() # blog.pk == 1 blog.pk = None blog.save() # blog.pk == 2 class ThemeBlog(Blog): theme = models.CharField(max_length=200) django_blog = ThemeBlog(name='Django', tagline='Django is easy', theme='python') django_blog.save() # django_blog.pk == 3 django_blog.pk = None django_blog.id = None django_blog.save() # django_blog.pk == 4
注意,复制对象不会复制原有对象的关系,需要手动复制。
entry = Entry.objects.all()[0] # some previous entry old_authors = entry.authors.all() entry.pk = None entry.save() entry.authors = old_authors # saves new many2many relations
无论是外键,还是一对多,多对多关系,都需要访问其他关系对象。
一对一关系时,正向、反向访问都直接用字段名即可。
一对多关系时,正向访问用字段名,反向访问用字段名加上"_set"后缀。关系对象集可以用add, remove, create, clear,count, filter等来操作。
Entry.objects.get(id=2).blog Entry.objects.get(id=2).authors.filter(name__contains='John') Blog.objects.get(id=1).entry_set.all()