######################
# in urls.py

    (r'^booklist/',  object_list, {'queryset': Book.objects.all()} ),
    (r'^newbook/$', addUpdateBooks),
    (r'^book/(\d+)/$', addUpdateBooks),

######################
# in models.py

class Author(models.Model):
    fname       = models.CharField(max_length=50)
    lname       = models.CharField(max_length=50)
    createdBy   = models.ForeignKey(User)
    createdAt   = models.DateTimeField()

class Book(models.Model):
    name        = models.CharField(max_length=200, unique=True)
    summary     = models.TextField()
    author      = models.ForeignKey(Author)
    createdBy   = models.ForeignKey(User)
    createdAt   = models.DateTimeField()

######################
# in forms.py

class AuthorForm(forms.ModelForm):
    fname = forms.CharField(label="Author First Name")
    lname = forms.CharField(label="Author Last Name")
    class Meta:
        model = Author
        exclude = ['createdBy', 'createdAt']
        
class BookForm(forms.ModelForm):
    summary = forms.CharField(widget=forms.Textarea(attrs={'cols':'17', 'rows':'5'}))
    class Meta:
        model = Book
        exclude = ['author', 'createdBy', 'createdAt']

######################
# in views.py

def addUpdateBooks(request, id=None):
    
    update_mode = False or (id is not None)

    if request.method == 'POST':
        new_book = None
        book_data, auth_data = getBookData(request.POST)
        if update_mode:
            " handle update after new data has been posted "
            book = Book.objects.get(pk=id)
            b = BookForm(book_data, instance=book)
            a = AuthorForm(auth_data, instance=book.author)
            
            if a.is_valid():
                new_auth = a.save(commit=True)
        
                if b.is_valid():
                    new_book = b.save(commit=False)
                    new_book.author = new_auth
                    new_book.save()
        else:
            " handle creation of new objects "
            b = BookForm(book_data)
            a = AuthorForm(auth_data)
            now = datetime.datetime.now()
            
            if a.is_valid():
                new_auth = a.save(commit=False)
                new_auth.createdBy = request.user
                new_auth.createdAt = now
                
                if b.is_valid():
                    new_auth.save()
                    new_book = b.save(commit=False)
                    new_book.author = new_auth
                    new_book.createdBy = request.user
                    new_book.createdAt = now
                    new_book.save()
        
        if new_book is not None:
            " create/update has succeeded "
            return HttpResponseRedirect("/booklist/")

    else:
        if id is not None:
            " request for an edit form. Fill the form with existing objects "
            book = Book.objects.get(pk=id)
            b = BookForm(instance=book)
            a = AuthorForm(instance=book.author)
        else:
            " request for create form. Return empty "
            b = BookForm()
            a = AuthorForm()
    
    return render_to_response('cru_book.html', 
                              {'bForm': b,
                               'aForm': a }, 
                               RequestContext(request))

def getBookData(post_data):
    raw = post_data.copy()
    book_data = {
        'name': raw['name'],
        'summary': raw['summary'],
    }
    auth_data = {
        'fname': raw['fname'],
        'lname': raw['lname'],
    }
    return book_data, auth_data

