Adding a field to the profile: Difference between revisions

Undo revision 18879 by 86.51.26.15 (talk)
imported>Mark
imported>Brittag
(Undo revision 18879 by 86.51.26.15 (talk))
 
(24 intermediate revisions by 8 users not shown)
Line 25:
== Getting the source ==
 
All the sample code in this walkthrough refers to version '''d56a354''' of the OpenHatch source. To make sure the code is in line with what you expect, follow the instructions on the [[http://openhatch.readthedocs.org/en/latest/contributor/getting_started.html getting started with the OpenHatch code]] page. But right after you do the "git clone", do these commands:
 
$ git checkout d56a354 # Switch to that revision
Line 32:
 
Here's how you can check that it worked. Run these commands in your new ''oh-mainline'' directory, and check that they have the same output as I've recorded:
 
<b>TODO: before continuing need to setup the DB for older version of code that you are trying to run</b>
The command is: <code>python manage.py migrate #####</code>
<b>How to determine what ##### should be? (bug paulproteus on IRC)</b>
 
$ git log -1 # look at the most recent commit on the current branch
Line 147 ⟶ 151:
 
<div class="example"><pre>
$ git commit -a -m "base_profile.html: Now everyone's profile says they were born on January 1, 1980."
</pre></div>
 
=== EditMaking 2:the Adding anew field to the Person modeldynamic ===
 
== Edit 2: Adding a field to the Person model ==
 
If you take a look at template you just edited, you will notice that the person's website was referred to as "person.homepage_url". Since you also know that the code we want to edit is most likely in the "profile" module, you should start by looking in models.py, located in the "mysite/profile/" folder.
Line 159 ⟶ 165:
 
<div class="example"><pre>
birthday = models.DateField(blank=True, null=True)
</pre></div>
 
 
=== Edit 3: Adding the new field to the View ===
 
Adding a field to the model will ensure that we have a place to store the new field. You now need a way to access and update the data in this field. In Django, this is the responsibility of the view.
Line 193 ⟶ 199:
</pre></div>
 
=== Edit 4: Adding the Form ===
 
As you saw while adding the birthday field to the view, a form is being used by thew view to capture the data entered by the user. If you look in the edit_person_info_do(request) function, you should notice this line:
Line 211 ⟶ 217:
</pre></div>
 
=== Inflection point ===
 
== Edit 5: Adding the template changes ==
The next things to do are:
 
Earlier you added a birthday to the base_profile.py file. This changed allowed you to see the birthday when viewing a profile. Now let's take it a step further and change it so the birthday is retrieved from the person's profile rather than being hard coded to January 1, 1980!
 
Open up '/mysite/profile/templates/profile/base_profile.html' and find the spot where you made your changes earlier. Remember, you want to mimic the way that the existing homepage_url and irc_nick fields work. Go ahead and do that now.
 
Did you end up with something like this?
<div class="example"><pre>
{%if person.birthday %}
<h4>birthday</h4>
<p id="birthday" style='clear: both;'>
{{ person.birthday }}
</p>
{% endif %}
{% if person.irc_nick %}
<h4>irc nick</h4>
<p id="ircnick" style='clear: both;'>
{{ person.irc_nick }}
</p>
{% endif %}
</pre></div>
 
Now let's see if there is anywhere else this field may need to be displayed to the user. Remember the 'git grep' command from before? Let's run that again and see if we find anywhere else we need to make our changes.
 
<div class="example"><pre>
$ git grep --color 'homepage_url'
</pre></div>
 
You should see some entries to 'mysite/profile/templates/profile/info_wrapper.html'. This html file is the page a user visits to update their information. You definitely need to add something here! Find the section where homepage_url and irc_nick have been added and you will again mimic the way this is set up and add some new code for the user to enter their birthday.
 
<div class="example"><pre>
<div class='form-row'>
<label>Birthday:</label>
{{ form.birthday.errors }}
{{ form.birthday }}
<p class='example'>Date must be entered in YYYY-MM-DD format. Example: 1980-01-01</p>
</div>
 
<div class='form-row'>
<label>IRC nick:</label>
{{ form.irc_nick.errors }}
{{ form.irc_nick }}
<p class='example'>Example: sufjan</p>
</div>
</pre><div>
 
== Commit 2: Saving our work before making database changes ==
 
Next we need to sync the database and create the migration file. This is a good time for you to save your work. So, let's do that now.
 
Run 'git status' and you should see all of the files you have edited up to now:
<div class="example"><pre>
$git status
 
# On branch tutorial
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: mysite/profile/forms.py
# modified: mysite/profile/models.py
# modified: mysite/profile/templates/profile/base_profile.html
# modified: mysite/profile/templates/profile/info_wrapper.html
# modified: mysite/profile/views.py
</pre></div>
 
Now we can tell git to commit our changes:
<div class="example"><pre>
$git commit -a -m "Added the birthday field to the profile: forms.py, models.pyviews.py and the templates: base_profile.html and info_wrapper.html."
 
[tutorial f38a12b] Added the birthday field to the profile: forms.py, models.pyviews.py and the templates: base_profile.html and info_wrapper.html.
5 files changed, 18 insertions(+), 1 deletions(-)
</pre></div>
 
= Managing the Database =
 
== Edit 6: Syncing the database and creating a migration ==
 
Django has the ability to automatically save model changes to the database, however will only do this for new models. Once a model has been created, you must either manually make the change, or use a tool such as 'South' to make the change for you. South is what we refer to when speaking of migrations. Go ahead and try to sync the database and you will see the mysite.profiles does not get updated, even though you have added a new field to the model.
 
<div class="example"><pre>
$ python manage.py syncdb
Syncing...
No fixtures found.
 
Synced:
> ghettoq
> django.contrib.auth
> django.contrib.contenttypes
> django.contrib.sessions
> django.contrib.sites
> django.contrib.webdesign
> django.contrib.admin
> registration
> django_authopenid
> django_extensions
> south
> django_assets
> celery
> invitation
> haystack
> voting
> reversion
> debug_toolbar
> sessionprofile
> model_utils
 
Not synced (use migrations):
- mysite.search
- mysite.profile
- mysite.customs
- mysite.account
- mysite.base
- mysite.project
- mysite.missions
(use ./manage.py migrate to migrate these)
</pre><div>
 
Now run the migration as described [http://openhatch.org/wiki/Making_schema_changes here].
<div class="example"><pre>
$ python manage.py schemamigration profile --auto
+ Added field birthday on profile.Person
Created 0090_auto__add_field_person_birthday.py. You can now apply this migration with: ./manage.py migrate profile
 
$ python manage.py migrate profile
Running migrations for profile:
- Migrating forwards to 0090_auto__add_field_person_birthday.
> profile:0090_auto__add_field_person_birthday
2011-07-06 20:16:02,282 execute:209 DEBUG south execute "ALTER TABLE `profile_person` ADD COLUMN `birthday` date NULL;" with params "[]"
2011-07-06 20:16:02,283 execute:209 DEBUG south execute "SET FOREIGN_KEY_CHECKS=1;" with params "[]"
2011-07-06 20:16:02,286 execute:209 DEBUG south execute "ALTER TABLE `profile_person` ADD COLUMN `birthday` date NULL;" with params "[]"
2011-07-06 20:16:02,701 execute:209 DEBUG south execute "ALTER TABLE `profile_person` ;" with params "[]"
2011-07-06 20:16:02,703 execute:209 DEBUG south execute "ALTER TABLE `profile_person` MODIFY `birthday` date NULL;;" with params "[]"
2011-07-06 20:16:02,714 execute:209 DEBUG south execute "ALTER TABLE `profile_person` ALTER COLUMN `birthday` DROP DEFAULT;" with params "[]"
- Loading initial data for profile.
No fixtures found.
</pre></div>
 
== Commit 3: Save the migration ==
 
Running 'git status' will show you that a couple of changes have taken place.
<div class="example"><pre>
$ git status
# On branch tutorial
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# mysite/indexes/
# mysite/profile/migrations/0090_auto__add_field_person_birthday.py
nothing added to commit but untracked files present (use "git add" to track)
</pre></div>
 
Next you will want to add the migration to the files to be committed, however ignore the index changes. Those should occur automatically once the patch is applied and migrations are run against the openhatch core codebase.
<div class="example"><pre>
$ git add mysite/profile/migrations/0090_auto__add_field_person_birthday.py
 
$ git commit -m "Migration for adding birthday to Person model."
[tutorial 1cfc527] Migration for adding birthday to Person model.
1 files changed, 218 insertions(+), 0 deletions(-)
create mode 100644 mysite/profile/migrations/0090_auto__add_field_person_birthday.py
</pre></div>
 
* Make the template changes so the new field can be updated and appears in the profile block.
* [[Making schema changes|Write a migration file]] to add that column to our database.
* Write a test.
* Submit a patch.
 
= Testing =
 
Through all this, we've just been hacking and slashing until things work the way we want. But the OpenHatch code has all these automated tests, and we won't deploy new code that doesn't have automated tests written for it. Each module contains a tests.py, which is provided for just this purpose.
 
You are going to be writing a [http://twill.idyll.org/ Twill test], which is a way of automating the steps a user would take when entering and saving data through the web site. Go ahead and edit mysite/profile/tests.py and search for 'irc_nick' and you will find an existing Twill test for the 'irc_nick' field. Use that as your template for writing one for the birthday field.
 
This test will do the following:
* Set up a data fixture to be used with the test
* Go to paulproteus's profile
* Check that a birthday doesn't already exist
* Click edit on the birthday form
* Enter the birthday as a string
* Save the changes
* bring up the profile and verify the birthday is still there.
** Note: Django will format the date as May 26, 1977
 
<div class="example"><pre>
class EditBirthday(TwillTests):
fixtures = ['user-paulproteus', 'person-paulproteus']
 
def test(self):
'''
* Goes to paulproteus's profile
* checks that they don't already have a birthday that says "1977-05-26"
* clicks edit on the birthday area
* enters a string as birthday
* checks that his birthday now contains string
'''
self.login_with_twill()
tc.go(make_twill_url('http://openhatch.org/people/paulproteus/'))
tc.notfind('May 26, 1977')
tc.go(make_twill_url('http://openhatch.org/profile/views/edit_info'))
# make sure our birthday is not already on the form
tc.notfind('1977-05-26')
# set the birthday in the form
tc.fv("edit-tags", 'edit-tags-birthday', '1977-05-26')
tc.submit()
self.assertEqual(Person.get_by_username('paulproteus').birthday,
datetime.date(1977, 5, 26))
# now we should see our birthday in the edit form
tc.go(make_twill_url('http://openhatch.org/profile/views/edit_info'))
tc.find('1977-05-26')
 
</pre></div>
 
Now run the test and let's make sure it passes!
<div class="example"><pre>
$ python manage.py test profile.EditBirthday
 
<test information will print here...>
 
Installed 12 object(s) from 1 fixture(s)
sh: /usr/sbin/postmap: not found
.
----------------------------------------------------------------------
Ran 1 test in 8.578s
 
OK
Destroying test database 'default'...
 
</pre></div>
 
 
== Commit 4: Save the tests ==
 
Go ahead and commit the tests.py file.
 
<div class="example"><pre>
$ git status
# On branch tutorial
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: mysite/profile/tests.py
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# mysite/indexes/
# mysite/static/twisted-ping-dir/twisted-ping-file
no changes added to commit (use "git add" and/or "git commit -a")
 
$ git add mysite/profile/tests.py
 
$ git commit -m "Added a test for the Person.birthday field."
[tutorial 9b13221] Added a test for the Person.birthday field.
1 files changed, 26 insertions(+), 0 deletions(-)
</pre></div>
 
= Submitting a patch =
 
At OpenHatch, code changes are accepted through patches. These should be uploaded and attached to the particular [http://openhatch.org/bugs/ issue tracker] item you are working on.
 
First, you should generate the patch file which includes all of your changes. Since you are making all of your changes as part of a branch, this process is easy! First, make sure you are in the tutorial branch and then create the patch file as seen below.
 
<div class="example"><pre>
$ git branch
master
* tutorial
 
$ git format-patch master --stdout > tutorial.patch
</pre></div>
 
This will create the patch file for you to upload to your tracker item.
 
That it! For more information on using git and creating a patch, check out our [http://openhatch.org/missions/git git mission].
 
= Wrapping it up =
 
Welcome to the OpenHatch community. We are very glad to have you here! be sure to [[chat with us on IRC]] and say hello or ask any questions you may have.
Anonymous user