Create multiple related objects at once

  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. Dynamic Form Class by dballanc 6 years, 2 months ago
  2. create_update for newforms (ModelForm) by Rozza 5 years, 3 months ago
  3. (Modified/Improved) MultiQuerySet by joonas 4 years, 6 months ago
  4. FieldAccessForm (per-field user access for forms derived from models) by Killarny 4 years, 8 months ago
  5. Complex Form Preview by smagala 4 years, 2 months ago

Comments

(Forgotten your password?)