Django Flashcards
How Django orders class attributes
class BaseAttribute(object):
__creation_counter = 1
__def __init__(self):
____self.creation_counter = BaseAttribute.creation_counter
____BaseAttribute.creation_counter += 1
Required ordering for argument types
- Required arguments - func(arg1, arg2)
- Optional arguments - func(arg1 = 1)
- Excess positional args - func(*args)
- Excess keyword args - func(**kwargs)
Descriptors
2 methods
class CurrentDate(object):
__def __get__(self, instance, owner):
____return datetime.date.today()
__def __set__(self, instance, value):
____raise NotImplementedError(“Can’t change date”)
class Example(object):
__date = CurrentDate()
e = Example()
e. date ## returns today
e. date = datetime.date.today()## raises error
instance - instance object containing attribute referenced, e in this case.
owner - class where descriptor was assigned. Example in this case
Descriptors short-circuit attribute access, so their values cannot be set with setattr - this would call the descriptor again and result in infinite recursion.
using __dict__ does the trick.
class Descriptor(object):
__def __init__(self, name):
____self.name = name
__def __get__(self, instance, owner):
____return instance.__dict__[self.name]
__def __set__(self, instance, value):
____instance.__dict__[self.name] = value
Common class and function attributes
- __name__ - name used to declare
- __doc__ - docstring for class or function
- __module__ - import path of the module where the class/function was declared
- __class__ - actual class object
Tracking subclasses
class SubclassTracker(type):
__def __init__(cls, name, bases, attrs):
____try:
______if TrackedClass not in bases:
________return
____except NameError:
______return
____TrackedClass._registry.append(cls)
class TrackedClass(metaclass=SubclassTracker):
__ _registry = []
class ClassOne(TrackedClass):
__pass
TrackedClass._registry
[<class>]</class>
etc….
Order of operations when processing model class
10 steps
metaclass for models is ModelBase. It is at django.db.models.base
- new class generated. preserve the module location where model is defined.
- if no custom_app label, it’s determined based on module location
- Meta options are pulled from model and placed in special Options object
- Special exception classes created. DoesNotExist and MultipleObjectsReturned
- Default manager assigned if not provided
- If model was already defined (based on importing from different stages), existing model is retrieved from the application cache.
- Attributes and methods defined on original model are added to the newly created model class
- Settings from inherited parent models are set
- New model is registered with application cache for future reference
- Newly created model is returned to be used in place of the class defined in the source file
Setting attributes on models
getattr() and setattr()
these are usually used, but one of Django’s hooks for model fields requires additional handling.
add_to_class()
a class method which checks the provided value for a contribute_to_class() method, calls if it exists. If it doesn’t, it uses setattr()
Pass any object in, it will be handled identically if you called setattr()
Getting Information about Models
Original structure can be determined via _meta attribute on every django model and instance.
- describes the model
- how it was defined
- values provided to customize behavior
Two groups of the above things
- attributes determined by looking at original class
- attributes specified directly as part of a Meta class defined inside model
_meta has:
- installed - bool, whether it’s installed
- fields - list of fields
- module_name - contains __module__ attribute from underlying model
- object_name - contains __name__ of underlying model
the last two deal with problems arising from not knowing the parent class of a given django model.
Starting off in the Django shell
from django.db.models.loading import cache
from django.db.conf.settings import *
cache. get_apps()
cache. get_app(‘viz’)
cache. get_models(cache.get_app(‘viz’))
cache. get_model(‘viz’, ‘optional’)
Common Field Attributes
21 total
- attname - name of the attribute on model instances where the related value is stored. typically same as name. When more appropriate to expose a complex object, name holds that object and attname holds the raw data to create it.
- blank - a bool indicating whether field must have a value supplied when using a form generated automatically based on the model. null controls whether a model can be saved without a value** **
- choices - sequence of 2-tuples indicating valid choices for field. First is the actual value stored in the db, second is text displayed to user.
- column - name of db column used to hold the field’s value. normally ignorable.
- db_column - explicitly supplied as db column name for the field’s values. db_column refers to what the model itself declared, rather than what will be used. usually None
- db_index - bool indicating whether the field was declared to have an index.
- db_tablespace - oracle specific, physical location
- default - default value for field. Will be used as initial value for forms based on model.
- description - can be used when displaying info about the field inside an app
- editable - bool indicating whether the field should be presented to users for editing when generating forms based on the model.
- empty_strings_allowed - boolean
- help_text - informative text provided in the field def to be displayed in forms when presented for editing
- max_length -
- name - name of the attribute where the field’s native Python value will be retrieved and assigned. attname stores raw data needed to populate name
- null - boolean whether field can be committed to db without a value
- primary_key - boolean indicating whether it is the pk for the db table.
- rel - when fields that relate one model to another, it’s a special object describing various aspects of the relationship.
- serialize - bool whether the field should be included when model instances are serialized using serialization framework
- unique - bool indicates field must be unique among all instances of model.
- unique_for_date, unique_for_month, unique_for_year
- verbose_name - full name of the field, in plain English. Recommended use lowercase, use capfirst() as needed.
Common Field Methods
16 (some were left out)
- clean(value, instance) - internally, defers to to_python() and validate() as well as processing list of validators defined when field was instantiated
- contribute_to_class(cls, name) - configures field for the class it’s attached to. called when ModelBase is processing attributes on the model.
- db_type(connection) - returns db-specific column type necessary to store its data.
- formfield() - returns a form field based on field’s data type and verbose name. optionally takes explicit arg form_class, which is a form field class to be instantiated.
- get_attname() - Returns name to be used for attname attribute. Called once, when being configured for class.
- get_cache_name() - returns a name suitable for use as a cache for the field, if caching is necessary.
- get_choices() - returns a sequence of 2-tuples used for displaying choices. May include empty option - include_blank and blank_choice
- get_db_prep_lookup(value, lookup_type, connection, prepared=False) - representation of supplied value suitable for comparing against existing values in db
- get_db_prep_save(value, connection) - supplied value suitable to be stored in db
- get_db_prep_value(value, conn, prepared=False)
- get_default() - default value for field
- get_internal_type() - returns string of high-level idea of what type of data the field contains
- has_default()
- to_python(value) - coerces supplied value to a native python data type
- validate(value, instance) - returns without error if value is appropriate for fields configuration. ValidationError otherwise.
- value_from_object(obj) - returns field’s value as it appears on the supplied object
Subclassing Fields
5 methods on fields
Django uses duck typing for fields, or things that look like fields. You don’t have to inherit from fields at all.
- contribute_to_class(self, cls, name) - ability for field to know what class it’s assigned on. called instead of setattr() and allows field to register itself in whatever way is most appropriate. cls is the actual class assigned to it, name is the name given at assignment (not known with normal descriptors). Method should do what it must with this info and return nothing
- contribute_to_related_class(self, cls, related) - called once related model is available so attributes can be added to that model as well. This is how Django provides a reverse attribute on a related class when ForeignKey is applied. cls is the class the relationship was applied to, related is the model it points to.
- get_internal_type(self) - returns a string which helps determine how db should store values for the field. String isn’t an actual db column type, rather applied to a mapping provided by the db backend. Means fields can be written without being tied to specific db backend
- validateself, value, instance) - used to determine whether field’s contents are valid. Can also be validated against values in rest of model via presence of instance
- to_python(self, value) - needs to handle a lot of different values coming back from db adapter. Needed for complex values - length of time turned to timedelta, for example
How to call to_python() every time
from django.db.models.fields.subclassing import SubfieldBase
from django.db import models
class DurationField(models.DecimalField, metaclass=SubfieldBase)
__pass
__#field logic here