| 166 | | See NamespaceSimplification for details. |
| | 166 | {{{django.utils.httpwrappers}}} has moved to {{{django.http}}}. |
| | 167 | |
| | 168 | {{{django.core.exceptions.Http404}}} has moved to {{{django.http.Http404}}}. |
| | 169 | |
| | 170 | {{{django.core.template}}} has moved to {{{django.template}}}. |
| | 171 | |
| | 172 | {{{django.core.formfields}}} has moved to {{{django.forms}}}. |
| | 173 | |
| | 174 | {{{django.core.extensions}}} has moved to {{{django.shortcuts}}}. |
| | 175 | |
| | 176 | {{{django.core.extensions.DjangoContext}}} has been renamed to {{{RequestContext}}} and moved to {{{django.template.RequestContext}}}. |
| | 177 | |
| | 178 | You'll need to update {{{TEMPLATE_LOADERS}}} in your settings from: |
| | 179 | {{{ |
| | 180 | #!python |
| | 181 | TEMPLATE_LOADERS = ( |
| | 182 | 'django.core.template.loaders.filesystem.load_template_source', |
| | 183 | 'django.core.template.loaders.app_directories.load_template_source', |
| | 184 | # 'django.core.template.loaders.eggs.load_template_source', |
| | 185 | ) |
| | 186 | }}} |
| | 187 | |
| | 188 | ...to: |
| | 189 | |
| | 190 | {{{ |
| | 191 | #!python |
| | 192 | TEMPLATE_LOADERS = ( |
| | 193 | 'django.template.loaders.filesystem.load_template_source', |
| | 194 | 'django.template.loaders.app_directories.load_template_source', |
| | 195 | # 'django.template.loaders.eggs.load_template_source', |
| | 196 | ) |
| | 197 | }}} |
| | 198 | |
| | 199 | The "auth" and "core" models have been split and moved to {{{django.contrib}}} as follows: |
| | 200 | |
| | 201 | * {{{django.models.auth}}} has moved to {{{django.contrib.auth.models}}}. |
| | 202 | * {{{django.models.core.sites}}} has moved to {{{django.contrib.sites.models}}}. |
| | 203 | * {{{django.models.core.contenttypes}}} has moved to {{{django.contrib.contenttypes.models}}}. |
| | 204 | * {{{django.models.core.packages}}} has moved to {{{django.contrib.contenttypes.models}}}. (Note that "packages" are going away before magic-removal is done.) |
| | 205 | |
| | 206 | Session middleware has moved from {{{django.middleware.sessions.SessionMiddleware}}} to {{{django.contrib.sessions.middleware.SessionMiddleware}}}. Make sure to update your {{{MIDDLEWARE_CLASSES}}} setting, if you're using sessions. |
| | 207 | |
| | 208 | Also, the {{{Session}}} model has moved from django/models/core.py to django/contrib/sessions/models.py. If you're accessing the {{{Session}}} model for some reason, note that location change. |
| 236 | | {{{ |
| 237 | | #!python |
| 238 | | from myproject.people.models import Person |
| 239 | | p_list = Person.objects.get_list() |
| 240 | | p = Person.objects.get_object() |
| 241 | | }}} |
| 242 | | |
| 243 | | This doesn't work from an instance. |
| 244 | | |
| 245 | | {{{ |
| 246 | | #!python |
| 247 | | p = Person.objects.get_object(pk=1) |
| 248 | | p.objects.get_list() # Raises AttributeError |
| | 314 | A model class's {{{objects}}} attribute is an instance of {{{django.db.models.manager.Manager}}}. A manager has the following methods, all of which return a {{{QuerySet}}} instance. |
| | 315 | |
| | 316 | * {{{all()}}} -- Returns a {{{QuerySet}}} of all objects in the database. This is like the old {{{get_list()}}}. Takes no arguments. |
| | 317 | * {{{filter(**kwargs)}}} -- Returns a {{{QuerySet}}}, filtered by the given keyword arguments. Lookup arguments are in the same style as previously, e.g. {{{pubdate__year=2005}}}, except you can leave off {{{__exact}}} as a convenience. For example, {{{name='John'}}} and {{{name__exact='John'}}} are equivalent. |
| | 318 | * {{{order_by(*fieldnames)}}} -- Returns a {{{QuerySet}}} |
| | 319 | * {{{count()}}} -- Returns the count of all objects in the database. |
| | 320 | * {{{dates(field_name, kind)}}} -- Like the old {{{get_FIELD_list()}}} for date fields. For example, old-school {{{get_pubdate_list('year')}}} is now {{{dates('pubdate', 'year')}}}. |
| | 321 | * {{{delete()}}} -- Deletes all objects. |
| | 322 | * {{{distinct()}}} -- Returns a {{{QuerySet}}} with DISTINCT set. |
| | 323 | * {{{extra(select=None, where=None, params=None, tables=None)}}} -- Sets the {{{select}}}, {{{where}}}, {{{params}}} and {{{tables}}} arguments, which are in the same format as before. |
| | 324 | * {{{get(**kwargs)}}} -- Like the old {{{get_object()}}}. Returns an object or raises {{{DoesNotExist}}} on error. |
| | 325 | * {{{in_bulk(id_list)}}} -- Like the old {{{get_in_bulk()}}}. |
| | 326 | * {{{iterator()}}} -- Returns a generator that iterators over results. |
| | 327 | * {{{select_related()}}} -- Returns a {{{QuerySet}}} with the "select related" option (which acts the same as before) set. |
| | 328 | * {{{values(*fieldnames)}}} -- Like the old {{{get_values()}}}. |
| | 329 | |
| | 330 | Each {{{QuerySet}}} has the following methods, which return a clone of the query set with the appropriate changes made: |
| | 331 | |
| | 332 | * {{{filter(**kwargs)}}} |
| | 333 | * {{{order_by(*fieldnames)}}} |
| | 334 | * {{{iterator()}}} |
| | 335 | * {{{count()}}} |
| | 336 | * {{{get(**kwargs)}}} |
| | 337 | * {{{delete()}}} |
| | 338 | * {{{filter(**kwargs)}}} |
| | 339 | * {{{select_related()}}} |
| | 340 | * {{{order_by(*fieldnames)}}} |
| | 341 | * {{{distinct()}}} |
| | 342 | * {{{extra(select=None, where=None, params=None, tables=None)}}} |
| | 343 | |
| | 344 | Here are some examples, which use the following models: |
| | 345 | |
| | 346 | {{{ |
| | 347 | #!python |
| | 348 | class Reporter(models.Model): |
| | 349 | fname = models.CharField(maxlength=30) |
| | 350 | lname = models.CharField(maxlength=30) |
| | 351 | |
| | 352 | class Site(models.Model): |
| | 353 | name = models.CharField(maxlength=20) |
| | 354 | |
| | 355 | class Article(models.Model): |
| | 356 | headline = models.CharField(maxlength=50) |
| | 357 | reporter = models.ForeignKey(Reporter) |
| | 358 | pub_date = models.DateField() |
| | 359 | sites = models.ManyToManyField(Site) |
| | 360 | }}} |
| | 361 | |
| | 362 | || '''Old syntax''' || '''New syntax''' || |
| | 363 | || {{{reporters.get_list()}}} || {{{Reporter.objects.all()}}} || |
| | 364 | || {{{reporters.get_list(fname__exact='John')}}} || {{{Reporter.objects.filter(fname='John')}}} || |
| | 365 | || {{{reporters.get_list(order_by=('-lname', 'fname'))}}} || {{{Reporter.objects.order_by('-lname', 'fname')}}} || |
| | 366 | || {{{reporters.get_list(fname__exact='John', order_by=('lname',))}}} || {{{Reporter.objects.filter(fname='John').order_by('lname')}}} || |
| | 367 | || {{{reporters.get_object(pk=3)}}} || {{{Reporter.objects.get(pk=3)}}} || |
| | 368 | || {{{reporters.get_object(fname__contains='John')}}} || {{{Reporter.objects.get(fname__contains='John')}}} || |
| | 369 | || {{{reporters.get_list(distinct=True)}}} || {{{Reporter.objects.distinct()}}} || |
| | 370 | || {{{reporters.get_values()}}} || {{{Reporter.objects.values()}}} || |
| | 371 | || {{{reporters.get_in_bulk([1, 2])}}} || {{{Reporter.objects.in_bulk([1, 2])}}} || |
| | 372 | || {{{reporters.get_in_bulk([1, 2], fname__exact='John')}}} || {{{Reporter.objects.filter(fname='John').in_bulk([1, 2])}}} || |
| | 373 | || '''Date lookup''' || || |
| | 374 | || {{{articles.get_pub_date_list('year')}}} || {{{Article.objects.dates('pub_date', 'year')}}} || |
| | 375 | || '''Many-to-one related lookup''' || || |
| | 376 | || {{{article_obj.reporter_id}}} || {{{article_obj.reporter.id}}} || |
| | 377 | || {{{article_obj.get_reporter()}}} || {{{article_obj.reporter}}} || |
| | 378 | || {{{reporter_obj.get_article_list()}}} || {{{reporter_obj.article_set.all()}}} || |
| | 379 | || {{{reporter_obj.get_article_list(headline__exact='Hello')}}} || {{{reporter_obj.article_set.filter(headline='Hello')}}} || |
| | 380 | || {{{reporter_obj.get_article_count()}}} || {{{reporter_obj.article_set.count()}}} || |
| | 381 | || {{{reporter_obj.add_article(headline='Foo')}}} || {{{reporter_obj.article_set.add(headline='Foo')}}} || |
| | 382 | || (Alternate syntax) || {{{reporter_obj.article_set.add(article_obj)}}} || |
| | 383 | || ("values" lookup, etc., not previously possible) || {{{reporter_obj.article_set.values()}}} || |
| | 384 | || '''Many-to-many related lookup''' || || |
| | 385 | || {{{article_obj.get_site_list()}}} || {{{article_obj.sites.all()}}} || |
| | 386 | || {{{article_obj.set_sites([s1.id, s2.id])}}} || {{{article_obj.sites.clear(); article_obj.sites.add(s1); article_obj.sites.add(s2)}}} || |
| | 387 | || {{{article_obj.set_sites([s1.id]) # deletion}}} || {{{article_obj.sites.remove(s2)}}} || |
| | 388 | || {{{site_obj.get_reporter_list()}}} || {{{site_obj.reporter_set.all()}}} || |
| | 389 | |
| | 390 | Note that related-object lookup uses the default manager of the related object, which means the API for accessing related objects is completely consistent with the API for accessing objects via a manager. |
| | 391 | |
| | 392 | Also note that managers can't be accessed from instances: |
| | 393 | |
| | 394 | {{{ |
| | 395 | #!python |
| | 396 | p = Person.objects.get(pk=1) |
| | 397 | p.objects.all() # Raises AttributeError |
| 397 | | === Moved "auth" and "core" models to django.contrib === |
| 398 | | |
| 399 | | See http://groups.google.com/group/django-developers/browse_thread/thread/276d071a74543448/7d4b1c40c2d53393 |
| 400 | | |
| 401 | | * Old: {{{django.models.auth}}} |
| 402 | | * New: {{{django.contrib.auth.models}}} |
| 403 | | |
| 404 | | * Old: {{{django.models.core.sites}}} |
| 405 | | * New: {{{django.contrib.sites.models}}} |
| 406 | | |
| 407 | | * Old: {{{django.models.core.contenttypes}}} |
| 408 | | * New: {{{django.contrib.contenttypes.models}}} |
| 409 | | |
| 410 | | * Old: {{{django.models.core.packages}}} |
| 411 | | * New: {{{django.contrib.contenttypes.models}}} ("Packages" will most likely be removed in the future.) |
| 412 | | |
| 413 | | === Moved Session model and middleware from core to django.contrib === |
| 414 | | |
| 415 | | The location of the session middleware has changed. |
| 416 | | |
| 417 | | * Old: {{{django.middleware.sessions.SessionMiddleware}}} |
| 418 | | * New: {{{django.contrib.sessions.middleware.SessionMiddleware}}} |
| 419 | | |
| 420 | | Make sure to update your {{{MIDDLEWARE_CLASSES}}} setting, if you're using sessions. |
| 421 | | |
| 422 | | Also, the {{{Session}}} model has moved from django/models/core.py to django/contrib/sessions/models.py. If you're accessing the {{{Session}}} model for some reason, note that location change. |
| 497 | | === You can override table-level functions === |
| 498 | | |
| 499 | | 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. |
| 500 | | |
| 501 | | {{{ |
| 502 | | #!python |
| 503 | | from django.db import models |
| 504 | | class PersonManager(models.Manager): |
| 505 | | def get_list(self, **kwargs): |
| 506 | | # Changes get_list() to hard-code a limit=10. |
| 507 | | kwargs['limit'] = 10 |
| 508 | | return models.Manager.get_list(self, **kwargs) # Call the "real" get_list() method. |
| 509 | | |
| 510 | | class Person(models.Model): |
| 511 | | first_name = models.CharField(maxlength=30) |
| 512 | | last_name = models.CharField(maxlength=30) |
| 513 | | objects = PersonManager() |
| 514 | | }}} |
| 515 | | |
| 516 | | If a manager needs to access its associated class, it should use {{{self.model}}}. Example: |
| 517 | | |
| 518 | | {{{ |
| 519 | | #!python |
| 520 | | class PersonManager(models.Manager): |
| 521 | | def get_fun_person(self): |
| 522 | | try: |
| 523 | | return self.get_object(fun__exact=True) |
| 524 | | except self.model.DoesNotExist: |
| 525 | | print "Doesn't exist." |
| 526 | | }}} |
| 527 | | |
| 528 | | |
| 529 | | |
| 530 | | |
| 531 | | |
| | 590 | === You can override default QuerySets === |
| | 591 | |
| | 592 | You can specify the default QuerySet (see "Descriptor fields" above) that a manager uses. For example: |
| | 593 | |
| | 594 | {{{ |
| | 595 | #!python |
| | 596 | class PublishedBookManager(models.Manager): |
| | 597 | def get_query_set(self): |
| | 598 | return super(PublishedBookManager, self).get_query_set().filter(is_published=True) |
| | 599 | |
| | 600 | class Book(models.Model): |
| | 601 | title = models.CharField(maxlength=50) |
| | 602 | author = models.CharField(maxlength=30) |
| | 603 | is_published = models.BooleanField() |
| | 604 | published_objects = PublishedBookManager() |
| | 605 | }}} |