What is the best way to display information from related objects on my Backbone.js wired front-end when on the backend these attributes are stored on separate Django models in a PostgreSQL database?
I am currently using Django, Tastypie, Django-Tastypie, Backbone.js, Backbone-Relational and Handlebars.js templates. I am open to doing things differently and I am willing to learn new technologies such as Riak if it’s necessary or more efficient.
On the front-end what I’m trying to do would be very simple with standard Django templates: display a list of tags on a post and the author of that post.
On the back-end I have a Post model and Tag, User and UserProfile (author) models. Users and UserProfiles are 1-to-1, Post has a relation to UserProfile but what I want to display is stored on the User model under the attribute username. At the moment this involves two painstaking lookups to get the author’s username for every post. The Post model:
class Post(models.Model):
author = models.ForeignKey(UserProfile)
topic = models.ForeignKey(Topic)
tags = models.ManyToManyField(Tag)
content = models.TextField()
title = models.CharField(max_length=250)
slug = models.SlugField()
description = models.TextField()
In Coffeescript I have my Backbone models. At present I am trying to fetch the relevant author and tag objects when a Post model is initialized. My current code is very sloppy and I apologize, my javascript foo is still under development!
class User extends Backbone.RelationalModel
class UserProfile extends Backbone.RelationalModel
urlRoot : '/api/v1/profile/?format=json'
class PostTag extends Backbone.RelationalModel
initialize: ->
this.get('tag').on 'change', ( model ) =>
this.get( 'post' ).trigger( 'change:tag', model )
class Tag extends Backbone.RelationalModel
urlRoot: '/api/v1/tag/?format=json'
idAttribute: 'id',
relations: [{
type: Backbone.HasMany,
key: 'post_tags',
relatedModel: PostTag,
reverseRelation: {
key: 'tag',
includeInJSON: 'id',
},
}],
class Post extends Backbone.RelationalModel
idAttribute: 'id',
relations: [{
type: Backbone.HasMany,
key: 'post_tags',
relatedModel: PostTag,
reverseRelation: {
key: 'post',
includeInJSON: 'id',
},
}]
initialize: ->
@.get('tags').forEach(@addTag, @)
@.addAuthor()
@.on 'change:tag', (model) ->
console.log('related tag=%o updated', model)
addAuthor: () ->
profile_id = @.get('author')
if app.UserProfiles.get(profile_id)?
profile = app.UserProfiles.get(profile_id)
user = app.Users.get(profile.user)
@.set('author_name',user.get('username'))
else
profile = new app.UserProfile(profile_id)
app.UserProfiles.add(profile)
profile.fetch(success: (model,response) =>
user_id = profile.get('user')
if app.Users.get(user_id)?
user = app.Users.get(user_id)
user.fetch(success: (model,response) =>
console.log(user.get('username'))
@.set('author_name',user.get('username'))
)
console.log("Existing user"+user_id)
console.log(user.get('username'))
#@.set('author_name',user.get('username'))
else
user = new app.User('resource_uri':user_id)
app.Users.add(user)
console.log("New user"+user_id)
user.fetch(success: (model,response) =>
console.log(user.get('username'))
@.set('author_name',user.get('username'))
)
)
addTag: (tag_id) ->
console.log(tag_id)
if app.Tags.get(tag_id)?
tag = app.Tags.get(tag_id)
console.log("TAG" + tag)
else
console.log("NON EXISTENT")
console.log(tag_id)
tag = new app.Tag({'id':tag_id})
tag.fetch()
app.Tags.add(tag)
post_tag = new app.postTag({
'tag': tag_id,
'post': @.get('resource_uri')
})
@.get('post_tags').add(post_tag)
This code actually works fine for fetching and storing the related objects but it’s incredibly messy and I’m sure there must be a better way. Further, I can’t figure out a way to access the stored tag names to display in my Handlebars.js templates.
When writing this I found the related question How do I load sub-models with a foreign key relationship in Backbone.js?
Since I’d already written the question I figured I may as well post it in case it’s useful for anyone.
The answer was as simple as adding
full=Trueto mytastypieresources. I could then get rid of theaddTagsandaddAuthorfunctions and since I don’t need to save or update the related objects the rest of the answer in the above thread wasn’t necessary for me.