My Wiki!

Pro Django

Book: Pro Django 2nd ed. Apress

Try code:

  source $_env/bin/activate
  python manage.py shell
  >>> import xxx
  >>> def do_smt(xxx):
  ...
  

Django is Py

Base class

from django.db import models

class Contact(models.Model):
  name = models.CharField(max_length=255)
  email = models.EmailField()
 

Attribute Classes (CharField) look here:

 
  vim refman_env/lib/python2.7/site-packages/django/db/models/fields/__init__.py
  

Models

Setting Attributes on Models

Python provides useful tools for getting and setting attributes on objects without knowing the name in advance, but while getattr() and setattr() represent the standard way of accessing attributes on objects, one of Django’s hooks for model fields requires some additional handling. Django provides a class method, addtoclass(), on all of its models, which should be used as a substitute for setattr().

Getting infomation about models - _meta

Class information

Consider a situation where a model may be subclassed without inheriting all the Django-specific model inheritance processing. This requires a bit of tweaking with metaclasses, but can prove useful for solving certain types of problems. When doing this, the name and module attributes will refer to the child class, rather than the actual model that sits underneath.

  • meta.modulename: module where the object is defined.
  • meta.objectname: name of the classes.

Field Definitions

Django uses the creationcounter technique described in Chapter 2 to keep track of the order of fields, so they can be placed inside a list for future reference. This list is stored in the fields attribute of the model’s meta attribute.

meta.getfield('fname') to get single field by name.

from django.utils.text import capfirst
 
def get_values(instance):
  for field in instance._meta.fields:
    name = capfirst(field.verbose_name)
    value = getattr(instance, field.name)
    print('%s: %s' % (name, value))
class Product(models.Model):
  sku = models.CharField(max_length=8, verbose_name='SKU')
  name = models.CharField(max_length=255)
  price = models.DecimalField(max_digits=5, decimal_places=2)
 
  def __unicode__(self):
    return self.name
 
>>> from django.utils.text import capfirst
>>> for field in Product._meta.fields:
...   print('%s: %s' % (capfirst(field.verbose_name), field.__class__))
...
ID: <class 'django.db.models.fields.AutoField'>
SKU: <class 'django.db.models.fields.CharField'>
Name: <class 'django.db.models.fields.CharField'>
Price: <class 'django.db.models.fields.DecimalField'>
>>> Product._meta.get_field('name').__class__
<class 'django.db.models.fields.CharField'>

Primary Key Fields

Django provides another _meta attribute, pk, which contains the field object that will be used as the primary key for the model. This is also faster than iterating over all the fields, since pk is populated once, when the model is first processed. After all, Django needs to determine whether it needs to provide an implicit primary key. The _meta.pk attribute is also used to enable the pk shortcut property on model instances, which returns the primary key value for an instance, regardless of which field is the primary key.

Django provides two attributes on the meta attribute that help with this situation. The first, meta.hasautofield, is True if the model let Django provide an id field implicitly. If it’s False, the model has an explicit primary key, so Django didn’t have to intervene.

The second attribute related to the automatic primary key field is meta.autofield, which will be the actual field object Django provided for use as the primary key. If meta.hasautofield is True, this will be an AutoField, and will always be configured the same way for all models that use it. It’s important to look at this attribute instead of making assumptions about the field’s structure, in case Django makes any changes in the future. It’s an easy way to help make sure your application keeps working properly in the future. If a model provides its own primary key field, and thus _meta.hasautofield is False, _meta.autofield will be set to None.

Configuration Options

abstract app_label db_table

Accessing the Model Cache

Once models have been processed by the ModelBase metaclass, they’re placed in a global registry called AppCache, located at django.db.models.loading.

Retrieving All Applications

The first step in a site-wide introspection is to determine what applications are installed. Calling cache.getapps() will return such a list, containing the application module for each application in the INSTALLEDAPPS setting that contains a models module. That’s not to say that it only returns applications that have models. It actually checks for the presence of a models module, so even an empty models.py will cause an application to be included in this list. Take, for example, the following INSTALLED_APPS setting, showing several of Django’s own contributed applications, as well as some in-house applications and the signedcookies application described in Chapter 7.

INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'news',
'customers',
'callcenter',
'signedcookies',
)

Most of these applications will, by necessity, contain various models. Chapter 7’s signedcookies, however, only interacts with the site’s HTTP traffic, so it has no use for the database. Therefore, when looking through the results of cache.get_apps(), the signedcookies application won’t show up.

>>> from django.conf import settings
>>> from django.db.models.loading import cache
>>> len(settings.INSTALLED_APPS)
9
>>> len(cache.get_apps())
8
>>> for app in cache.get_apps():
...
print(app.__name__)
...
django.contrib.admin.models
django.contrib.auth.models
django.contrib.contenttypes.models
django.contrib.sessions.models
django.contrib.sites.models
news.models
customers.models
callcenter.models

Retrieving a Single Application

Django provides a utility for handling this situation. By passing the known label to cache.getapp(), an application can retrieve the application module for just the application matching that particular label. The label referred to here is determined as a specific part of the application’s import path. Typically referenced as applabel, an application’s label is usually formed from the last part of the application module’s import path before the models portion. To illustrate a few examples, consider the following application labels, corresponding to the entries in the INSTALLED_APPS setting.

 
admin
auth
contenttypes
sessions
sites
news
customers
callcenter
signedcookies

As demonstrated earlier with cache.getapps(), applications without models are viewed slightly differently within Django itself than others. By default, cache.getapp() will raise an ImproperlyConfigured exception if the application doesn’t contain a models.py file. Sometimes it may still be useful to process applications without models, so cache.getapp() accepts an optional second argument to control how such applications are handled. This second argument, called emptyOK, takes a Boolean indicating whether the application is allowed to not contain any models. This defaults to False, which will raise the ImproperlyConfigured exception, but if True is given instead, cache.getapp() will simply return None, allowing the calling code to continue managing the application.

>>> from django.db.models.loading import cache
>>> print(cache.get_app('admin'))
<module 'django.contrib.admin.models' from ...>
>>> print(cache.get_app('signedcookies'))
Traceback (most recent call last):
...
django.core.exceptions.ImproperlyConfigured: App with label signedcookies could not be found
>>> print(cache.get_app('signedcookies', emptyOK=True))
None

Dealing with Individual Models

In the first case, consider pure introspection. Remember from the previous section that AppCache provides access to all known applications with a single call to the getapps() method, which returns application modules. Since these modules are actually the models modules within each application, it may seem easy to just use dir(appmodule) or iterate over appmodule.dict_ to get the models that were defined.

cache.getmodels() retrieves a list of proper Django models that are specific to the given application module. It’s no coincidence that both cache.getapps() and cache.getapp() return application modules; cache.getmodels() is suitable for use with both of these methods. That means that a list of models can be retrieved even without an application, but knowing the application in advance reduces the number of models retrieved. The following code demonstrates how these techniques can be used in combination to retrieve a list of models for each of the known applications in use on the site.

>>> from django.db.models.loading import cache
>>> for app in cache.get_apps():
...
app_label = app.__name__.split('.')[-2]
...
for model in cache.get_models(app):
...
print('%s.%s' % (app_label, model.__name__))
...
admin.LogEntry
auth.Message
auth.Group
auth.User
auth.Permission
contenttypes.ContentType
sessions.Session
sites.Site
news.News
customers.Customer
callcenter.Agent
callcenter.Call
callcenter.Case
 

As an additional option, get_models() can also be called with no argument, which will cause it to return all the models that are known to AppCache. This is a useful shortcut to avoid some of the overhead associated with the extra loop in this example, as a quick way to grab all the models.

There’s a catch, however.

When using getmodels() directly, with no argument, all registered models are returned. This may sound like a great idea, and sometimes it is, but remember that AppCache registers all models as they’re encountered, regardless of where they were found. The full list may include models that aren’t part of an installed application. Contrast that with the getapps()/getmodels() combination, which only retrieves models if their applications are found in the INSTALLEDAPPS setting.

Using Model Fields

Common Fields Attributes

  • attname
  • blank
  • choices: A sequence of 2-tuples indicating the valid choices for the field. The first item in each tuple is the actual value that would be stored in the database if selected, while the second item is the text that will be displayed to the user for that value.
  • column
  • dbcolumn * dbindex
  • db_tablespace

Common Field Methods

  • clean(value, instance)
  • contributetoclass(cls, name)

Subclassing Fields

URLs and Views


Navigation