Version 9 (modified by 19 years ago) ( diff ) | ,
---|
Removing the magic
This document proposes a new, cleaner and less magical Django database API.
Model definition
Difference: Import is from django.db.models
instead of django.core.meta
. This is easier to remember. However, models
may not be the best name for it.
from django.db import models class Person(models.Model): first_name = models.CharField(maxlength=30) last_name = models.CharField(maxlength=30)
Unlike before, properties are supported.
from django.db import models class Person(models.Model): first_name = models.CharField(maxlength=30) last_name = models.CharField(maxlength=30) def _get_full_name(self): return "%s %s" % (self.first_name, self.last_name) full_name = property(_get_full_name)
Database connection
Old:
from django.core.db import db cursor = db.cursor()
New:
from django.db import connection cursor = connection.cursor()
This is easier to remember, clearer and more consistent.
API usage: Object creation
Import the model class directly from the module in which it was defined. No more django.models.*
magic.
from myproject.people.models import Person p = Person(first_name='John', last_name='Smith') p.save()
API usage: Table-level functions
All "table-level" functions -- ways of retrieving records tablewide rather than performing instance-specific tasks -- are accessed via a model class's objects
attribute. They aren't direct methods of a model instance object because we want to keep the "table-wide" and "row-specific" namespaces separate.
from myproject.people.models import Person p_list = Person.objects.get_list() p = Person.objects.get_object()
This doesn't work from an instance.
p = Person.objects.get_object(pk=1) p.objects.get_list() # Will raise an exception.
If a model already has an objects
attribute, you'll need to specify an alternate name for the magic objects
.
class Person(models.Model): first_name = models.CharField(maxlength=30) last_name = models.CharField(maxlength=30) objects = models.TextField() class META: manager = Manager(name='more_objects') p = Person(first_name='Mary', last_name='Jones', objects='Hello there.') p.save() p.objects == 'Hello there.' Person.more_objects.get_list()
API usage: Overriding model methods (and pre- and post-save hooks)
Proper subclassing of methods will now work, so you can subclass the automatic save()
and delete()
methods. This removes the need for the _pre_save()
and _post_save()
hooks. Example:
class Person(models.Model): first_name = models.CharField(maxlength=30) last_name = models.CharField(maxlength=30) def save(self): self.do_something() super(Person, self).save(self) # Call the "real" save() method. self.do_something_else()
You can even skip saving (as requested in #1014).
class Person(models.Model): first_name = models.CharField(maxlength=30) last_name = models.CharField(maxlength=30) def save(self): if datetime.date.today() > datetime.date(2005, 1, 1): super(Person, self).save(self) # Call the "real" save() method. else: # Don't save. pass
API usage: Overriding table-level functions
You can override any table-level functions, such as get_list()
or get_object()
. Do this by creating a custom models.Manager
subclass and passing it to your model. The term "manager" could be replaced with some other word.
from django.db import models class PersonManager(models.Manager): def get_list(self, **kwargs): # Changes get_list() to hard-code a limit=10. kwargs['limit'] = 10 return super(PersonManager, self).get_list(self, **kwargs) # Call the "real" get_list() method. class Person(models.Model): first_name = models.CharField(maxlength=30) last_name = models.CharField(maxlength=30) class META: manager = PersonManager()
API usage: Specifying lookups
Old:
people.get_list(first_name__exact='Adrian')
New:
Person.objects.get_list(Person.q.first_name == 'Adrian')
The old syntax will still be supported and documented, indefinitely. The new syntax will be implemented as a thin wrapper around the old syntax. See patch on #851 for implementation.
Other "module"-level members: Automatic manipulators and ObjectDoesNotExist exception
Person.get_add_manipulator() Person.get_change_manipulator() Person.DoesNotExist
DescriptorFields - descriptor for fields proposal (rjwittams)