Skip to content

Commit 70a01b0

Browse files
committed
Add bootstrap. Add django messages on submit.
1 parent 8b773c8 commit 70a01b0

File tree

13 files changed

+127
-83
lines changed

13 files changed

+127
-83
lines changed

db.sqlite3

0 Bytes
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

django_formset_vuejs/forms.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ class Meta:
1111
class AuthorForm(ModelForm):
1212
class Meta:
1313
model = models.Author
14-
fields = ('first_name', 'last_name', 'email')
15-
14+
fields = ('first_name', 'last_name')
1615

1716

1817
class BookForm(ModelForm):
@@ -22,7 +21,6 @@ class Meta:
2221
fields = ('title', 'isbn',)
2322

2423

25-
2624
BookFormset = inlineformset_factory(models.Author, models.Book, form=BookForm, can_delete=True, extra=0)
2725

2826

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Generated by Django 2.2.5 on 2020-01-24 06:10
2+
3+
from django.db import migrations
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('django_formset_vuejs', '0002_delete_award'),
10+
]
11+
12+
operations = [
13+
migrations.RemoveField(
14+
model_name='author',
15+
name='email',
16+
),
17+
]
Binary file not shown.

django_formset_vuejs/models.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ class Author(models.Model):
1313
author_container = models.ForeignKey(AuthorContainer, on_delete=models.CASCADE)
1414
first_name = models.CharField(max_length=255, null=True, blank=True)
1515
last_name = models.CharField(max_length=255, null=True, blank=True)
16-
email = models.EmailField(null=True, blank=True)
1716

1817
def __str__(self):
1918
return '{} {}'.format(self.first_name, self.last_name)

django_formset_vuejs/templates/django_formset_vuejs/author.html

Lines changed: 77 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,21 @@
22

33
{% block content %}
44
<div id="author-books">
5-
<h1>
6-
Nested formset
7-
</h1>
8-
<div>
5+
<div class="jumbotron">
6+
<h1>Django formsets with Vuejs</h1>
7+
</div>
8+
<div class="container">
9+
{% for message in messages %}
10+
<div class="alert {{ message.tags }} alert-dismissible" role="alert">
11+
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
12+
<span aria-hidden="true">&times;</span>
13+
</button>
14+
{{ message }}
15+
</div>
16+
{% endfor %}
917
<form enctype="multipart/form-data" method="post">
1018
{% csrf_token %}
11-
<input type="hidden" name="author_set-TOTAL_FORMS" v-model="getTotalAuthorForm()"
19+
<input type="hidden" name="author_set-TOTAL_FORMS" v-model="getTotalAuthorForms()"
1220
id="id_author_set-TOTAL_FORMS">
1321
<input type="hidden" name="author_set-INITIAL_FORMS" v-model="getInitialAuthorForms()"
1422
id="id_author_set-INITIAL_FORMS">
@@ -29,46 +37,41 @@ <h1>
2937
v-bind:id="'id_author_set-' + author.author_formset_index + '-id'"
3038
>
3139
</p>
32-
<div class="">
33-
<div>
34-
<strong>
35-
Author [[getIndexAmongVisibleAuthors(author_index) + 1]]
36-
</strong>
37-
</div>
38-
<div>
39-
<label v-bind:for="'id_author_set-' + author.author_formset_index + '-first_name'">First
40-
name:</label>
41-
<input type="text"
42-
v-bind:name="'author_set-' + author.author_formset_index +'-first_name'"
43-
v-model="author.first_name"
44-
v-bind:id="'id_author_set-' + author.author_formset_index + '-first_name'">
45-
</div>
46-
47-
<div>
48-
<label v-bind:for="'id_author_set-' + author.author_formset_index + '-last_name'">Last
49-
name:</label>
50-
<input type="text"
51-
v-bind:name="'author_set-' + author.author_formset_index +'-last_name'"
52-
v-model="author.last_name"
53-
v-bind:id="'id_author_set-' + author.author_formset_index + '-last_name'">
54-
</div>
40+
<div class="form-group">
41+
<h4>
42+
Author
43+
</h4>
44+
<div class="form-row">
45+
<div class="col">
46+
<label v-bind:for="'id_author_set-' + author.author_formset_index + '-first_name'">First
47+
name:</label>
48+
<input type="text"
49+
v-bind:name="'author_set-' + author.author_formset_index +'-first_name'"
50+
v-model="author.first_name"
51+
v-bind:id="'id_author_set-' + author.author_formset_index + '-first_name'"
52+
class="form-control"
53+
>
54+
</div>
5555

56-
<div>
57-
<label v-bind:for="'id_author_set-' + author.author_formset_index + '-email'">Email:</label>
58-
<input type="text"
59-
v-bind:name="'author_set-' + author.author_formset_index +'-email'"
60-
v-model="author.email"
61-
v-bind:id="'id_author_set-' + author.author_formset_index + '-email'">
56+
<div class="col">
57+
<label v-bind:for="'id_author_set-' + author.author_formset_index + '-last_name'">Last
58+
name:</label>
59+
<input type="text"
60+
v-bind:name="'author_set-' + author.author_formset_index +'-last_name'"
61+
v-model="author.last_name"
62+
v-bind:id="'id_author_set-' + author.author_formset_index + '-last_name'"
63+
class="form-control"
64+
>
65+
</div>
6266
</div>
63-
6467
</div>
6568

6669
<!-- BOOK -->
6770
<div>
6871
<input type="hidden"
6972
v-bind:name="'nested_book-author_set-'+author.author_formset_index+'-book_set-TOTAL_FORMS'"
7073
v-bind:id="'id_nested_book-author_set-'+author.author_formset_index+'-book_set-TOTAL_FORMS'"
71-
v-model="getTotalBookForm(author_index)">
74+
v-model="getTotalBookForms(author_index)">
7275
<input type="hidden"
7376
v-bind:name="'nested_book-author_set-'+author.author_formset_index+'-book_set-INITIAL_FORMS'"
7477
v-bind:id="'id_nested_book-author_set-'+author.author_formset_index+'-book_set-INITIAL_FORMS'"
@@ -100,43 +103,50 @@ <h1>
100103
>
101104
</span>
102105

103-
<div>
104-
<div>
105-
<strong>
106-
Book [[getIndexAmongVisibleBooks(author_index, book_index) + 1]]
107-
</strong>
106+
<div class="books-form">
107+
<h5>
108+
Book [[getIndexAmongVisibleBooks(author_index, book_index) + 1]]
109+
110+
<span v-show="getTotalVisibleBooks(author_index) > 1">
111+
<a href="" v-on:click="removeBook($event, author_index, book_index)">[X]</a>
112+
</span>
113+
</h5>
114+
115+
<div class="container">
116+
<div class="row">
117+
<div class="form-group col-xs-5">
118+
<label v-bind:for="'id_nested_book-author_set-'+author.author_formset_index+'-book_set-'+book.book_formset_index+'-title'">Title:</label>
119+
<input type="text"
120+
v-bind:name="'nested_book-author_set-'+author.author_formset_index+'-book_set-'+book.book_formset_index+'-title'"
121+
v-model="book.title"
122+
v-bind:id="'id_nested_book-author_set-'+author.author_formset_index+'-book_set-'+book.book_formset_index+'-title'"
123+
class="form-control"
124+
>
125+
</div>
126+
</div>
127+
<div class="row">
128+
<div class="form-group col-xs-5">
129+
<label v-bind:for="'id_nested_book-author_set-'+author.author_formset_index+'-book_set-'+book.book_formset_index+'-isbn'">ISBN:</label>
130+
<input type="text"
131+
v-bind:name="'nested_book-author_set-'+author.author_formset_index+'-book_set-'+book.book_formset_index+'-isbn'"
132+
v-model="book.isbn"
133+
v-bind:id="'id_nested_book-author_set-'+author.author_formset_index+'-book_set-'+book.book_formset_index+'-isbn'"
134+
class="form-control"
135+
>
136+
</div>
137+
</div>
108138
</div>
109139
</div>
110-
111-
<div>
112-
<label v-bind:for="'id_nested_book-author_set-'+author.author_formset_index+'-book_set-'+book.book_formset_index+'-title'">Title:</label>
113-
<input type="text"
114-
v-bind:name="'nested_book-author_set-'+author.author_formset_index+'-book_set-'+book.book_formset_index+'-title'"
115-
v-model="book.title"
116-
v-bind:id="'id_nested_book-author_set-'+author.author_formset_index+'-book_set-'+book.book_formset_index+'-title'">
117-
</div>
118-
119-
<div>
120-
<label v-bind:for="'id_nested_book-author_set-'+author.author_formset_index+'-book_set-'+book.book_formset_index+'-isbn'">ISBN:</label>
121-
<input type="text"
122-
v-bind:name="'nested_book-author_set-'+author.author_formset_index+'-book_set-'+book.book_formset_index+'-isbn'"
123-
v-model="book.isbn"
124-
v-bind:id="'id_nested_book-author_set-'+author.author_formset_index+'-book_set-'+book.book_formset_index+'-isbn'">
125-
</div>
126-
127-
<div v-show="getTotalVisibleBooks(author_index) > 1">
128-
<a href="" v-on:click="removeBook($event, author_index, book_index)">Remove Book</a>
129-
</div>
130-
131140
</div>
132141
</div>
133142
<div>
134-
<a href="" v-on:click="addNewBook($event,author_index)">Add New Book</a>
143+
<a href="" v-on:click="addNewBook($event,author_index)" role="button"
144+
class="btn btn-outline-primary">Add New Book</a>
135145
</div>
136146
</div>
137147
<hr/>
138148
<div>
139-
<button type="submit" value="Next">Save</button>
149+
<button type="submit" value="Next" class="btn btn-primary btn-lg btn-block">Save</button>
140150
</div>
141151
</form>
142152
</div>
@@ -155,7 +165,6 @@ <h1>
155165

156166
first_name: '{{ author.first_name.value|default_if_none:"" }}',
157167
last_name: '{{ author.last_name.value|default_if_none:"" }}',
158-
email: '{{ author.email.value|default_if_none:"" }}',
159168

160169
nested_book: [
161170
{% if author.nested_book %}
@@ -200,13 +209,10 @@ <h1>
200209
},
201210
methods: {
202211
// author
203-
getIndexAmongVisibleAuthors: function (index) {
204-
return this.$data.authors.filter((author, i) => i < index && !author.marked_for_delete).length
205-
},
206212
getInitialAuthorForms: function () {
207213
return this.$data.authors.filter(author => !!author.id).length;
208214
},
209-
getTotalAuthorForm: function () {
215+
getTotalAuthorForms: function () {
210216
return this.$data.authors.map(author => author.author_formset_index).reduce((a, b) => a > b ? a : b, 0) + 1;
211217
},
212218
// books
@@ -219,14 +225,14 @@ <h1>
219225
getInitialBookForms: function (author_index) {
220226
return this.$data.authors[author_index].nested_book.filter(book => !!book.id).length;
221227
},
222-
getTotalBookForm: function (author_index) {
228+
getTotalBookForms: function (author_index) {
223229
var books = this.$data.authors[author_index].nested_book;
224230
return books && books.length || 0;
225231
},
226232
addNewBook: function (event, author_index) {
227233
event.preventDefault();
228234
const default_new_book = {
229-
book_formset_index: this.getTotalBookForm(author_index),
235+
book_formset_index: this.getTotalBookForms(author_index),
230236
};
231237
this.$data.authors[author_index].nested_book.push(default_new_book);
232238
},

django_formset_vuejs/templates/django_formset_vuejs/home.html

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,25 @@
44
<meta charset="UTF-8">
55
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
66
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
7-
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
7+
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
8+
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
9+
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js"
10+
integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn"
11+
crossorigin="anonymous"></script>
12+
813
<title>Django Formset with Vuejs</title>
14+
15+
<style>
16+
.books-form {
17+
padding: 10px;
18+
margin-bottom: 10px;
19+
border: 1px solid lightgray;
20+
border-radius: 5px
21+
}
22+
</style>
923
</head>
1024
<body>
11-
<div class="container">
1225
{% block content %}
13-
{% endblock content %}
14-
</div>
26+
{% endblock %}
1527
</body>
1628
</html>

0 commit comments

Comments
 (0)