Login

Create multiple related objects at once

Author:
yaniv.haber
Posted:
March 29, 2009
Language:
Python
Version:
1.0
Score:
1 (after 1 ratings)

The following code takes two related models and creates one user interface to for create and update operations that handles them both. It enables the creation or update of instances from both models in one shot, without having to create very complex forms. As I could not find examples for creation of related objects together, I thought this might be useful for someone.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
######################
# 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

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 8 months, 4 weeks ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 9 months ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 3 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 4 months ago
  5. Help text hyperlinks by sa2812 1 year, 5 months ago

Comments

Please login first before commenting.