Slide 1

Slide 1 text

Advanced Models ˜The Django Book™ Chapter 10 4QJO -BJ +VMZ ϋ˜˚݋ಂɧ

Slide 2

Slide 2 text

፠̡̻ 4QJO ༟ן҃ρ ं൥߅Ҧԫุஈ 1)1e+BWBTDSJQUe1ZUIPO About me ϋ˜˚݋ಂɧ

Slide 3

Slide 3 text

3FMBUFE PCKFDUT 6QEBUF EBUBCBTF TDIFNB .PEFM NFUIPET .BOBHFST &YFDVUF SBX 42- RVFSJFT .PSF BCPVU .BOBHFST Today’s topics ϋ˜˚݋ಂɧ

Slide 4

Slide 4 text

Related objects ϋ˜˚݋ಂɧ

Slide 5

Slide 5 text

Recalling the Chapter 5 ... ϋ˜˚݋ಂɧ

Slide 6

Slide 6 text

Publisher id name address city state_province country website AutoField CharField CharField CharField CharField CharField URLField Book id title authors publisher publication_date AutoField CharField ManyToManyField ForeignKey DateField Author id first_name last_name email AutoField CharField CharField EmailField N:1 N:M ϋ˜˚݋ಂɧ

Slide 7

Slide 7 text

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 ϋ˜˚݋ಂɧ

Slide 8

Slide 8 text

class Author(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=40) email = models.EmailField() def __unicode__(self): return u'%s %s' % (self.first_name, self.last_name) ϋ˜˚݋ಂɧ

Slide 9

Slide 9 text

class Book(models.Model): title = models.CharField(max_length=100) authors = models.ManyToManyField(Author) publisher = models.ForeignKey(Publisher) publication_date = models.DateField() def __unicode__(self): return self.title ϋ˜˚݋ಂɧ

Slide 10

Slide 10 text

class Book(models.Model): title = models.CharField(max_length=100) authors = models.ManyToManyField(Author) publisher = models.ForeignKey(Publisher) publication_date = models.DateField() def __unicode__(self): return self.title ϋ˜˚݋ಂɧ

Slide 11

Slide 11 text

Foreign Key Value Publisher id name address city state_province country website AutoField CharField CharField CharField CharField CharField URLField Book id title authors publisher AutoField CharField ManyToManyField ForeignKey >>> b = Book.objects.get(id=50) >>> b.publisher >>> b.publisher.website u'http://www.apress.com/' ϋ˜˚݋ಂɧ

Slide 12

Slide 12 text

Foreign Key Value Publisher id name address city state_province country website AutoField CharField CharField CharField CharField CharField URLField Book id title authors publisher AutoField CharField ManyToManyField ForeignKey >>> p = Publisher.objects.get(name='Apress Publishing') >>> p.book_set.all() [, , ...] >>> p.book_set.filter(name__icontains='django') [, ] ϋ˜˚݋ಂɧ

Slide 13

Slide 13 text

Foreign Key Value Publisher id name address city state_province country website AutoField CharField CharField CharField CharField CharField URLField Book id title authors publisher AutoField CharField ManyToManyField ForeignKey >>> p = Publisher.objects.get(name='Apress Publishing') >>> p.book_set.all() [, , ...] >>> p.book_set.filter(name__icontains='django') [, ] ϋ˜˚݋ಂɧ

Slide 14

Slide 14 text

class Book(models.Model): title = models.CharField(max_length=100) authors = models.ManyToManyField(Author) publisher = models.ForeignKey(Publisher) publication_date = models.DateField() def __unicode__(self): return self.title ϋ˜˚݋ಂɧ

Slide 15

Slide 15 text

class Book(models.Model): title = models.CharField(max_length=100) authors = models.ManyToManyField(Author) publisher = models.ForeignKey(Publisher) publication_date = models.DateField() def __unicode__(self): return self.title ϋ˜˚݋ಂɧ

Slide 16

Slide 16 text

Many-to-Many Values Author id first_name last_name email AutoField CharField CharField EmailField Book id title authors publisher AutoField CharField ManyToManyField ForeignKey >>> b = Book.objects.get(id=50) >>> b.authors.all() [, ] >>> b.authors.filter (first_name='Adrian') [] >>> b.authors.filter (first_name='Adam') [] ϋ˜˚݋ಂɧ

Slide 17

Slide 17 text

Many-to-Many Values Author id first_name last_name email AutoField CharField CharField EmailField Book id title authors publisher AutoField CharField ManyToManyField ForeignKey >>> a = Author.objects.get(first_name='Adrian', last_name='Holovaty') >>> a.book_set.all() [, ]' ϋ˜˚݋ಂɧ

Slide 18

Slide 18 text

Many-to-Many Values Author id first_name last_name email AutoField CharField CharField EmailField Book id title authors publisher AutoField CharField ManyToManyField ForeignKey >>> a = Author.objects.get(first_name='Adrian', last_name='Holovaty') >>> a.book_set.all() [, ]' ϋ˜˚݋ಂɧ

Slide 19

Slide 19 text

Update database schema ϋ˜˚݋ಂɧ

Slide 20

Slide 20 text

First of all ϋ˜˚݋ಂɧ

Slide 21

Slide 21 text

Does not care extra DB table columns Does not care extra DB tables Complains if model contains fields that has not yet been created in the DB table Django ϋ˜˚݋ಂɧ

Slide 22

Slide 22 text

`syncdb` only create tables for models which have not yet been installed. ϋ˜˚݋ಂɧ

Slide 23

Slide 23 text

"EE NPEFM GJFMET 3FNPWF NPEFM GJFMET 3FNPWF NPEFMT Update database schema ϋ˜˚݋ಂɧ

Slide 24

Slide 24 text

Add model fields ϋ˜˚݋ಂɧ

Slide 25

Slide 25 text

Add model fields Add fields to the model Check the column definitions for new fields Add new columns to the DB table Verify new fields was added properly In development environments ... ϋ˜˚݋ಂɧ

Slide 26

Slide 26 text

Add model fields Add fields to the model Check the column definitions for new fields Add new columns to the DB table Verify new fields was added properly In development environments ... class Book(models.Model): title = models.CharField(max_length=100) authors = models.ManyToManyField(Author) publisher = models.ForeignKey(Publisher) publication_date = models.DateField() num_pages = models.IntegerField(blank=True, null=True) def __unicode__(self): return self.title ϋ˜˚݋ಂɧ

Slide 27

Slide 27 text

Add model fields Add fields to the model Check the column definitions for new fields Add new columns to the DB table Verify new fields was added properly In development environments ... CREATE TABLE "books_book" ( "id" serial NOT NULL PRIMARY KEY, "title" varchar(100) NOT NULL, "publisher_id" integer NOT NULL REFERENCES "books_publisher" ("id"), "publication_date" date NOT NULL, "num_pages" integer NULL ); $ python manage.py sqlall books ϋ˜˚݋ಂɧ

Slide 28

Slide 28 text

Add model fields Add fields to the model Check the column definitions for new fields Add new columns to the DB table Verify new fields was added properly In development environments ... ALTER TABLE books_book ADD COLUMN num_pages integer; ϋ˜˚݋ಂɧ

Slide 29

Slide 29 text

Add model fields Add fields to the model Check the column definitions for new fields Add new columns to the DB table Verify new fields was added properly In development environments ... >>> from mysite.books.models import Book >>> Book.objects.all()[:5] ϋ˜˚݋ಂɧ

Slide 30

Slide 30 text

Add model fields Add new columns to the DB table Add fields to the model Restart the web server In production environments ... ϋ˜˚݋ಂɧ

Slide 31

Slide 31 text

Remove model fields ϋ˜˚݋ಂɧ

Slide 32

Slide 32 text

Add model fields Remove fields from the model Restart the web server Remove columns from the DB table Remove Normal fields ... ϋ˜˚݋ಂɧ

Slide 33

Slide 33 text

Add model fields Remove fields from the model Restart the web server Remove columns from the DB table Remove Normal fields ... ALTER TABLE books_book DROP COLUMN num_pages; ϋ˜˚݋ಂɧ

Slide 34

Slide 34 text

Add model fields Remove Many-to-Many fields from the model Restart the web server Remove Many-to-Many table from the DB Remove Many-to-Many fields ... ϋ˜˚݋ಂɧ

Slide 35

Slide 35 text

Add model fields Remove Many-to-Many fields from the model Restart the web server Remove Many-to-Many table from the DB Remove Many-to-Many fields ... DROP TABLE books_book_authors; ϋ˜˚݋ಂɧ

Slide 36

Slide 36 text

Remove models ϋ˜˚݋ಂɧ

Slide 37

Slide 37 text

Remove model from the models.py Restart the web server Remove dependent tables from the DB Remove the target table from the DB Remove models ϋ˜˚݋ಂɧ

Slide 38

Slide 38 text

Remove model from the `models.py` Restart the web server Remove dependent tables from the DB Remove the target table from the DB Remove models DROP TABLE books_book; ϋ˜˚݋ಂɧ

Slide 39

Slide 39 text

Model methods ϋ˜˚݋ಂɧ

Slide 40

Slide 40 text

class Person(models.Model): first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) birth_date = models.DateField() address = models.CharField(max_length=100) city = models.CharField(max_length=50) state = USStateField() # Yes, this is U.S.-centric... def baby_boomer_status(self): "Returns the person's baby-boomer status." import datetime if datetime.date(1945, 8, 1) <= self.birth_date <= datetime.date(1964, 12, 31): return "Baby boomer" if self.birth_date < datetime.date(1945, 8, 1): return "Pre-boomer" return "Post-boomer" def is_midwestern(self): "Returns True if this person is from the Midwest." return self.state in ('IL', 'WI', 'MI', 'IN', 'OH', 'IA', 'MO') def _get_full_name(self): "Returns the person's full name." return u'%s %s' % (self.first_name, self.last_name) full_name = property(_get_full_name) ϋ˜˚݋ಂɧ

Slide 41

Slide 41 text

class Person(models.Model): first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) birth_date = models.DateField() address = models.CharField(max_length=100) city = models.CharField(max_length=50) state = USStateField() # Yes, this is U.S.-centric... def baby_boomer_status(self): "Returns the person's baby-boomer status." import datetime if datetime.date(1945, 8, 1) <= self.birth_date <= datetime.date(1964, 12, 31): return "Baby boomer" if self.birth_date < datetime.date(1945, 8, 1): return "Pre-boomer" return "Post-boomer" def is_midwestern(self): "Returns True if this person is from the Midwest." return self.state in ('IL', 'WI', 'MI', 'IN', 'OH', 'IA', 'MO') def _get_full_name(self): "Returns the person's full name." return u'%s %s' % (self.first_name, self.last_name) full_name = property(_get_full_name) ϋ˜˚݋ಂɧ

Slide 42

Slide 42 text

Model methods >>> p = Person.objects.get(first_name='Barack', last_name='Obama') >>> p.birth_date datetime.date(1961, 8, 4) >>> p.baby_boomer_status() 'Baby boomer' >>> p.is_midwestern() True ϋ˜˚݋ಂɧ

Slide 43

Slide 43 text

class Person(models.Model): first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) birth_date = models.DateField() address = models.CharField(max_length=100) city = models.CharField(max_length=50) state = USStateField() # Yes, this is U.S.-centric... def baby_boomer_status(self): "Returns the person's baby-boomer status." import datetime if datetime.date(1945, 8, 1) <= self.birth_date <= datetime.date(1964, 12, 31): return "Baby boomer" if self.birth_date < datetime.date(1945, 8, 1): return "Pre-boomer" return "Post-boomer" def is_midwestern(self): "Returns True if this person is from the Midwest." return self.state in ('IL', 'WI', 'MI', 'IN', 'OH', 'IA', 'MO') def _get_full_name(self): "Returns the person's full name." return u'%s %s' % (self.first_name, self.last_name) full_name = property(_get_full_name) ϋ˜˚݋ಂɧ

Slide 44

Slide 44 text

Property methods >>> p = Person.objects.get(first_name='Barack', last_name='Obama') >>> p.full_name # Note this isn't a method u'Barack Obama' ϋ˜˚݋ಂɧ

Slide 45

Slide 45 text

Managers ϋ˜˚݋ಂɧ

Slide 46

Slide 46 text

What is Manager? ϋ˜˚݋ಂɧ

Slide 47

Slide 47 text

Manager Book.objects.all() ϋ˜˚݋ಂɧ

Slide 48

Slide 48 text

Manager Book.objects.all() ϋ˜˚݋ಂɧ

Slide 49

Slide 49 text

Manager “ The interface through which database query operations are provided to Django models. ” ϋ˜˚݋ಂɧ

Slide 50

Slide 50 text

Why do we need a custom Manager? ϋ˜˚݋ಂɧ

Slide 51

Slide 51 text

"EE FYUSB .BOBHFS NFUIPET .PEJGZ JOJUJBM .BOBHFS 2VFSZ4FUT Custom Mangers ϋ˜˚݋ಂɧ

Slide 52

Slide 52 text

Add extra Manager methods ϋ˜˚݋ಂɧ

Slide 53

Slide 53 text

Add extra Manager methods # Get the number of books that have a title ‘Django’ >>> Book.objects.filter(title__icontains='Django') # Get the number of books that have a title ‘Python’ >>> Book.objects.filter(title__icontains='Python') # Get the number of books that have a title ‘xxx’ .... # Get the number of books that have a title ‘yyy’ .... ..... ....... ϋ˜˚݋ಂɧ

Slide 54

Slide 54 text

Add extra Manager methods # takes a keyword and returns the number of books >>> Book.objects.title_count('django') >>> Book.objects.title_count('python') ϋ˜˚݋ಂɧ

Slide 55

Slide 55 text

# models.py from django.db import models # ... Author and Publisher models here ... class BookManager(models.Manager): def title_count(self, keyword): return self.filter(title__icontains=keyword).count() class Book(models.Model): title = models.CharField(max_length=100) authors = models.ManyToManyField(Author) publisher = models.ForeignKey(Publisher) publication_date = models.DateField() num_pages = models.IntegerField(blank=True, null=True) objects = BookManager() def __unicode__(self): return self.title ϋ˜˚݋ಂɧ

Slide 56

Slide 56 text

# models.py from django.db import models # ... Author and Publisher models here ... class BookManager(models.Manager): def title_count(self, keyword): return self.filter(title__icontains=keyword).count() class Book(models.Model): title = models.CharField(max_length=100) authors = models.ManyToManyField(Author) publisher = models.ForeignKey(Publisher) publication_date = models.DateField() num_pages = models.IntegerField(blank=True, null=True) objects = BookManager() def __unicode__(self): return self.title ϋ˜˚݋ಂɧ

Slide 57

Slide 57 text

Modify initial Manager QuerySets ϋ˜˚݋ಂɧ

Slide 58

Slide 58 text

Modify initial Manager QuerySets Default Manager return all the records Override Manager’s base QuerySets ϋ˜˚݋ಂɧ

Slide 59

Slide 59 text

Modify initial Manager QuerySets Default Manager return all the records Override Manager’s base QuerySets # returns all books in the book database >>> Book.objects.all() ϋ˜˚݋ಂɧ

Slide 60

Slide 60 text

Modify initial Manager QuerySets Default Manager return all the records Override Manager’s base QuerySets By overriding the Manager.get_query_set() ϋ˜˚݋ಂɧ

Slide 61

Slide 61 text

Modify initial Manager QuerySets from django.db import models # First, define the Manager subclass. class DahlBookManager(models.Manager): def get_query_set(self): return super(DahlBookManager, self).get_query_set()\ .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. ϋ˜˚݋ಂɧ

Slide 62

Slide 62 text

Modify initial Manager QuerySets from django.db import models # First, define the Manager subclass. class DahlBookManager(models.Manager): def get_query_set(self): return super(DahlBookManager, self).get_query_set()\ .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. ϋ˜˚݋ಂɧ

Slide 63

Slide 63 text

Modify initial Manager QuerySets >>> Book.dahl_objects.all() >>> Book.dahl_objects.filter(title='Matilda') >>> Book.dahl_objects.count() ϋ˜˚݋ಂɧ

Slide 64

Slide 64 text

Another example class MaleManager(models.Manager): def get_query_set(self): return super(MaleManager, self).get_query_set().filter(sex='M') class FemaleManager(models.Manager): def get_query_set(self): return super(FemaleManager, self).get_query_set().filter(sex='F') class Person(models.Model): first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) sex = models.CharField(max_length=1, choices=(('M', 'Male'), ('F', 'Female'))) people = models.Manager() men = MaleManager() women = FemaleManager() ϋ˜˚݋ಂɧ

Slide 65

Slide 65 text

Another example class MaleManager(models.Manager): def get_query_set(self): return super(MaleManager, self).get_query_set().filter(sex='M') class FemaleManager(models.Manager): def get_query_set(self): return super(FemaleManager, self).get_query_set().filter(sex='F') class Person(models.Model): first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) sex = models.CharField(max_length=1, choices=(('M', 'Male'), ('F', 'Female'))) people = models.Manager() men = MaleManager() women = FemaleManager() ϋ˜˚݋ಂɧ

Slide 66

Slide 66 text

Modify initial Manager QuerySets >>> Person.men.all() >>> Person.women.all() >>> Person.people.all() ϋ˜˚݋ಂɧ

Slide 67

Slide 67 text

Execute raw SQL queries ϋ˜˚݋ಂɧ

Slide 68

Slide 68 text

Django DB objects ϋ˜˚݋ಂɧ

Slide 69

Slide 69 text

connection object cursor object cursor.execute() cursor.fetchone() / cursor.fetchall() Implement the Python DB-API (PEP-0249) Django DB objects ϋ˜˚݋ಂɧ

Slide 70

Slide 70 text

Execute raw SQL queries >>> from django.db import connection >>> cursor = connection.cursor() >>> cursor.execute(""" ... SELECT DISTINCT first_name ... FROM people_person ... WHERE last_name = %s""", ['Lennon']) >>> row = cursor.fetchone() >>> print row ['John'] ϋ˜˚݋ಂɧ

Slide 71

Slide 71 text

Execute raw SQL queries class PersonManager(models.Manager): def first_names(self, last_name): cursor = connection.cursor() cursor.execute(""" SELECT DISTINCT first_name FROM people_person WHERE last_name = %s""", [last_name]) return [row[0] for row in cursor.fetchone()] class Person(models.Model): first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) objects = PersonManager() ϋ˜˚݋ಂɧ

Slide 72

Slide 72 text

Execute raw SQL queries class PersonManager(models.Manager): def first_names(self, last_name): cursor = connection.cursor() cursor.execute(""" SELECT DISTINCT first_name FROM people_person WHERE last_name = %s""", [last_name]) return [row[0] for row in cursor.fetchone()] class Person(models.Model): first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) objects = PersonManager() ϋ˜˚݋ಂɧ

Slide 73

Slide 73 text

Execute raw SQL queries class PersonManager(models.Manager): def first_names(self, last_name): cursor = connection.cursor() cursor.execute(""" SELECT DISTINCT first_name FROM people_person WHERE last_name = %s""", [last_name]) return [row[0] for row in cursor.fetchone()] class Person(models.Model): first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) objects = PersonManager() ϋ˜˚݋ಂɧ

Slide 74

Slide 74 text

Execute raw SQL queries >>> Person.objects.first_names('Lennon') ['John', 'Cynthia'] ϋ˜˚݋ಂɧ

Slide 75

Slide 75 text

More about Managers ϋ˜˚݋ಂɧ

Slide 76

Slide 76 text

As mentioned previously... ϋ˜˚݋ಂɧ

Slide 77

Slide 77 text

Business logic encapsulation Add custom Managers Override default Manager with custom methods ϋ˜˚݋ಂɧ

Slide 78

Slide 78 text

Add custom Managers class IncompleteTodoManager(models.Manager): def get_query_set(self): return super(TodoManager, self).get_query_set().filter(is_done=False) class HighPriorityTodoManager(models.Manager): def get_query_set(self): return super(TodoManager, self).get_query_set().filter(priority=1) class Todo(models.Model): content = models.CharField(max_length=100) # other fields go here.. objects = models.Manager() # the default manager # attach our custom managers: incomplete = models.IncompleteTodoManager() high_priority = models.HighPriorityTodoManager() ϋ˜˚݋ಂɧ

Slide 79

Slide 79 text

Add custom Managers class IncompleteTodoManager(models.Manager): def get_query_set(self): return super(TodoManager, self).get_query_set().filter(is_done=False) class HighPriorityTodoManager(models.Manager): def get_query_set(self): return super(TodoManager, self).get_query_set().filter(priority=1) class Todo(models.Model): content = models.CharField(max_length=100) # other fields go here.. objects = models.Manager() # the default manager # attach our custom managers: incomplete = models.IncompleteTodoManager() high_priority = models.HighPriorityTodoManager() ϋ˜˚݋ಂɧ

Slide 80

Slide 80 text

Add custom Managers >>> Todo.incomplete.all() >>> Todo.high_priority.all() ϋ˜˚݋ಂɧ

Slide 81

Slide 81 text

But ϋ˜˚݋ಂɧ

Slide 82

Slide 82 text

Drawbacks Verbose Managers Cluttered model namespace Not chainable ϋ˜˚݋ಂɧ

Slide 83

Slide 83 text

Custom Manager methods ϋ˜˚݋ಂɧ

Slide 84

Slide 84 text

Custom Manager methods class TodoManager(models.Manager): def incomplete(self): return self.filter(is_done=False) def high_priority(self): return self.filter(priority=1) class Todo(models.Model): content = models.CharField(max_length=100) # other fields go here.. objects = TodoManager() ϋ˜˚݋ಂɧ

Slide 85

Slide 85 text

Custom Manager methods >>> Todo.objects.incomplete() >>> Todo.objects.high_priority() ϋ˜˚݋ಂɧ

Slide 86

Slide 86 text

But ϋ˜˚݋ಂɧ

Slide 87

Slide 87 text

Drawbacks Not chainable between custom methods. # It didn’t work ! >>> Todo.objects.incomplete().high_priority() ϋ˜˚݋ಂɧ

Slide 88

Slide 88 text

Custom QuerySets ϋ˜˚݋ಂɧ

Slide 89

Slide 89 text

Custom QuerySets class TodoQuerySet(models.query.QuerySet): def incomplete(self): return self.filter(is_done=False) def high_priority(self): return self.filter(priority=1) class TodoManager(models.Manager): def get_query_set(self): return TodoQuerySet(self.model, using=self._db) class Todo(models.Model): content = models.CharField(max_length=100) # other fields go here.. objects = TodoManager() ϋ˜˚݋ಂɧ

Slide 90

Slide 90 text

Custom QuerySets class TodoQuerySet(models.query.QuerySet): def incomplete(self): return self.filter(is_done=False) def high_priority(self): return self.filter(priority=1) class TodoManager(models.Manager): def get_query_set(self): return TodoQuerySet(self.model, using=self._db) class Todo(models.Model): content = models.CharField(max_length=100) # other fields go here.. objects = TodoManager() ϋ˜˚݋ಂɧ

Slide 91

Slide 91 text

Custom QuerySets >>> Todo.objects.get_query_set().incomplete() >>> Todo.objects.get_query_set().high_priority() >>> # (or) >>> Todo.objects.all().incomplete() >>> Todo.objects.all().high_priority() >>> # Chainable !!! >>> Todo.objects.all().incomplete().high_priority() ϋ˜˚݋ಂɧ

Slide 92

Slide 92 text

But ϋ˜˚݋ಂɧ

Slide 93

Slide 93 text

Custom QuerySets >>> Todo.objects.get_query_set().incomplete() >>> Todo.objects.get_query_set().high_priority() >>> # (or) >>> Todo.objects.all().incomplete() >>> Todo.objects.all().high_priority() >>> # Chainable !!! >>> Todo.objects.all().incomplete().high_priority() ϋ˜˚݋ಂɧ

Slide 94

Slide 94 text

Custom QuerySets >>> Todo.objects.get_query_set().incomplete() >>> Todo.objects.get_query_set().high_priority() >>> # (or) >>> Todo.objects.all().incomplete() >>> Todo.objects.all().high_priority() >>> # Chainable !!! >>> Todo.objects.all().incomplete().high_priority() Ug== Ugly !! ϋ˜˚݋ಂɧ

Slide 95

Slide 95 text

Proxy everything !! ϋ˜˚݋ಂɧ

Slide 96

Slide 96 text

Proxy everything !! class TodoQuerySet(models.query.QuerySet): def incomplete(self): return self.filter(is_done=False) def high_priority(self): return self.filter(priority=1) class TodoManager(models.Manager): def get_query_set(self): return TodoQuerySet(self.model, using=self._db) def incomplete(self): return self.get_query_set().incomplete() def high_priority(self): return self.get_query_set().high_priority() ϋ˜˚݋ಂɧ

Slide 97

Slide 97 text

Proxy everything !! class TodoQuerySet(models.query.QuerySet): def incomplete(self): return self.filter(is_done=False) def high_priority(self): return self.filter(priority=1) class TodoManager(models.Manager): def get_query_set(self): return TodoQuerySet(self.model, using=self._db) def incomplete(self): return self.get_query_set().incomplete() def high_priority(self): return self.get_query_set().high_priority() ϋ˜˚݋ಂɧ

Slide 98

Slide 98 text

Proxy everything !! >>> Todo.objects.incomplete().high_priority() # Perfect !! ϋ˜˚݋ಂɧ

Slide 99

Slide 99 text

Thank you ϋ˜˚݋ಂɧ