(self)
| 823 | self.validate_unique() |
| 824 | |
| 825 | def validate_unique(self): |
| 826 | # Collect unique_checks and date_checks to run from all the forms. |
| 827 | all_unique_checks = set() |
| 828 | all_date_checks = set() |
| 829 | forms_to_delete = self.deleted_forms |
| 830 | valid_forms = [ |
| 831 | form |
| 832 | for form in self.forms |
| 833 | if form.is_valid() and form not in forms_to_delete |
| 834 | ] |
| 835 | for form in valid_forms: |
| 836 | exclude = form._get_validation_exclusions() |
| 837 | unique_checks, date_checks = form.instance._get_unique_checks( |
| 838 | exclude=exclude, |
| 839 | include_meta_constraints=True, |
| 840 | ) |
| 841 | all_unique_checks.update(unique_checks) |
| 842 | all_date_checks.update(date_checks) |
| 843 | |
| 844 | errors = [] |
| 845 | # Do each of the unique checks (unique and unique_together) |
| 846 | for uclass, unique_check in all_unique_checks: |
| 847 | seen_data = set() |
| 848 | for form in valid_forms: |
| 849 | # Get the data for the set of fields that must be unique among |
| 850 | # the forms. |
| 851 | row_data = ( |
| 852 | field if field in self.unique_fields else form.cleaned_data[field] |
| 853 | for field in unique_check |
| 854 | if field in form.cleaned_data |
| 855 | ) |
| 856 | # Reduce Model instances to their primary key values |
| 857 | row_data = tuple( |
| 858 | ( |
| 859 | d._get_pk_val() |
| 860 | if hasattr(d, "_get_pk_val") |
| 861 | # Prevent "unhashable type" errors later on. |
| 862 | else make_hashable(d) |
| 863 | ) |
| 864 | for d in row_data |
| 865 | ) |
| 866 | if row_data and None not in row_data: |
| 867 | # if we've already seen it then we have a uniqueness |
| 868 | # failure |
| 869 | if row_data in seen_data: |
| 870 | # poke error messages into the right places and mark |
| 871 | # the form as invalid |
| 872 | errors.append(self.get_unique_error_message(unique_check)) |
| 873 | form._errors[NON_FIELD_ERRORS] = self.error_class( |
| 874 | [self.get_form_error()], |
| 875 | renderer=self.renderer, |
| 876 | ) |
| 877 | # Remove the data from the cleaned_data dict since it |
| 878 | # was invalid. |
| 879 | for field in unique_check: |
| 880 | if field in form.cleaned_data: |
| 881 | del form.cleaned_data[field] |
| 882 | # mark the data as seen |
no test coverage detected