1. from django import forms
    
  2. from django.forms.formsets import DELETION_FIELD_NAME, BaseFormSet
    
  3. from django.forms.models import (
    
  4.     BaseModelFormSet,
    
  5.     inlineformset_factory,
    
  6.     modelform_factory,
    
  7.     modelformset_factory,
    
  8. )
    
  9. from django.forms.utils import ErrorDict, ErrorList
    
  10. from django.test import TestCase
    
  11. 
    
  12. from .models import (
    
  13.     Host,
    
  14.     Manager,
    
  15.     Network,
    
  16.     ProfileNetwork,
    
  17.     Restaurant,
    
  18.     User,
    
  19.     UserPreferences,
    
  20.     UserProfile,
    
  21.     UserSite,
    
  22. )
    
  23. 
    
  24. 
    
  25. class InlineFormsetTests(TestCase):
    
  26.     def test_formset_over_to_field(self):
    
  27.         """
    
  28.         A formset over a ForeignKey with a to_field can be saved.
    
  29.         """
    
  30.         Form = modelform_factory(User, fields="__all__")
    
  31.         FormSet = inlineformset_factory(User, UserSite, fields="__all__")
    
  32. 
    
  33.         # Instantiate the Form and FormSet to prove
    
  34.         # you can create a form with no data
    
  35.         form = Form()
    
  36.         form_set = FormSet(instance=User())
    
  37. 
    
  38.         # Now create a new User and UserSite instance
    
  39.         data = {
    
  40.             "serial": "1",
    
  41.             "username": "apollo13",
    
  42.             "usersite_set-TOTAL_FORMS": "1",
    
  43.             "usersite_set-INITIAL_FORMS": "0",
    
  44.             "usersite_set-MAX_NUM_FORMS": "0",
    
  45.             "usersite_set-0-data": "10",
    
  46.             "usersite_set-0-user": "apollo13",
    
  47.         }
    
  48.         user = User()
    
  49.         form = Form(data)
    
  50.         if form.is_valid():
    
  51.             user = form.save()
    
  52.         else:
    
  53.             self.fail("Errors found on form:%s" % form_set)
    
  54. 
    
  55.         form_set = FormSet(data, instance=user)
    
  56.         if form_set.is_valid():
    
  57.             form_set.save()
    
  58.             usersite = UserSite.objects.values()
    
  59.             self.assertEqual(usersite[0]["data"], 10)
    
  60.             self.assertEqual(usersite[0]["user_id"], "apollo13")
    
  61.         else:
    
  62.             self.fail("Errors found on formset:%s" % form_set.errors)
    
  63. 
    
  64.         # Now update the UserSite instance
    
  65.         data = {
    
  66.             "usersite_set-TOTAL_FORMS": "1",
    
  67.             "usersite_set-INITIAL_FORMS": "1",
    
  68.             "usersite_set-MAX_NUM_FORMS": "0",
    
  69.             "usersite_set-0-id": str(usersite[0]["id"]),
    
  70.             "usersite_set-0-data": "11",
    
  71.             "usersite_set-0-user": "apollo13",
    
  72.         }
    
  73.         form_set = FormSet(data, instance=user)
    
  74.         if form_set.is_valid():
    
  75.             form_set.save()
    
  76.             usersite = UserSite.objects.values()
    
  77.             self.assertEqual(usersite[0]["data"], 11)
    
  78.             self.assertEqual(usersite[0]["user_id"], "apollo13")
    
  79.         else:
    
  80.             self.fail("Errors found on formset:%s" % form_set.errors)
    
  81. 
    
  82.         # Now add a new UserSite instance
    
  83.         data = {
    
  84.             "usersite_set-TOTAL_FORMS": "2",
    
  85.             "usersite_set-INITIAL_FORMS": "1",
    
  86.             "usersite_set-MAX_NUM_FORMS": "0",
    
  87.             "usersite_set-0-id": str(usersite[0]["id"]),
    
  88.             "usersite_set-0-data": "11",
    
  89.             "usersite_set-0-user": "apollo13",
    
  90.             "usersite_set-1-data": "42",
    
  91.             "usersite_set-1-user": "apollo13",
    
  92.         }
    
  93.         form_set = FormSet(data, instance=user)
    
  94.         if form_set.is_valid():
    
  95.             form_set.save()
    
  96.             usersite = UserSite.objects.values().order_by("data")
    
  97.             self.assertEqual(usersite[0]["data"], 11)
    
  98.             self.assertEqual(usersite[0]["user_id"], "apollo13")
    
  99.             self.assertEqual(usersite[1]["data"], 42)
    
  100.             self.assertEqual(usersite[1]["user_id"], "apollo13")
    
  101.         else:
    
  102.             self.fail("Errors found on formset:%s" % form_set.errors)
    
  103. 
    
  104.     def test_formset_over_inherited_model(self):
    
  105.         """
    
  106.         A formset over a ForeignKey with a to_field can be saved.
    
  107.         """
    
  108.         Form = modelform_factory(Restaurant, fields="__all__")
    
  109.         FormSet = inlineformset_factory(Restaurant, Manager, fields="__all__")
    
  110. 
    
  111.         # Instantiate the Form and FormSet to prove
    
  112.         # you can create a form with no data
    
  113.         form = Form()
    
  114.         form_set = FormSet(instance=Restaurant())
    
  115. 
    
  116.         # Now create a new Restaurant and Manager instance
    
  117.         data = {
    
  118.             "name": "Guido's House of Pasta",
    
  119.             "manager_set-TOTAL_FORMS": "1",
    
  120.             "manager_set-INITIAL_FORMS": "0",
    
  121.             "manager_set-MAX_NUM_FORMS": "0",
    
  122.             "manager_set-0-name": "Guido Van Rossum",
    
  123.         }
    
  124.         restaurant = User()
    
  125.         form = Form(data)
    
  126.         if form.is_valid():
    
  127.             restaurant = form.save()
    
  128.         else:
    
  129.             self.fail("Errors found on form:%s" % form_set)
    
  130. 
    
  131.         form_set = FormSet(data, instance=restaurant)
    
  132.         if form_set.is_valid():
    
  133.             form_set.save()
    
  134.             manager = Manager.objects.values()
    
  135.             self.assertEqual(manager[0]["name"], "Guido Van Rossum")
    
  136.         else:
    
  137.             self.fail("Errors found on formset:%s" % form_set.errors)
    
  138. 
    
  139.         # Now update the Manager instance
    
  140.         data = {
    
  141.             "manager_set-TOTAL_FORMS": "1",
    
  142.             "manager_set-INITIAL_FORMS": "1",
    
  143.             "manager_set-MAX_NUM_FORMS": "0",
    
  144.             "manager_set-0-id": str(manager[0]["id"]),
    
  145.             "manager_set-0-name": "Terry Gilliam",
    
  146.         }
    
  147.         form_set = FormSet(data, instance=restaurant)
    
  148.         if form_set.is_valid():
    
  149.             form_set.save()
    
  150.             manager = Manager.objects.values()
    
  151.             self.assertEqual(manager[0]["name"], "Terry Gilliam")
    
  152.         else:
    
  153.             self.fail("Errors found on formset:%s" % form_set.errors)
    
  154. 
    
  155.         # Now add a new Manager instance
    
  156.         data = {
    
  157.             "manager_set-TOTAL_FORMS": "2",
    
  158.             "manager_set-INITIAL_FORMS": "1",
    
  159.             "manager_set-MAX_NUM_FORMS": "0",
    
  160.             "manager_set-0-id": str(manager[0]["id"]),
    
  161.             "manager_set-0-name": "Terry Gilliam",
    
  162.             "manager_set-1-name": "John Cleese",
    
  163.         }
    
  164.         form_set = FormSet(data, instance=restaurant)
    
  165.         if form_set.is_valid():
    
  166.             form_set.save()
    
  167.             manager = Manager.objects.values().order_by("name")
    
  168.             self.assertEqual(manager[0]["name"], "John Cleese")
    
  169.             self.assertEqual(manager[1]["name"], "Terry Gilliam")
    
  170.         else:
    
  171.             self.fail("Errors found on formset:%s" % form_set.errors)
    
  172. 
    
  173.     def test_inline_model_with_to_field(self):
    
  174.         """
    
  175.         #13794 --- An inline model with a to_field of a formset with instance
    
  176.         has working relations.
    
  177.         """
    
  178.         FormSet = inlineformset_factory(User, UserSite, exclude=("is_superuser",))
    
  179. 
    
  180.         user = User.objects.create(username="guido", serial=1337)
    
  181.         UserSite.objects.create(user=user, data=10)
    
  182.         formset = FormSet(instance=user)
    
  183. 
    
  184.         # Testing the inline model's relation
    
  185.         self.assertEqual(formset[0].instance.user_id, "guido")
    
  186. 
    
  187.     def test_inline_model_with_primary_to_field(self):
    
  188.         """An inline model with a OneToOneField with to_field & primary key."""
    
  189.         FormSet = inlineformset_factory(
    
  190.             User, UserPreferences, exclude=("is_superuser",)
    
  191.         )
    
  192.         user = User.objects.create(username="guido", serial=1337)
    
  193.         UserPreferences.objects.create(user=user, favorite_number=10)
    
  194.         formset = FormSet(instance=user)
    
  195.         self.assertEqual(formset[0].fields["user"].initial, "guido")
    
  196. 
    
  197.     def test_inline_model_with_to_field_to_rel(self):
    
  198.         """
    
  199.         #13794 --- An inline model with a to_field to a related field of a
    
  200.         formset with instance has working relations.
    
  201.         """
    
  202.         FormSet = inlineformset_factory(UserProfile, ProfileNetwork, exclude=[])
    
  203. 
    
  204.         user = User.objects.create(username="guido", serial=1337, pk=1)
    
  205.         self.assertEqual(user.pk, 1)
    
  206.         profile = UserProfile.objects.create(user=user, about="about", pk=2)
    
  207.         self.assertEqual(profile.pk, 2)
    
  208.         ProfileNetwork.objects.create(profile=profile, network=10, identifier=10)
    
  209.         formset = FormSet(instance=profile)
    
  210. 
    
  211.         # Testing the inline model's relation
    
  212.         self.assertEqual(formset[0].instance.profile_id, 1)
    
  213. 
    
  214.     def test_formset_with_none_instance(self):
    
  215.         "A formset with instance=None can be created. Regression for #11872"
    
  216.         Form = modelform_factory(User, fields="__all__")
    
  217.         FormSet = inlineformset_factory(User, UserSite, fields="__all__")
    
  218. 
    
  219.         # Instantiate the Form and FormSet to prove
    
  220.         # you can create a formset with an instance of None
    
  221.         Form(instance=None)
    
  222.         FormSet(instance=None)
    
  223. 
    
  224.     def test_empty_fields_on_modelformset(self):
    
  225.         """
    
  226.         No fields passed to modelformset_factory() should result in no fields
    
  227.         on returned forms except for the id (#14119).
    
  228.         """
    
  229.         UserFormSet = modelformset_factory(User, fields=())
    
  230.         formset = UserFormSet()
    
  231.         for form in formset.forms:
    
  232.             self.assertIn("id", form.fields)
    
  233.             self.assertEqual(len(form.fields), 1)
    
  234. 
    
  235.     def test_save_as_new_with_new_inlines(self):
    
  236.         """
    
  237.         Existing and new inlines are saved with save_as_new.
    
  238. 
    
  239.         Regression for #14938.
    
  240.         """
    
  241.         efnet = Network.objects.create(name="EFNet")
    
  242.         host1 = Host.objects.create(hostname="irc.he.net", network=efnet)
    
  243. 
    
  244.         HostFormSet = inlineformset_factory(Network, Host, fields="__all__")
    
  245. 
    
  246.         # Add a new host, modify previous host, and save-as-new
    
  247.         data = {
    
  248.             "host_set-TOTAL_FORMS": "2",
    
  249.             "host_set-INITIAL_FORMS": "1",
    
  250.             "host_set-MAX_NUM_FORMS": "0",
    
  251.             "host_set-0-id": str(host1.id),
    
  252.             "host_set-0-hostname": "tranquility.hub.dal.net",
    
  253.             "host_set-1-hostname": "matrix.de.eu.dal.net",
    
  254.         }
    
  255. 
    
  256.         # To save a formset as new, it needs a new hub instance
    
  257.         dalnet = Network.objects.create(name="DALnet")
    
  258.         formset = HostFormSet(data, instance=dalnet, save_as_new=True)
    
  259. 
    
  260.         self.assertTrue(formset.is_valid())
    
  261.         formset.save()
    
  262.         self.assertQuerysetEqual(
    
  263.             dalnet.host_set.order_by("hostname"),
    
  264.             Host.objects.filter(
    
  265.                 hostname__in=[
    
  266.                     "matrix.de.eu.dal.net",
    
  267.                     "tranquility.hub.dal.net",
    
  268.                 ]
    
  269.             ).order_by("hostname"),
    
  270.         )
    
  271. 
    
  272.     def test_initial_data(self):
    
  273.         user = User.objects.create(username="bibi", serial=1)
    
  274.         UserSite.objects.create(user=user, data=7)
    
  275.         FormSet = inlineformset_factory(User, UserSite, extra=2, fields="__all__")
    
  276. 
    
  277.         formset = FormSet(instance=user, initial=[{"data": 41}, {"data": 42}])
    
  278.         self.assertEqual(formset.forms[0].initial["data"], 7)
    
  279.         self.assertEqual(formset.extra_forms[0].initial["data"], 41)
    
  280.         self.assertIn('value="42"', formset.extra_forms[1].as_p())
    
  281. 
    
  282. 
    
  283. class FormsetTests(TestCase):
    
  284.     def test_error_class(self):
    
  285.         """
    
  286.         Test the type of Formset and Form error attributes
    
  287.         """
    
  288.         Formset = modelformset_factory(User, fields="__all__")
    
  289.         data = {
    
  290.             "form-TOTAL_FORMS": "2",
    
  291.             "form-INITIAL_FORMS": "0",
    
  292.             "form-MAX_NUM_FORMS": "0",
    
  293.             "form-0-id": "",
    
  294.             "form-0-username": "apollo13",
    
  295.             "form-0-serial": "1",
    
  296.             "form-1-id": "",
    
  297.             "form-1-username": "apollo13",
    
  298.             "form-1-serial": "2",
    
  299.         }
    
  300.         formset = Formset(data)
    
  301.         # check if the returned error classes are correct
    
  302.         # note: formset.errors returns a list as documented
    
  303.         self.assertIsInstance(formset.errors, list)
    
  304.         self.assertIsInstance(formset.non_form_errors(), ErrorList)
    
  305.         for form in formset.forms:
    
  306.             self.assertIsInstance(form.errors, ErrorDict)
    
  307.             self.assertIsInstance(form.non_field_errors(), ErrorList)
    
  308. 
    
  309.     def test_initial_data(self):
    
  310.         User.objects.create(username="bibi", serial=1)
    
  311.         Formset = modelformset_factory(User, fields="__all__", extra=2)
    
  312.         formset = Formset(initial=[{"username": "apollo11"}, {"username": "apollo12"}])
    
  313.         self.assertEqual(formset.forms[0].initial["username"], "bibi")
    
  314.         self.assertEqual(formset.extra_forms[0].initial["username"], "apollo11")
    
  315.         self.assertIn('value="apollo12"', formset.extra_forms[1].as_p())
    
  316. 
    
  317.     def test_extraneous_query_is_not_run(self):
    
  318.         Formset = modelformset_factory(Network, fields="__all__")
    
  319.         data = {
    
  320.             "test-TOTAL_FORMS": "1",
    
  321.             "test-INITIAL_FORMS": "0",
    
  322.             "test-MAX_NUM_FORMS": "",
    
  323.             "test-0-name": "Random Place",
    
  324.         }
    
  325.         with self.assertNumQueries(1):
    
  326.             formset = Formset(data, prefix="test")
    
  327.             formset.save()
    
  328. 
    
  329. 
    
  330. class CustomWidget(forms.widgets.TextInput):
    
  331.     pass
    
  332. 
    
  333. 
    
  334. class UserSiteForm(forms.ModelForm):
    
  335.     class Meta:
    
  336.         model = UserSite
    
  337.         fields = "__all__"
    
  338.         widgets = {
    
  339.             "id": CustomWidget,
    
  340.             "data": CustomWidget,
    
  341.         }
    
  342.         localized_fields = ("data",)
    
  343. 
    
  344. 
    
  345. class Callback:
    
  346.     def __init__(self):
    
  347.         self.log = []
    
  348. 
    
  349.     def __call__(self, db_field, **kwargs):
    
  350.         self.log.append((db_field, kwargs))
    
  351.         return db_field.formfield(**kwargs)
    
  352. 
    
  353. 
    
  354. class FormfieldCallbackTests(TestCase):
    
  355.     """
    
  356.     Regression for #13095 and #17683: Using base forms with widgets
    
  357.     defined in Meta should not raise errors and BaseModelForm should respect
    
  358.     the specified pk widget.
    
  359.     """
    
  360. 
    
  361.     def test_inlineformset_factory_default(self):
    
  362.         Formset = inlineformset_factory(
    
  363.             User, UserSite, form=UserSiteForm, fields="__all__"
    
  364.         )
    
  365.         form = Formset().forms[0]
    
  366.         self.assertIsInstance(form["id"].field.widget, CustomWidget)
    
  367.         self.assertIsInstance(form["data"].field.widget, CustomWidget)
    
  368.         self.assertFalse(form.fields["id"].localize)
    
  369.         self.assertTrue(form.fields["data"].localize)
    
  370. 
    
  371.     def test_modelformset_factory_default(self):
    
  372.         Formset = modelformset_factory(UserSite, form=UserSiteForm)
    
  373.         form = Formset().forms[0]
    
  374.         self.assertIsInstance(form["id"].field.widget, CustomWidget)
    
  375.         self.assertIsInstance(form["data"].field.widget, CustomWidget)
    
  376.         self.assertFalse(form.fields["id"].localize)
    
  377.         self.assertTrue(form.fields["data"].localize)
    
  378. 
    
  379.     def assertCallbackCalled(self, callback):
    
  380.         id_field, user_field, data_field = UserSite._meta.fields
    
  381.         expected_log = [
    
  382.             (id_field, {"widget": CustomWidget}),
    
  383.             (user_field, {}),
    
  384.             (data_field, {"widget": CustomWidget, "localize": True}),
    
  385.         ]
    
  386.         self.assertEqual(callback.log, expected_log)
    
  387. 
    
  388.     def test_inlineformset_custom_callback(self):
    
  389.         callback = Callback()
    
  390.         inlineformset_factory(
    
  391.             User,
    
  392.             UserSite,
    
  393.             form=UserSiteForm,
    
  394.             formfield_callback=callback,
    
  395.             fields="__all__",
    
  396.         )
    
  397.         self.assertCallbackCalled(callback)
    
  398. 
    
  399.     def test_modelformset_custom_callback(self):
    
  400.         callback = Callback()
    
  401.         modelformset_factory(UserSite, form=UserSiteForm, formfield_callback=callback)
    
  402.         self.assertCallbackCalled(callback)
    
  403. 
    
  404. 
    
  405. class BaseCustomDeleteFormSet(BaseFormSet):
    
  406.     """
    
  407.     A formset mix-in that lets a form decide if it's to be deleted.
    
  408.     Works for BaseFormSets. Also works for ModelFormSets with #14099 fixed.
    
  409. 
    
  410.     form.should_delete() is called. The formset delete field is also suppressed.
    
  411.     """
    
  412. 
    
  413.     def add_fields(self, form, index):
    
  414.         super().add_fields(form, index)
    
  415.         self.can_delete = True
    
  416.         if DELETION_FIELD_NAME in form.fields:
    
  417.             del form.fields[DELETION_FIELD_NAME]
    
  418. 
    
  419.     def _should_delete_form(self, form):
    
  420.         return hasattr(form, "should_delete") and form.should_delete()
    
  421. 
    
  422. 
    
  423. class FormfieldShouldDeleteFormTests(TestCase):
    
  424.     """
    
  425.     BaseModelFormSet should use ModelFormSet method _should_delete_form.
    
  426.     """
    
  427. 
    
  428.     class BaseCustomDeleteModelFormSet(BaseModelFormSet, BaseCustomDeleteFormSet):
    
  429.         """Model FormSet with CustomDelete MixIn"""
    
  430. 
    
  431.     class CustomDeleteUserForm(forms.ModelForm):
    
  432.         """A model form with a 'should_delete' method"""
    
  433. 
    
  434.         class Meta:
    
  435.             model = User
    
  436.             fields = "__all__"
    
  437. 
    
  438.         def should_delete(self):
    
  439.             """Delete form if odd serial."""
    
  440.             return self.instance.serial % 2 != 0
    
  441. 
    
  442.     NormalFormset = modelformset_factory(
    
  443.         User, form=CustomDeleteUserForm, can_delete=True
    
  444.     )
    
  445.     DeleteFormset = modelformset_factory(
    
  446.         User, form=CustomDeleteUserForm, formset=BaseCustomDeleteModelFormSet
    
  447.     )
    
  448. 
    
  449.     data = {
    
  450.         "form-TOTAL_FORMS": "4",
    
  451.         "form-INITIAL_FORMS": "0",
    
  452.         "form-MAX_NUM_FORMS": "4",
    
  453.         "form-0-username": "John",
    
  454.         "form-0-serial": "1",
    
  455.         "form-1-username": "Paul",
    
  456.         "form-1-serial": "2",
    
  457.         "form-2-username": "George",
    
  458.         "form-2-serial": "3",
    
  459.         "form-3-username": "Ringo",
    
  460.         "form-3-serial": "5",
    
  461.     }
    
  462. 
    
  463.     delete_all_ids = {
    
  464.         "form-0-DELETE": "1",
    
  465.         "form-1-DELETE": "1",
    
  466.         "form-2-DELETE": "1",
    
  467.         "form-3-DELETE": "1",
    
  468.     }
    
  469. 
    
  470.     def test_init_database(self):
    
  471.         """Add test data to database via formset"""
    
  472.         formset = self.NormalFormset(self.data)
    
  473.         self.assertTrue(formset.is_valid())
    
  474.         self.assertEqual(len(formset.save()), 4)
    
  475. 
    
  476.     def test_no_delete(self):
    
  477.         """Verify base formset doesn't modify database"""
    
  478.         # reload database
    
  479.         self.test_init_database()
    
  480. 
    
  481.         # pass standard data dict & see none updated
    
  482.         data = dict(self.data)
    
  483.         data["form-INITIAL_FORMS"] = 4
    
  484.         data.update(
    
  485.             {
    
  486.                 "form-%d-id" % i: user.pk
    
  487.                 for i, user in enumerate(User.objects.order_by("pk"))
    
  488.             }
    
  489.         )
    
  490.         formset = self.NormalFormset(data, queryset=User.objects.all())
    
  491.         self.assertTrue(formset.is_valid())
    
  492.         self.assertEqual(len(formset.save()), 0)
    
  493.         self.assertEqual(len(User.objects.all()), 4)
    
  494. 
    
  495.     def test_all_delete(self):
    
  496.         """Verify base formset honors DELETE field"""
    
  497.         # reload database
    
  498.         self.test_init_database()
    
  499. 
    
  500.         # create data dict with all fields marked for deletion
    
  501.         data = dict(self.data)
    
  502.         data["form-INITIAL_FORMS"] = 4
    
  503.         data.update(
    
  504.             {"form-%d-id" % i: user.pk for i, user in enumerate(User.objects.all())}
    
  505.         )
    
  506.         data.update(self.delete_all_ids)
    
  507.         formset = self.NormalFormset(data, queryset=User.objects.all())
    
  508.         self.assertTrue(formset.is_valid())
    
  509.         self.assertEqual(len(formset.save()), 0)
    
  510.         self.assertEqual(len(User.objects.all()), 0)
    
  511. 
    
  512.     def test_custom_delete(self):
    
  513.         """Verify DeleteFormset ignores DELETE field and uses form method"""
    
  514.         # reload database
    
  515.         self.test_init_database()
    
  516. 
    
  517.         # Create formset with custom Delete function
    
  518.         # create data dict with all fields marked for deletion
    
  519.         data = dict(self.data)
    
  520.         data["form-INITIAL_FORMS"] = 4
    
  521.         data.update(
    
  522.             {
    
  523.                 "form-%d-id" % i: user.pk
    
  524.                 for i, user in enumerate(User.objects.order_by("pk"))
    
  525.             }
    
  526.         )
    
  527.         data.update(self.delete_all_ids)
    
  528.         formset = self.DeleteFormset(data, queryset=User.objects.all())
    
  529. 
    
  530.         # Three with odd serial values were deleted.
    
  531.         self.assertTrue(formset.is_valid())
    
  532.         self.assertEqual(len(formset.save()), 0)
    
  533.         self.assertEqual(User.objects.count(), 1)
    
  534. 
    
  535.         # No odd serial values left.
    
  536.         odd_serials = [user.serial for user in User.objects.all() if user.serial % 2]
    
  537.         self.assertEqual(len(odd_serials), 0)
    
  538. 
    
  539. 
    
  540. class RedeleteTests(TestCase):
    
  541.     def test_resubmit(self):
    
  542.         u = User.objects.create(username="foo", serial=1)
    
  543.         us = UserSite.objects.create(user=u, data=7)
    
  544.         formset_cls = inlineformset_factory(User, UserSite, fields="__all__")
    
  545.         data = {
    
  546.             "serial": "1",
    
  547.             "username": "foo",
    
  548.             "usersite_set-TOTAL_FORMS": "1",
    
  549.             "usersite_set-INITIAL_FORMS": "1",
    
  550.             "usersite_set-MAX_NUM_FORMS": "1",
    
  551.             "usersite_set-0-id": str(us.pk),
    
  552.             "usersite_set-0-data": "7",
    
  553.             "usersite_set-0-user": "foo",
    
  554.             "usersite_set-0-DELETE": "1",
    
  555.         }
    
  556.         formset = formset_cls(data, instance=u)
    
  557.         self.assertTrue(formset.is_valid())
    
  558.         formset.save()
    
  559.         self.assertEqual(UserSite.objects.count(), 0)
    
  560.         formset = formset_cls(data, instance=u)
    
  561.         # Even if the "us" object isn't in the DB any more, the form
    
  562.         # validates.
    
  563.         self.assertTrue(formset.is_valid())
    
  564.         formset.save()
    
  565.         self.assertEqual(UserSite.objects.count(), 0)
    
  566. 
    
  567.     def test_delete_already_deleted(self):
    
  568.         u = User.objects.create(username="foo", serial=1)
    
  569.         us = UserSite.objects.create(user=u, data=7)
    
  570.         formset_cls = inlineformset_factory(User, UserSite, fields="__all__")
    
  571.         data = {
    
  572.             "serial": "1",
    
  573.             "username": "foo",
    
  574.             "usersite_set-TOTAL_FORMS": "1",
    
  575.             "usersite_set-INITIAL_FORMS": "1",
    
  576.             "usersite_set-MAX_NUM_FORMS": "1",
    
  577.             "usersite_set-0-id": str(us.pk),
    
  578.             "usersite_set-0-data": "7",
    
  579.             "usersite_set-0-user": "foo",
    
  580.             "usersite_set-0-DELETE": "1",
    
  581.         }
    
  582.         formset = formset_cls(data, instance=u)
    
  583.         us.delete()
    
  584.         self.assertTrue(formset.is_valid())
    
  585.         formset.save()
    
  586.         self.assertEqual(UserSite.objects.count(), 0)