Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Lesson 7 - A Deeper Dive into Models

Lesson 7 - A Deeper Dive into Models

Dana Spiegel

October 28, 2012
Tweet

More Decks by Dana Spiegel

Other Decks in Education

Transcript

  1. Quick Review • MVC for web apps • Django models,

    fields, and relationships • Django shell • syncdb • Using models for querying, inserting, and deleting • Using related fields in models 2
  2. Field Options • All fields support certain standard parameters used

    when they are created • Offer a way to influence database column definition, Django admin (more on this later), or general usage • default: provides a default value when the object is created; can either be a value, or a “callable” • db_index: adds database index for the column • unique: adds database index for the column making it unique (all rows) • null: indicates that the field is NULL-able in the database • blank: field can be blank (unrelated to DB); if False, field is required • editable: if False, field won’t be displayed in admin or in forms • help_text: extra text that will be displayed in a form • error_messages: dict of user facing error messages for form errors (null, blank, invalid, invalid_choice, and unique) • verbose_name: human readable name for field 3 contact_info = CharField(default = lambda: uuid.uuid4().hex)
  3. Field Options (cont’d.) • choices: used for CharField in order

    to restrict the options available • Think dropdown list or checkboxes in a web form • Defined in a constant as an iterable of 2-tuples of the form: • (value, human-readable name) • First element will be stored in the database as the value for that field • Second element will be shown to users in forms for selection • Use Model.get_FOO_display() to get the human readable version of the Foo field 4 YEAR_IN_SCHOOL_CHOICES = ( ('FR', 'Freshman'), ('SO', 'Sophomore'), ('JR', 'Junior'), ('SR', 'Senior'), ('GR', 'Graduate'), ) year_in_school = models.CharField(max_length=2, choices=YEAR_IN_SCHOOL_CHOICES)
  4. Working with Fields: Numbers • IntegerField is used for most

    number storage • Stores 4 bytes of data - (28) * 4 = -2,147,483,648 to +2,147,483,647 • PositiveIntegerField should be used when you only care about values > 0 • Stores 4 bytes of data - (28) * 4 = 0 to 4,294,967,295 • BigIntegerField is used if you need to store a much larger number (like some ids) • Stores 8 bytes of data - (28) * 8 = -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 • SmallIntegerField stores only 2 bytes of information (not really that useful) • (28) * 2 = -32,768 to 32,787 • PositiveSmallIntegerField can be used much like PositiveIntegerField • DecimalField stores a fixed precision decimal number, using a python Decimal number • Requires 2 arguments: max_digits and decimal places • FloatField stores a floating point number (not fixed precision) as a float 5
  5. Working with Fields: More Numbers • CommaSeparatedIntegerField is used to

    store a list of numbers, separated by commas • Stored as a text field in the database • Not available for computation and aggregation at the database level • Requires a max_length parameter (like a text field) to limit its size 6
  6. Working with Fields: Booleans • BooleanField is used to keep

    track of True/False values or “flags” • They can be used for settings, like “send email alerts” • Sometimes stored as 1 bit ints in the database (MySQL) • Useful for database queries like: • find all users that have email alerts turned on • Users.objects.filter(email_alerts=True) • Sometimes, its useful to know if a flag has been set: • Similar to 3-way switches: on, off, unset • Use a NullBooleanField, which can also have the value of None • Use the default parameter on the field to indicate the default value you want for this field when an object is created 7
  7. Working with Fields: Text • CharField is the standard way

    to store text in models • Uses a varchar in the database • Has a limit of 255 characters, making it great for storing names, address fields, labels, etc. • Requires max_length to enforce a maximum amount of text • TextField is used for storing larger text values • Can store up to 4,294,967,295 characters (4GB!) • Don’t store that much information in the database; use files! • Good for longer text values, like descriptions or a few paragraphs of text • SlugField keeps a text identifier useful for URLs (like in blogs) • Allows only letters, numbers, underscores, and hyphens • The EmailField validates that the text is an valid email address • URLField validates that the text is a valid URL (but won’t check existence) 8
  8. Working with Fields: Dates • DateTimeField, DateField, TimeField used for

    keeping track of any date/time information • All 3 are used in the same way • All 3 use various datetime.* objects • Returned objects have no timezone associated with them, so be sure to always store UTC dates/times • datetime.datetime.utcnow() vs. now() • Useful parameters: • auto_now will set the field to the current time whenever it is saved; useful for updated_on • auto_now_add will set the field to the current time only upon creation; useful for created_on 9 >>> datetime.datetime.utcnow() datetime.datetime(2012, 10, 27, 0, 5, 17, 296049) >>> datetime.datetime.now() datetime.datetime(2012, 10, 26, 20, 5, 30, 33746)
  9. Using Fields: Address 10 COUNTRIES = ( ('US', 'United States

    of America'), ... ) ADDRESS_TYPES = ( ('W', 'Work'), ('H', 'Home'), ('O', 'Other'), ... ) class Address(models.Model): person = models.ForeignKey('Person', related_name='addresses') type = models.CharField(max_length=1, choices=ADDRESS_TYPES, db_index=True) street_address_1 = models.CharField(max_length=100) street_address_2 = models.CharField(max_length=100, blank=True) city = models.CharField(max_length=100, blank=True) state_province = models.CharField(max_length=100, db_index=True) postal_code = models.CharField(max_length=10) country = models.CharField(max_length=2, choices=COUNTRIES, db_index=True) is_primary_address = models.BooleanField(default=True, db_index=True) https://github.com/danaspiegel/hatchery-code/blob/master/project/models.py
  10. Using Fields: Parking Lot 11 from django.db import models LOT_TYPES

    = ( ('S', 'Street Lot'), ('M', 'Multi-level Above Ground'), ('O', 'Multi-level Below Ground'), ) SPOT_SIZES = ( ('S', 'Standard'), ('C', 'Compact'), ('T', 'Truck'), ('U', 'Unusable'), ) ORIENTATIONS = ( ('N', 'North'), ('NE', 'North East'), ('E', 'East'), ) class Lot(models.Model): name = models.CharField(max_length=100) slug = models.SlugField(max_length=100) lot_type = models.CharField(max_length=1, choices=LOT_TYPES, db_index=True) open_time = models.TimeField('Lot opens') ... https://github.com/danaspiegel/hatchery-code/blob/master/parking_lot/models.py
  11. Model Meta Options 12 • When defining a Model, you

    can specify Meta options • Inform Django how to handle certain aspects of your Model • ordering: provides a default ordering to use when querying objects; incurs a cost, so don’t use it unless necessary; can take a - (negative) • permissions: a collection of 2-tuples that define additional permissions to be used by Django’s permissions system (not covered) • unique_together: collection of 2-tuples that should be treaded as unique together by creating a compound index in the database • verbose_name: used by Django admin for labeling the model • verbose_name_plural: used by Django admin for labeling multiple of the model
  12. Validators • Small methods that are used to ensure fields

    conform to certain criteria • Specified when creating a field • Work at the python level, not the database level, so more functional, but logic won’t reside in database • Useful ones live in module django.core.validators, but you can write your own • Used for both Models and Forms (more on this when we cover Forms) • When saving an object, you must explicitly call full_clean; Validators aren’t enforced on save()! 13 https://docs.djangoproject.com/en/1.4/ref/forms/validation/ from django.core.validators import * class Foo(models.Model): bar = models.CharField(max_length=100, validators=[MinLengthValidator(3)]) pct = models.IntegerField(validators=[ MinValueValidator(0), MaxValueValidator(100)])
  13. Advanced Querying • Use all() to get all objects for

    a given Model • Returns a QuerySet, which efficiently iterates over all items • Use values() or values_list() to get just dicts or tuples of data • Name the fields you want, including related fields • You can use multiple filters to shave down your queryset • Also, you can filter on related fields • Use exclude() to invert the filtering logic • Aggregate queries run computation on columns with group_by, returning the results • Annotate works like Aggregate queries, but work on related objects 14 Lot.objects.values('name', 'spots__level', 'spots__designation') Lot.objects.filter(lot_type='M').filter(spots__level=-1) Lot.objects.exclude(lot_type='M') rates = Lot.objects.all().aggregate(avg=Avg('hourly_rate'), max=Max('hourly_rate')) lots_with_spots = Lot.objects.annotate(spots_count=Count('spots'))
  14. In Class: Using tools • Use parking_lot models and add

    more data and practice querying • How would I get a count of all Spot types in each Lot? • Homework: • Start building models for a Softball Team tracker • Keep track of: • Roster • Games • Players playing • Innings • Box score • At bats, walks, runs, 1B, 2B, 3B, HR, strikeouts for each player in game • Can you compute a player’s batting average? 15