Django

Dev Week -- Django and you -- mhall119 -- Fri, Jul 16th, 2010

(11:55:39 AM) mhall119: While we're waiting, if anybody isn't familiar with Django, please take a quick look here: http://www.djangoproject.com/
(11:56:30 AM) mhall119: also, if you plan on following along with our actual code, you might want to go ahead and sudo apt-get install python-django
(12:00:47 PM) mhall119: alright, time to get things started
(12:01:26 PM) mhall119: First off, my name is Michael Hall, I'm a software developer for the Moffitt Cancer Research Center in central Florida
(12:01:58 PM) mhall119: We use Django extensively for internal applications that support our medical research studies
(12:02:22 PM) mhall119: I'm also one of the loco-directory hackers (http://loco.ubuntu.com), which is also based on Django
(12:02:59 PM) mhall119: Django is a web application framework for Python, it's a lot like J2EE is for Java, only much much easier
(12:03:42 PM) mhall119: You can get Django from http://www.djangoproject.com/ or apt-get install python-django if you're on Ubuntu
(12:04:12 PM) mhall119: today's class is going to be 2 hours long, which still isn't enough time to cover everything you can do with Django
(12:04:28 PM) mhall119: so we're going to be covering enough to get a very simple web app up and running
(12:04:54 PM) mhall119: there will be code involved, if you have django I'll help you get it up and running on your local box
(12:05:11 PM) mhall119: if you don't have Django, I still recommend getting the code with us, so you can follow along
(12:05:49 PM) mhall119: in the first hour, we'll just be getting django setup with a very simple "hello world" type app
(12:06:10 PM) mhall119: in the second hour we'll start creating data models, which is where django really makes programming fun and easy
(12:06:24 PM) mhall119: so if you can stick around for both session, I'd highly recommend it
(12:06:45 PM) mhall119: before we get started, any question on Django in general?
(12:07:05 PM) mhall119: < saji89> QUESTION:does a web framework differ from a CMS?
(12:07:23 PM) mhall119: yes, a web framework is more low-level than a CMS
(12:07:44 PM) mhall119: at it's most basic, it run redirects queries to a URL to come piece of code you've written to handle it and return a response
(12:08:26 PM) mhall119:  < abuazzam> QUESTION is there any alternative to django? why django is better? sorry for my  english
(12:08:51 PM) mhall119: Yes, there are alternatives.  Zope is another python web framework, it's what Launchpad is built on
(12:09:07 PM) mhall119: I don't have as much experience with Zope, so I won't go into which is better or why
(12:09:56 PM) mhall119: any other questions before we start working on code?
(12:10:17 PM) mhall119: okay
(12:10:45 PM) mhall119: if you have Django installed, it provided a command line tool to help you bootstrap your project
(12:10:58 PM) ClassBot: abhijit asked: i know about qunta plus. is django similar to it?
(12:11:06 PM) mhall119: I'm not familiar with qunta, sorry
(12:11:39 PM) mhall119: okay, so to start a django project, you run django-admin $projectname
(12:11:52 PM) mhall119: for these classes, we're going to make a cookbook app
(12:12:02 PM) mhall119: so I ran: django-admin startproject cookbook
(12:12:20 PM) mhall119: sorry, forgot the "startproject" command in the first example
(12:13:07 PM) mhall119: instead of doing that, I'd like everyone to run this: bzr branch -r tag:mkproject lp:~mhall119/+junk/cookbook
(12:13:30 PM) mhall119: that will get you a copy of my cookbook branch as it is after running startproject
(12:17:36 PM) mhall119: sorry for the confusion, it seems you need to have an ssh key registered with Launchpad to run the bzr command
(12:17:43 PM) mhall119: those who don't can view the code here: http://bazaar.launchpad.net/~mhall119/+junk/cookbook/revision/1
(12:18:15 PM) mhall119: as you'll see, Django creates a few files for you, I'll quickly go over each
(12:18:44 PM) mhall119: manage.py is going to be the script you use to work with your project
(12:18:50 PM) mhall119: you'll see more of that later
(12:19:15 PM) mhall119: settings.py is where you configure your project, giving it DB connection information, telling it which apps to include, etc
(12:19:44 PM) mhall119: A django project is comprised of multiple django applications, which means you can mix and match existing applications with your own custom ones to build your project
(12:20:51 PM) mhall119: finally, urls.py is where you map a url pattern to a python function that will handle requests to it
(12:20:59 PM) abhijit_ is now known as abhijit
(12:21:21 PM) mhall119: okay, so next we need to create our custom application
(12:21:35 PM) mhall119: for that I ran "django-admin startapp recipes"
(12:21:39 PM) mhall119: but you don't have to do that
(12:21:56 PM) mhall119: if you have the bzr branch, just run bzr pull -r tag:mkapp
(12:22:04 PM) mhall119: that will update your local copy with the app's files
(12:22:35 PM) mhall119: this creates a "recipes" folder under your project folder
(12:22:54 PM) mhall119: ( I should have said to cd into the cookbook project folder first)
(12:23:30 PM) ClassBot: nite asked: what do you need to have to work withdjango?
(12:23:38 PM) mhall119: all you need is python and django
(12:23:55 PM) mhall119: you can also run Django behind apache, using mod_wsgi or mod_python
(12:24:09 PM) mhall119: but django has a built-in web server that is very useful for local development
(12:24:16 PM) mhall119: that's what we'll be using today
(12:24:35 PM) ClassBot: Nervengift95 asked: is there a difference between the bzr branch and the files created by the django commands?
(12:24:53 PM) mhall119: nope, I ran those command and commited the files they created directly into the branch
(12:25:02 PM) ClassBot: abhijit asked: do I need to know python to use django?
(12:25:17 PM) mhall119: yes, since you will be programming a web app, you will need to know the language
(12:25:28 PM) mhall119: this is another way a web framework differs from a CMS
(12:25:40 PM) mhall119: but python is very easy to learn, so don't let that discourage you
(12:25:54 PM) ClassBot: saji8973 asked: So, bzr is not an absolute requirement?
(12:26:06 PM) mhall119: correct, you don't need bzr to use django,  I'm just using it for this class
(12:26:28 PM) mhall119: okay, moving on
(12:26:42 PM) mhall119: you should now have your 'recipes' app folder, lets look at what's in there
(12:26:56 PM) mhall119: models.py you can ignore for now, we'll come back to that in the next hour
(12:27:07 PM) mhall119: test.py we're not going to touch on at all, that's a topic for another day
(12:27:15 PM) mhall119: so that only leaves us with views.py
(12:27:49 PM) mhall119: for those who can't get bzr working, you can look at the files here: http://bazaar.launchpad.net/~mhall119/+junk/cookbook/revision/2
(12:28:21 PM) mhall119: as you can see, views is currently empty
(12:28:43 PM) mhall119: Django follows a Model-View-Template model, which is analogous to MVC
(12:29:13 PM) mhall119: a Django view is nothing more than a Python function that takes an HttpRequest object as an argument
(12:29:47 PM) mhall119: so if you run: "bzr pull -r tag:welcome" we'll get our first view
(12:31:48 PM) mhall119: now if you look at views.py, you will see our first view
(12:32:26 PM) mhall119: it also made a couple changes to cookbook/settings.py and cookbook/urls.py
(12:32:42 PM) mhall119: in settings.py, we added our 'recipes' app to the INSTALLED_APPS array
(12:32:46 PM) mhall119: at the bottom of the file
(12:33:10 PM) mhall119: that tells Django that we want to include that app in our project
(12:33:43 PM) mhall119: above it you see some of Django's built in apps that are installed by default to give you the functionality you'd expect from a web framework
(12:34:03 PM) mhall119: next if you look at urls.py, you'll see we added a single entry at the bottom
(12:34:43 PM) mhall119: this tells django that any request to this server who's path matches '^welcome/', pass the request on to the welcome function
(12:35:09 PM) ClassBot: Error404NotFound asked: Is it really essential to have an application? We can host views.py urls.py models.py and other such in project directory and access them. Which is better and why? Also how does Django compare to its PHP alternates such as Zend, CakePHP?
(12:35:31 PM) mhall119: true, your views can exist outside of application directories
(12:35:51 PM) mhall119: but using applications helps keep your code separate and modular
(12:36:06 PM) mhall119: which helps reusability and readability
(12:36:29 PM) mhall119: I'm not familiar enough with PHP frameworks to make a comparison
(12:37:23 PM) mhall119: okay, now that we have our app and our view, it's time to see it in action
(12:37:32 PM) mhall119: from the project's directory, run: ./manage.py runserver
(12:37:52 PM) mhall119: this will start Django's built-in webserver on http://127.0.0.1:8000/
(12:38:36 PM) mhall119: if you go there in a browser, you will see a lovely 404 page like this: http://family.ubuntu-fl.org:8002/
(12:38:51 PM) mhall119: why the 404?
(12:39:12 PM) mhall119: because the only URL we have mapped is /welcome, Django doesn't know what to do with just /
(12:39:45 PM) mhall119: try it again with /welcome at the end
(12:39:55 PM) mhall119: you should see something more like http://family.ubuntu-fl.org:8002/welcome/
(12:40:27 PM) mhall119: which is nothing more than the text string we put into our HttpResponse object in our welcome view
(12:42:03 PM) mhall119: as Error404NotFound just mentioned, you will see that page a lot when writing your django app, as well as the 500 error page
(12:42:34 PM) mhall119: the 404 shows you what url patterns Django is looking for, so if you have a typo or something, it makes it easy to compare and find
(12:43:10 PM) mhall119: the 500 page will give you a stacktrace of the calls leading up to the error, as well as the values of local variables in those calls, it's very useful for tracking down the source of errors
(12:43:46 PM) mhall119: now, as easy as it is to throw a string into HttpResponse and return it, you don't really want to do that for an entire page of HTML
(12:44:03 PM) mhall119: so Django provides a built-in templating system
(12:44:26 PM) mhall119: if you now run: "bzr pull -r tag:addtemplate" you will see how that works
(12:45:07 PM) mhall119: that revision pulls in recipes/media and recipes/templates directories
(12:45:36 PM) mhall119: by default, Django will look for template files in $app/templates/ for any installed application
(12:45:44 PM) mhall119: (another good reason for using applications)
(12:46:09 PM) mhall119: if you take a look at templates/welcome.html, you'll notice it's not 100% HTML
(12:46:23 PM) mhall119: it contains markup for Django's custom template language
(12:46:52 PM) mhall119: you can't use straight Python in Django templates, which makes them a little less powerful by themselves compared to regular PHP
(12:46:57 PM) mhall119: but it does make them very fast
(12:47:21 PM) mhall119: and you can extend the template language with your own tags (which we won't cover today, sorry)
(12:48:26 PM) mhall119: right now the only tag we're using in welcome.html is {{MEDIA_URL}}
(12:48:48 PM) mhall119: Django templates use {{ }} for variable substitution
(12:49:00 PM) mhall119: which means MEDIA_URL is a variable name in teh templates context
(12:49:09 PM) mhall119: how did it get there?  take another look at your views.py
(12:49:36 PM) mhall119: now, instead of returning an HttpResponse object, we're calling render_to_response
(12:49:55 PM) mhall119: which itself is just a helper function that renders the template to an HttpResponse object for you
(12:50:08 PM) mhall119: the first parameter is the name of the template file to use
(12:50:26 PM) ClassBot: There are are 10 minutes remaining in the current session.
(12:50:27 PM) mhall119: the second is a python dictionary of name/value pairs, this is the template's context
(12:51:14 PM) mhall119: recipes.MEDIA_URL is defined in cookbook/recipes/__init__.py, it's just a base URL path for the recipes/media folder
(12:51:59 PM) mhall119: if you look again at cookbook/urls.py, you'll see that there is an extra line mapping urls with that base to Django's built-ind static.serve view
(12:52:29 PM) mhall119: if you are running behind Apache, you'll set your apache conf to serve those files basedon that url, bypassing Django all together, which is more efficient
(12:53:00 PM) mhall119: now if you go back to your welcome page you will see this: http://family.ubuntu-fl.org:8002/welcome
(12:53:28 PM) mhall119: and before anyone says it, I know my HTML is horrible, and my graphic is lame
(12:53:55 PM) mhall119: one last thing in this hour
(12:54:05 PM) mhall119: run: "bzr pull -r tag:showdebug"
(12:54:35 PM) mhall119: and refresh your browser
(12:54:44 PM) mhall119: you'll see now a red bar saying you're in debug mode
(12:54:53 PM) mhall119: look again at welcome.html to see how I did that
(12:55:22 PM) ClassBot: There are are 5 minutes remaining in the current session.
(12:55:55 PM) mhall119: notice the {% if settings.DEBUG %} {% endif %} tags
(12:56:16 PM) mhall119: if/else/endif lets you conditionally display blocks of your template depending on the values of context variables
(12:56:48 PM) mhall119: in this case, it's getting the value from our settings.py file
(12:57:14 PM) mhall119: and that's the end of this hour, any question on what we've covered so far?
(12:57:58 PM) ClassBot: ean5533 asked: Is there anything Django CAN'T do?
(12:58:14 PM) mhall119: At this point, I haven't figured out how to make it serve me coffee
(12:58:30 PM) mhall119: joking aside, since your views are in python, it can do pretty much anything you can do in python
(12:58:53 PM) ClassBot: lousygarua asked: how are the {% and %}'s quicker than <?php ?>?
(12:59:06 PM) mhall119: I don't know about quicker, it's just what Django uses
(12:59:18 PM) mhall119: {% %} denotes a tag, while {{ }} denotes variable substitution
(12:59:40 PM) mhall119: tags are bits of python code that operate on values passed to them, or wrapped in them
(12:59:59 PM) ClassBot: ubuntufreak16 asked: You mentioned about the red bar with debug mode but that didn't happen for me is it because i use chromium ?
(01:00:06 PM) mhall119: I'm using chromium, so that's not it
(01:00:27 PM) mhall119: did you do the last bzr pull?  Also, check that settings.py DEBUG == True
(01:00:40 PM) mhall119: should be on line 3
(01:01:17 PM) mhall119: ubuntufreak16: try restarting the django server then, you usually don't have to do that though
(01:01:58 PM) ClassBot: Nervengift95 asked: i get a 404 that /welcome doesn't match ^welcome$ whats wrong?
(01:02:05 PM) mhall119: make sure you don't have a / at the end of the url
(01:02:21 PM) mhall119: this is my mistake, I removed it from the original url pattern at some point
(01:03:31 PM) mhall119: okay, I'm going to take a 2 minute break, let everyone run to the restroom or refill their coffee
(01:03:44 PM) mhall119: because the next hour is going to be kind of fast, and you won't want to miss any of it
(01:07:15 PM) mhall119: okay, everybody back now?
(01:08:13 PM) tsduncan_ is now known as tsduncan
(01:09:08 PM) mhall119: alright, I hope everyone is back by now
(01:09:24 PM) mhall119: so, if Django views are simple, Django models are magic
(01:09:53 PM) mhall119: models are really at the heard of most Django applications, they define the data records you're going to be working with throughout your app
(01:10:13 PM) mhall119: and Django provides a very nice ORM layer between your model definitions and your database tables
(01:10:48 PM) mhall119: run "bzr pull -r tag:addmodels"
(01:11:38 PM) mhall119: first, lets look at the changes this made in our settings.py
(01:12:03 PM) mhall119: on line 12, we specified that the DATABASE_ENGINE we'll be using is sqlite3
(01:12:32 PM) mhall119: Django should make it so you never have to care about what database you're using
(01:12:41 PM) mhall119: and sqlite is convenient for development
(01:13:02 PM) mhall119: at Moffitt, we use sqlite3 for development, and MySQL or Oracle in production
(01:13:35 PM) mhall119: on line 13, we specify the file name to use for our Sqlite3 database
(01:14:08 PM) mhall119: now let's look at recipes/models.py
(01:14:37 PM) mhall119: in it you'll see that I've defined 4 data models for our cookbook application
(01:15:16 PM) mhall119: Django models are Python classes that extend django.db.models.Model
(01:15:28 PM) mhall119: in them, you define the fields your model will have
(01:16:16 PM) mhall119: Django comes with many predefined field types that will most likely cover everything you need
(01:16:22 PM) mhall119: the full list can be found here: http://docs.djangoproject.com/en/1.2/ref/models/fields/#ref-models-fields
(01:16:44 PM) mhall119: but you can also make your own custom fields if you ever needed to
(01:17:20 PM) mhall119: the first 2 models, Category and Ingredient, are pretty basic, they just contain a character field called "name"
(01:17:36 PM) mhall119: most of what we're interested in is in the Recipe model
(01:18:07 PM) mhall119: here we can create links to other models with the ForeignKey and ManyToMany field types
(01:18:48 PM) mhall119: category links a Recipe record to one Category record (a Category record can be linked to zero or more Recipes)
(01:19:11 PM) mhall119: and ingredients links one or more recipes to one or more ingredients
(01:19:43 PM) mhall119: if you don't include the "through" parameter on the ManyToMany field, Django will create the necessary linkage for you
(01:20:06 PM) mhall119: but in this case, I wanted to add additional information to that linkage, so I created another Measurement class
(01:20:19 PM) mhall119: this lets me add a quanity and unit field to the relationship between recipes and ingredients
(01:20:50 PM) mhall119: notice also that I am giving the "unit" field a list of choices
(01:21:22 PM) mhall119: Django will automatically create HTML form elements for you, based on your model definitions, and the "choices" parameter will make this field a <select>, rather than an <input>
(01:22:01 PM) mhall119: now that we have our model definition, Django can use them to build out database tables
(01:22:25 PM) mhall119: so we don't need to write any SQL create statements, or thinking about table structure
(01:22:37 PM) mhall119: Django does that all for us, and in a surprisingly efficient manner
(01:22:50 PM) mhall119: so, from your cookbook/ project folder, run ./manage.py syncdb
(01:23:10 PM) mhall119: syncdb tells Django to update the database with tables for any new models
(01:23:27 PM) mhall119: since we're using sqlite3, it will also create the cookbook.db file in our project's folder
(01:23:51 PM) mhall119: any questions so far?
(01:24:44 PM) ClassBot: ean5533 asked: What if you want to change your model? Does Django gracefully change the database structure?
(01:25:02 PM) mhall119: the short answer is no, syncdb is only smart enough to create a table if it's missing
(01:25:18 PM) mhall119: if you add or remove fields from your model after the fact, it won't touch the tables
(01:25:35 PM) mhall119: the long answer is "yes", but with the help of a Django application called South
(01:25:57 PM) mhall119: http://south.aeracode.org/
(01:26:31 PM) mhall119: South takes snapshots of our model defintions as you change them, and lets you automatically "migrate" your table structures to add or remove columns
(01:26:53 PM) mhall119: we have recently started using South at Moffitt, and also in the loco-directory project, and I've been very impressed with it
(01:27:03 PM) ClassBot: lousygarua asked: can you elaborate more on the ManyToMany field? I don't understand what it does
(01:27:25 PM) mhall119: basically, it will create an intermediate table, with foreign key links to both the model tables
(01:28:06 PM) mhall119: since we provided the Measurement model, and it has foreign key fields to both Ingredient and Reciple, it will use that
(01:28:20 PM) mhall119: I hope than answers your question
(01:28:36 PM) ClassBot: ubuntufreak asked: when i tried the command it showed me the Django's auth system to define a superuser, what is its purpose ?
(01:28:52 PM) mhall119: ah yes, in settings.py we have django.contrib.auth as one of our INSTALLED_APPS
(01:29:03 PM) mhall119: this gives us a user/group system to use in our project
(01:29:15 PM) mhall119: and as part of the setup for that app's models, it's going to ask you to create a superuser
(01:29:21 PM) mhall119: for this demo, just use root/password
(01:30:03 PM) mhall119: we won't really go into using access controls, but the Auth system is what lets you require user accounts and logins
(01:30:16 PM) mhall119: < ubuntufreak> mhall119, is it a one-time process specific to the app
(01:30:30 PM) mhall119: yes, it'll only ask you for that when you syncdb for the first time with the Auth app
(01:30:55 PM) mhall119: another very useful app that comes with Django is the Admin app
(01:31:01 PM) mhall119: django.contrib.admin
(01:31:21 PM) mhall119: which gives you a very generic interface to add/modify/delete records based on your model definitions
(01:31:55 PM) mhall119: do use it, we need to add it to our INSTALLED_APPS, create a url pattern for it, and most importantly tell it about our models
(01:32:10 PM) mhall119: so run "bzr pull -r tag:addadmin" from your project folder
(01:32:48 PM) mhall119: in settings.py, we just added django.contrib.admin to our INSTALLED_APPS list
(01:32:57 PM) mhall119: and in urls.py we uncommented the lines to enable it
(01:33:09 PM) mhall119: finally, we added the file recipes/admin.py
(01:33:16 PM) mhall119: let's take a look at that real quick
(01:34:05 PM) mhall119: the first three are very simple, we just register the model with the admin site, and it will use the field definitions in them to build our interface
(01:34:16 PM) mhall119: but for Recipe, we want to add a little bit more
(01:34:34 PM) mhall119: we want to be able to add/remove Measurement items from the same form
(01:35:21 PM) mhall119: so we create an "Inline" form for them, and then create a custom Admin interface for Recipe, specifying that we want to inline forms for Measurements
(01:35:55 PM) mhall119: otherwise we'd have to go define all our measurements in one place, then the recipe in another
(01:36:28 PM) mhall119: next, we need to run ./manage.py syncdb again
(01:36:31 PM) mhall119: why again?
(01:36:52 PM) mhall119: well, because we added the Admin app to our project, so we need to create whatever tables it needs
(01:37:25 PM) mhall119: in this case, it's just a LogEntry table, for tracking changes you make from the admin app
(01:37:46 PM) ClassBot: Nervengift95 asked: how do I create a superuser when i said i didn't want one during syncdb?
(01:38:09 PM) mhall119: I'm not sure how to make one after the fact, since we're just getting started you can simply delete cookbook.db, and run syncdb again
(01:38:21 PM) mhall119: you will want a superuser account for the next step
(01:39:44 PM) mhall119: now if you point your browser to /admin/ you will see the login screen for the admin app
(01:39:51 PM) mhall119: like this: http://family.ubuntu-fl.org:8002/admin/
(01:40:24 PM) mhall119: once you log in, you'll see your models listed under the Recipes app
(01:40:57 PM) mhall119: from there you can add/change/delete your records
(01:41:34 PM) mhall119: for the sake of time, though, just download http://people.ubuntu.com/~mhall119/cookbook.db and copy it over your current cookbook.db
(01:42:47 PM) mhall119: then you can see that I've got all the fixing for a delicious plate of Spaghetti
(01:43:45 PM) mhall119: okay, gonna have to rush through the rest, so hang on
(01:43:56 PM) mhall119: run "bzr pull -r tag:recipeview"
(01:44:37 PM) mhall119: you will see that I added a new view function called show_recipe
(01:45:22 PM) mhall119: with a new line in urls.py, mapping the path /recipe/(\d*) to that view
(01:45:51 PM) mhall119: the (\d*) regular expression will match any number, and that number will be passed as the second argument to our view function
(01:45:59 PM) mhall119: in this case, it will be the internal recipe_id
(01:46:37 PM) mhall119: also, I am not a chef, this is the spaghetti I make when it's my turn to cook
(01:46:43 PM) mhall119: don't mock it
(01:47:27 PM) mhall119: now if you go back to your /welcome page, you will see our spaghetti entry listed as a link
(01:47:35 PM) mhall119: click that link, and you'll go to our new view page
(01:48:00 PM) mhall119: that view uses the recipes/templates/recipe.html template
(01:48:28 PM) mhall119: in there you see that we use the {{ }} substitution to put the values for our recipe's fields where we want them
(01:48:56 PM) mhall119: we can also loop over the ManyToMany field using the {% for value in list %} tag
(01:49:22 PM) mhall119: okay, one last step, let's add a search form
(01:49:29 PM) mhall119: bzr pull -r tag:searchform
(01:50:40 PM) mhall119: then look at recipes/forms.py
(01:51:07 PM) mhall119: we define forms in much the same way we defined models, they are a python class that extends django.forms.Form
(01:51:13 PM) mhall119: and contains fields of different types
(01:51:25 PM) mhall119: these are different from our model field types
(01:51:50 PM) mhall119: form fields can be found here: http://docs.djangoproject.com/en/1.2/ref/forms/fields/#ref-forms-fields
(01:51:56 PM) mhall119: and again you can make your own if you ever needed to
(01:52:07 PM) mhall119: Django forms are also magical
(01:52:42 PM) mhall119: they not only handle building the HTML elements to display our form, they also parse the values out of the submit request, and validate them against the field type
(01:53:01 PM) mhall119: you can also add your own clean_$fieldname methods to your form, to perform extra validation
(01:53:33 PM) mhall119: now if you go back to your /welcome page, you will have a search box at the top
(01:53:42 PM) mhall119: type in "taco" and hit search, and you'll get nothing
(01:53:51 PM) mhall119: type in "spa" and hit searh, you get Spaghetti
(01:54:21 PM) mhall119: the magic behind all that is recipes/views.py lines 13 to 17, only 4 lines!
(01:54:48 PM) mhall119: not covered here, but something you will use, is the ModelForm
(01:55:11 PM) mhall119: ModelForm takes a model definition, and automagically created a Form based on it's field definitions
(01:55:38 PM) mhall119: it also performs validation based on not only the field type, but any additional restrictions you have
(01:56:31 PM) mhall119: remember how Measurement.unit has an array of choices?  Not only will the ModelForm render that as a <select> field, but if the submitted value isn't in the choices list, it will fail validation and tell the user so
(01:56:49 PM) mhall119: any questions in our remaining few minutes?
(01:57:26 PM) mhall119: before I go, I want to mention again the loco-directory project: https://launchpad.net/loco-directory
(01:57:32 PM) mhall119: this is the code behind loco.ubuntu.com
(01:57:54 PM) mhall119: we are always looking for new contributors, and I just taught you everything you needed to know to get started
(01:58:42 PM) mhall119: we label quick and easy fixes as "bitesize" bugs, and they are perfect for getting started: https://bugs.launchpad.net/loco-directory/+bugs?field.tag=bitesize
(01:59:11 PM) mhall119: the developers hang out in #ubuntu-locoteams most of the time, so if you need help getting loco-directory setup just come in and ask
(01:59:24 PM) mhall119: but mostly if you follow the directions in the INSTALL file, you'll be up and running in no time
(01:59:41 PM) mhall119: any other questions?

MeetingLogs/devweek1007/Django (last edited 2010-07-16 18:01:24 by ausimage)