diff options
Diffstat (limited to 'old/published/Webmonkey/Frameworks/django-migrate.txt')
-rw-r--r-- | old/published/Webmonkey/Frameworks/django-migrate.txt | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/old/published/Webmonkey/Frameworks/django-migrate.txt b/old/published/Webmonkey/Frameworks/django-migrate.txt new file mode 100644 index 0000000..9cfe49f --- /dev/null +++ b/old/published/Webmonkey/Frameworks/django-migrate.txt @@ -0,0 +1,158 @@ +If you started following our Django tutorials back when they first started you may be wondering about the recent news that the [http://code.djangoproject.com/wiki/NewformsAdminBranch NewForms Admin branch] of Django was recently merged to trunk. + +What does that mean? Well it means that, if you update your svn checkout of Django, it's going to break all the code we wrote earlier. But don't worry, the changes aren't too radical and adjusting our code takes only a few minutes. + +The goal of the NewForms Admin branch was two-fold. First the developers wanted to make sure that the admin app (which is a standalone app that ships with Django) used the latest Django froms code (hence the NewForms bit of the name). The other goal was to decouple the admin and make it much easier to customize. + +We're not going to dive into customizations today (see the [http://www.djangoproject.com/documentation/admin/ updated Django docs] if you're itching to know more details), but let's take a look at what we need to do to port our code over to the latest version of Django. + +But first make sure you have the latest version of Django: fire up your terminal and cd over to your Django folder. Then run <code>svn up</code> and Django will update itself. + +== Decoupling == + +The first thing we need to do is create a new file in our blog app folder named admin.py. As part of the decoupling, a model's admin definitions now live in seperate file, which makes sense since the old Admin class really had nothing to do with the model. + +So open up the admin.py file and we'll re-write our admin class definition. Our old code, where the <code>Admin</code> class lived in model.py looked something like this (I've left out a few things for clarity): + +<pre> +class Entry(models.Model): + """ + ...all the field definitions omitted... + """ + + class Meta: + ordering = ('-pub_date',) + get_latest_by = 'pub_date' + verbose_name_plural = 'entries' + + class Admin: + list_display = ('title', 'pub_date','enable_comments', 'status',) + search_fields = ['title', 'body_markdown'] + list_filter = ('pub_date', 'enable_comments', 'status') + fields = ( + (None, { + 'fields': (('title', 'status'), 'body_markdown', ('pub_date', 'enable_comments'), 'tags', 'slug') + }), + ) +</pre> + +Now the <code>Meta</code> class remains part of the models.py file, since it controls model-related behavior. But the <code>Admin</code> class really doesn't relate directly to the model, so open up blog/models.py and we're going to cut all that data out, so our models.py file now looks like: + +<pre> +class Entry(models.Model): + title = models.CharField(max_length=200) + slug = models.SlugField( + unique_for_date='pub_date', + help_text='Automatically built from the title.' + ) + body_html = models.TextField(blank=True) + body_markdown = models.TextField() #note, if you're using Markdown, include this field, otherwise just go with body_html + pub_date = models.DateTimeField('Date published') + tags = TagField() + enable_comments = models.BooleanField(default=True) + PUB_STATUS = ( + (0, 'Draft'), + (1, 'Published'), + ) + status = models.IntegerField(choices=PUB_STATUS, default=0) + + class Meta: + ordering = ('-pub_date',) + get_latest_by = 'pub_date' + verbose_name_plural = 'entries' + + def __unicode__(self): + return u'%s' %(self.title) + + def get_absolute_url(self): + return "/%s/%s/" %(self.pub_date.strftime("%Y/%b/%d").lower(), self.slug) + + def save(self): + self.body_html = markdown.markdown(self.body_markdown, safe_mode = False) + super(Entry, self).save() + +</pre> + +Note that we also deleted the prepopulate_from field in the slug definition. That's another thing that's moved over to the new admin.py file. + +Okay, now we need to define our <code>Admin</code> class according to the new conventions. Jump back to the new admin.py and paste in this code: + +<pre> +from django.contrib import admin + +from djangoblog.blog import Entry + +class EntryAdmin(admin.ModelAdmin): + list_display = ('title', 'pub_date','enable_comments', 'status') + search_fields = ['title', 'body_markdown'] + list_filter = ('pub_date', 'enable_comments', 'status') + prepopulated_fields = {"slug" : ('title',)} + fields = ( + (None, {'fields': (('title', 'status'), 'body_markdown', ('pub_date', 'enable_comments'), 'tags', 'slug')}), + ) + +admin.site.register(Entry, EntryAdmin) +</pre> + +So what's different? Well, first off we import the admin module and new extend the ModelAdmin class with our own <code>EntryAdmin</code> class. Then we brought over the same definitions we use above to control <code>list_display</code>, <code>search_fields</code> and <code>list_filter</code>. Then we use one brand new bit of syntax. Remember in our original model we used <code>prepopulate_from</code> to automatically fill our slug field with whatever is typed in our title field? + +Well the new name is <code>prepopulated_fields</code> and instead of a string, it's now a dictionary. The key is the field to fill and the value is where to pull from. Obviously, since it's a dictionary you could add several fields if need be. + +The fields customizations remain the same in our case, though there is a new fieldsets option if you want to have several, uh, sets of fields. + +The last line of our code just registers our new Admin class and lets Django know that whenever it's displaying info about our Entry model it should follow the rules we set up in EntryAdmin. + +See that wasn't so bad. + +== New URL structures == + +As I said earlier one of the main goals with NewForms Admin ws to make the Django admin more flexible. Part of the way that's achieved is through the urls.py file. So open up our project level urls.py file and you should see something like this: + +<pre> +urlpatterns = patterns('', + # Example: + # (r'^djangoblog/', include('djangoblog.foo.urls')), + (r'^admin/(.*)', include('django.contrib.admin.urls')), +) + +</pre> + +We're going to change that to this: + +<pre> +from django.conf.urls.defaults import * +from django.contrib import admin + +admin.autodiscover() + + +urlpatterns = patterns('', + (r'^admin/(.*)', admin.site.root), + ... the rest stays the same... +) + +</pre> + +Notice that we're no longer simply handing off all the admin urls to an mysterious include statement. That means we could concievably create all sort of urls and pass them to our own custom views. In fact you could have several different admin sites if you so desired. + +== Updating Tagging == + +The last step in our transition to NewForms Admin is to update our django-tagging application. As of this writing, django-tagging hasn't caught up to the newforms admin update yet, so we're actually going to need to checkout the Newforms Admin branch of the django-tagging codebase. + +To do that we'll grab the files using Subversion. Paste this code into your terminal window: + +<pre> +svn checkout http://django-tagging.googlecode.com/svn/branches/newforms-admin django-tagging +</pre> + +Now cd into the new django-tagging folder and type: + +<pre> +python setup.py install +</pre> + +After that just delete the old version (if you're good with Subversion, there are other ways to do this). + +== Other Changes == + +There are quite a few other changes to the admin section, and if you have a lot of old code to port definitely head over and [http://www.djangoproject.com/documentation/admin/ check out the new documentation]. Also highly recommended is [http://oebfare.com/blog/2008/jul/20/newforms-admin-migration-and-screencast/ Brian Rosner's very informative screencast] which covers inlines and some other more complicated things our project isn't using.
\ No newline at end of file |