@@ -32,6 +32,28 @@ def test_add_another(self):
3232 self .assertEqual (review .title , "Not so great" )
3333 self .assertEqual (review .rating , 1 )
3434
35+ def test_no_change (self ):
36+ movie = Movie .objects .create (
37+ title = "Lion King" ,
38+ reviews = [Review (title = "Great!" , rating = 10 )],
39+ )
40+ data = {
41+ "title" : "Lion King" ,
42+ "reviews-0-title" : "Great!" ,
43+ "reviews-0-rating" : "10" ,
44+ "reviews-TOTAL_FORMS" : 2 ,
45+ "reviews-INITIAL_FORMS" : 1 ,
46+ }
47+ form = MovieForm (data , instance = movie )
48+ self .assertTrue (form .is_valid ())
49+ form .save ()
50+ self .assertEqual (form .changed_data , [])
51+ movie .refresh_from_db ()
52+ self .assertEqual (len (movie .reviews ), 1 )
53+ review = movie .reviews [0 ]
54+ self .assertEqual (review .title , "Great!" )
55+ self .assertEqual (review .rating , 10 )
56+
3557 def test_update (self ):
3658 movie = Movie .objects .create (
3759 title = "Lion King" ,
@@ -47,6 +69,7 @@ def test_update(self):
4769 form = MovieForm (data , instance = movie )
4870 self .assertTrue (form .is_valid ())
4971 form .save ()
72+ self .assertEqual (form .changed_data , ["reviews" ])
5073 movie .refresh_from_db ()
5174 self .assertEqual (len (movie .reviews ), 1 )
5275 review = movie .reviews [0 ]
@@ -149,34 +172,38 @@ def test_delete_required(self):
149172 self .assertFalse (form .is_valid ())
150173 self .assertEqual (form .errors ["reviews" ], ["This field cannot be blank." ])
151174
152- # def test_nullable_field(self):
153- # """A nullable EmbeddedModelField is removed if all fields are empty ."""
154- # author = Author .objects.create(
155- # name="Bob ",
156- # age=50 ,
157- # address=Address(city="NYC ", state="NY", zip_code="10001") ,
158- # billing_address=Address(city="NYC", state="NY", zip_code="10001"),
159- # )
160- # data = {
161- # "name ": "Bob ",
162- # "age ": 51 ,
163- # "address-po_box ": "",
164- # "address-city ": "New York City" ,
165- # "address-state ": "NY" ,
166- # "address-zip_code ": "10001 ",
167- # "billing_address-po_box ": "",
168- # "billing_address-city ": "",
169- # "billing_address-state ": "" ,
170- # "billing_address-zip_code ": "" ,
171- # }
172- # form = AuthorForm (data, instance=author )
173- # self.assertTrue(form.is_valid())
174- # form.save()
175- # author .refresh_from_db()
176- # self.assertIsNone(author.billing_address )
175+ def test_nullable_field (self ):
176+ """A nullable field is emptied if all rows are deleted ."""
177+ movie = Movie .objects .create (
178+ title = "Lion King " ,
179+ reviews = [ Review ( title = "Great!" , rating = 10 )] ,
180+ featured_reviews = [ Review ( title = "Okay " , rating = 5 )] ,
181+ )
182+ data = {
183+ "title" : "Lion King" ,
184+ "reviews-0-title " : "Not so great " ,
185+ "reviews-0-rating " : "1" ,
186+ "reviews-0-DELETE " : "" ,
187+ "reviews-TOTAL_FORMS " : 2 ,
188+ "reviews-INITIAL_FORMS " : 1 ,
189+ "featured-reviews-0-title " : "Okay " ,
190+ "featured-reviews-0-rating " : "5 " ,
191+ "featured-reviews-0-DELETE " : "1 " ,
192+ "featured-reviews-TOTAL_FORMS " : 2 ,
193+ "featured-reviews-INITIAL_FORMS " : 1 ,
194+ }
195+ form = MovieForm (data , instance = movie )
196+ self .assertTrue (form .is_valid ())
197+ form .save ()
198+ movie .refresh_from_db ()
199+ self .assertEqual ( len ( movie . featured_reviews ), 0 )
177200
178201 def test_rendering (self ):
179202 form = MovieForm ()
203+ self .assertHTMLEqual (
204+ str (form .fields ["reviews" ].get_bound_field (form , "reviews" ).label_tag ()),
205+ '<label for="id_reviews">Reviews:</label>' ,
206+ )
180207 self .assertHTMLEqual (
181208 str (form .fields ["reviews" ].get_bound_field (form , "reviews" )),
182209 """
@@ -209,6 +236,64 @@ def test_rendering(self):
209236 name="reviews-MAX_NUM_FORMS" value="1000" id="id_reviews-MAX_NUM_FORMS">""" ,
210237 )
211238
239+ def test_rendering_initial (self ):
240+ movie = Movie .objects .create (
241+ title = "Lion King" ,
242+ reviews = [Review (title = "Great!" , rating = 10 )],
243+ )
244+ form = MovieForm (instance = movie )
245+ self .assertHTMLEqual (
246+ str (form .fields ["reviews" ].get_bound_field (form , "reviews" )),
247+ """
248+ <table>
249+ <tbody><tr>
250+ <th><label for="id_reviews-0-title">Title:</label></th>
251+ <td>
252+ <input type="text" name="reviews-0-title" maxlength="255"
253+ id="id_reviews-0-title" value="Great!">
254+ </td>
255+ </tr>
256+ <tr>
257+ <th><label for="id_reviews-0-rating">Rating:</label></th>
258+ <td>
259+ <input type="number" name="reviews-0-rating"
260+ id="id_reviews-0-rating" value="10">
261+ </td>
262+ </tr>
263+ <tr>
264+ <th><label for="id_reviews-0-DELETE">Delete:</label></th>
265+ <td>
266+ <input type="checkbox" name="reviews-0-DELETE" id="id_reviews-0-DELETE">
267+ </td>
268+ </tr></tbody>
269+ <tbody><tr>
270+ <th><label for="id_reviews-1-title">Title:</label></th>
271+ <td>
272+ <input type="text" name="reviews-1-title" maxlength="255" id="id_reviews-1-title">
273+ </td>
274+ </tr>
275+ <tr>
276+ <th><label for="id_reviews-1-rating">Rating:</label></th>
277+ <td>
278+ <input type="number" name="reviews-1-rating" id="id_reviews-1-rating">
279+ </td>
280+ </tr>
281+ <tr>
282+ <th><label for="id_reviews-1-DELETE">Delete:</label></th>
283+ <td>
284+ <input type="checkbox" name="reviews-1-DELETE" id="id_reviews-1-DELETE">
285+ </td>
286+ </tr></tbody>
287+ </table>
288+ <input type="hidden" name="reviews-TOTAL_FORMS" value="2"
289+ id="id_reviews-TOTAL_FORMS"><input type="hidden"
290+ name="reviews-INITIAL_FORMS" value="1"
291+ id="id_reviews-INITIAL_FORMS">
292+ <input type="hidden" name="reviews-MIN_NUM_FORMS" value="0"
293+ id="id_reviews-MIN_NUM_FORMS"><input type="hidden"
294+ name="reviews-MAX_NUM_FORMS" value="1000" id="id_reviews-MAX_NUM_FORMS">""" ,
295+ )
296+
212297
213298# class NestedFormTests(TestCase):
214299# def test_update(self):
0 commit comments