Django Unit tests can't ovveride variable from tessting when post

I need a test for update view. My update view creates folders. For tests I want to change path of the folders. I tried to change settings with override_settings decorator and with with self.settings(): statment from https://docs.djangoproject.com/en/2.2/topics/testing/tools/#django.test.modify_settings

But when I run post in my test the folders are created according to settings of my project not test settings. The path for creating the folders in my settings is saving in variable CERTIFICATION_WORKS_ROOT. In my view I import it as from django.conf import settings and then output_path = settings.CERTIFICATION_WORKS_ROOT. For debugging I added in view print(f'output_path in view - {output_path}'), and in my test print(f'test settings - {settings.CERTIFICATION_WORKS_ROOT}'). In my settings the variable is defined as:

CERTIFICATION_WORKS_ROOT = os.path.join('/home/oleh/Documents/certDB_output/')

Here is my update view class:

...

from django.conf import settings
output_path = settings.CERTIFICATION_WORKS_ROOT
print(f'output_path in view - {output_path}')

...

class UpdateCase(LoginRequiredMixin, PassRequestToFormViewMixin, UpdateView):
    model = Case
    login_url = reverse_lazy('login')
    template_name = 'case/update_case.html'
    form_class = CaseForm

    def summary_list(self):
        work_list = CertificationByDocumentAnalysis.\
            objects.filter(case=self.object).values(
                'id',
                'work_number',
                'startdate',
                'work_type',
                'producer__name',
                'producer__address',
                'producer__code',
                'case__id',
                'case__agreement'
            )
        conformity_assessment_list = ConformityAssessment.\
            objects.filter(case=self.object).values(
                'id',
                'work_number',
                'startdate',
                'work_type',
                'producer__name',
                'producer__address',
                'producer__code',
                'case__id',
                'case__agreement'
            )
        declaration_of_conformity_list = DeclarationOfConformity.\
            objects.filter(case=self.object).values(
                'id',
                'work_number',
                'startdate',
                'work_type',
                'producer__name',
                'producer__address',
                'producer__code',
                'case__id',
                'case__agreement'
            )
        hygienic_examination_list = HygienicExamination.\
            objects.filter(case=self.object).values(
                'id',
                'work_number',
                'startdate',
                'work_type',
                'producer__name',
                'producer__address',
                'producer__code',
                'case__id',
                'case__agreement'
            )
        summary_list = conformity_assessment_list.union(work_list)
        summary_list = hygienic_examination_list.union(summary_list)
        summary_list = declaration_of_conformity_list.union(summary_list)
        summary_list = summary_list.order_by('work_number')
        return summary_list

    def get_context_data(self, *args, **kwargs):
        context = super(UpdateCase, self).get_context_data(*args, **kwargs)
        try:
            calculation = Calculation.objects.\
                get(case__id=self.object.id)
        except Calculation.DoesNotExist:
            calculation = None
        case = self.object
        context['path'] = get_path(case)
        context['calculation'] = calculation
        context['case_id'] = case.id
        context['case_type'] = case.get_case_type_display
        context['next'] = 'update_case'
        context['summary_list'] = self.summary_list()

        if calculation != None:
            calculation_dailies = CalculationDaily.objects.filter(
                calculation=calculation)
            calculation_cars = CalculationCar.objects.filter(
                calculation=calculation)
            calculation_transits = CalculationExpense.objects.filter(
                calculation=calculation, expenses_type='transit')
            calculation_accommodations = CalculationExpense.objects.filter(
                calculation=calculation, expenses_type='accommodation')
            calculation_others = CalculationExpense.objects.filter(
                calculation=calculation, expenses_type='other')
            context['calculation_dailies'] = calculation_dailies
            context['calculation_cars'] = calculation_cars
            context['calculation_transits'] = calculation_transits
            context['calculation_accommodations'] = calculation_accommodations
            context['calculation_others'] = calculation_others

        try:
            business_trip = BusinessTrip.objects.get(case=case)
        except BusinessTrip.DoesNotExist:
            business_trip = None
        context['business_trip'] = business_trip
        if business_trip != None:
            business_trip_cars = BusinessTripCar.objects.filter(
                business_trip_employee__business_trip__id=business_trip.id)
            context['business_trip_cars'] = business_trip_cars
            business_trip_employees = BusinessTripEmployee.objects.filter(
                business_trip__id=business_trip.id)
            context['business_trip_employees'] = business_trip_employees
            business_trip_expenses = BusinessTripExpense.objects.filter(
                business_trip_employee__business_trip__id=business_trip.id)
            context['business_trip_expenses'] = business_trip_expenses
            business_trip_dailies = BusinessTripDaily.objects.filter(
                business_trip_employee__business_trip__id=business_trip.id)
            context['business_trip_dailies'] = business_trip_dailies
        return context
   
    def form_valid(self, form):
        if self.request.user != Case.objects.get(id=self.object.id).author and self.request.user.id != 1:
            return self.handle_no_permission()
        new_case = self.object
        old_case = Case.objects.get(id=self.object.id)
        rename_case_folder(new_case, old_case)
        self.object.author = Case.objects.get(id=self.object.id).author
        self.object = form.save()
        return HttpResponseRedirect(self.get_success_url())

    def get_success_url(self):
        '''payments = Payment.objects\
            .filter(case__id=self.object.id)'''
        messages.success(self.request, 'Справу успішно збережено!')
        return reverse('update_case', kwargs={'pk': self.kwargs.get('pk')})

    def post(self, request, *args, **kwargs):
        if request.POST.get('cancel_button'):
            messages.info(request, 'Редагування справи відмінено!')
            return HttpResponseRedirect(reverse('cases'))
        else:
            return super(UpdateCase, self).post(request, *args, **kwargs)

...

def rename_case_folder(new_case, old_case, *args, **kwargs):
    new_producer = kwargs.pop('new_producer', None)
    new_path = get_path(new_case)
    old_path = get_path(old_case)
    if new_producer is not None and new_producer not in old_path:
        old_path = old_path[:-(len(new_producer) + 2)]
    if not os.path.exists(old_path):
        os.makedirs(old_path)
    if old_path != new_path:
        shutil.move(old_path, new_path)
        if new_case.customer != old_case.customer:
            message = f"'{old_path}' moved to '{new_path}' successfully."
            logger = logging.getLogger(__name__)
            logger.info(message)
        else:
            message = f"'{old_path}' renamed to '{new_path}' successfully."
            logger = logging.getLogger(__name__)
            logger.info(message)
    return None

...

def get_path(case):
    if case.producers:
        producers = ' ' + case.producers
    else:
        producers = ''
    path = os.path.join(output_path,
                        get_clean_parametr(case.body.simple_name),
                        get_clean_parametr(case.customer.simple_name),
                        str(case.startdate.year),
                        (case.agreement.replace('/', '_')
                         + ' від '
                         + case.startdate.strftime('%d-%m-%Y')
                         + producers
                         ))
    return path

Here is my test module:

from datetime import date
import os

from django.test import TestCase, Client, override_settings
from django.urls import reverse
from django.contrib.auth.models import User
from django.core.files.images import ImageFile

from case.models import *

TEST_WORKS_ROOT = os.path.join('/home/oleh/Documents/test_output/')


@override_settings(CERTIFICATION_WORKS_ROOT=TEST_WORKS_ROOT)
class TestCases(TestCase):

    fixtures = ['cases_test_data.json']

    def setUp(self):
        body1 = Body.objects.get(name='body_one')
        body1.logo.save('uploads/logo-UC.svg',
            ImageFile(open('/home/oleh/Downloads/logo-UC.svg', 'rb'), 'logo-UC'))
        self.client = Client()
        # remember url to case list page
        self.url = reverse('update_case', kwargs={'pk': 1})
        #self.url = reverse('cases')

    def test_form(self):
        user = User.objects.get(id=1)
        self.client.force_login(user)
        response = self.client.get(self.url)
        #print(response.url)

        self.assertEqual(response.status_code, 200)
        self.assertContains(response, 'ЗМІНИТИ СПРАВУ')
        self.assertContains(response, 'Додати роботу')
        self.assertContains(response, 'Друк')
        self.assertContains(response, 'Тип договору')
        self.assertContains(response, 'Замовник')
        self.assertContains(response, 'name="save_button"')
        self.assertContains(response, 'name="cancel_button"')
        self.assertContains(response, f'action="{self.url}"')

    def test_success_update(self):
        from django.conf import settings
        print(f'test settings - {settings.CERTIFICATION_WORKS_ROOT}')
        user = User.objects.get(id=1)
        body = Body.objects.get(id=1)
        customer2 = Enterprise.objects.get(id=2)
        self.client.force_login(user)
        with self.settings(CERTIFICATION_WORKS_ROOT=TEST_WORKS_ROOT):
            from django.conf import settings
            print(f'test settings - {settings.CERTIFICATION_WORKS_ROOT}')
            response = self.client.post(
                self.url,
                {
                    "body": body.id,
                    "author": user.id,
                    "agreement": "7/21/1",
                    "agreement_number": 1,
                    "case_type": "СО",
                    "currency": "USD",
                    "startdate": "2022-1-2",
                    "enddate": "2022-1-7",
                    "price": 150.00,
                    "customer": customer2.id
                },
                follow=True
            )

        self.assertEqual(response.status_code, 200)
        case = Case.objects.get(id=1)
        self.assertEqual(case.body.id, 1)
        self.assertEqual(case.author.id, 1)
        self.assertEqual(case.agreement, "7/21/1")
        self.assertEqual(case.agreement_number, 1)
        self.assertEqual(case.case_type, 'СО')
        self.assertEqual(case.currency, 'USD')
        self.assertEqual(case.startdate, date(2022, 1, 2))
        self.assertEqual(case.enddate, date(2022, 1, 7))
        self.assertEqual(case.price, 150.00)
        self.assertEqual(case.customer.id, 2)

        self.assertContains(response, 'Справу успішно збережено!')

        self.assertEqual(response.redirect_chain[0][0],
            f'/update-case/{case.id}/')
        from django.conf import settings
        print(f'test settings - {settings.CERTIFICATION_WORKS_ROOT}')

And here is terminal output:

...
...
INFO 2022-01-23 09:45:20,665 signals: user None added Migration 0001_initial for sessions
output_path in view - /home/oleh/Documents/certDB_output/
System check identified no issues (0 silenced).
INFO 2022-01-23 09:45:22,858 signals: user None added body1
INFO 2022-01-23 09:45:22,869 signals: user None added user1
INFO 2022-01-23 09:45:22,877 signals: user None added enterprise_one, , код ЄДРПОУ: 
INFO 2022-01-23 09:45:22,882 signals: user None added enterprise_two, , код ЄДРПОУ: 
INFO 2022-01-23 09:45:22,913 signals: user None added body1 Договір №:7/21/1, від: 2022-01-01, Заявник: enterprise1, вартість: 100
INFO 2022-01-23 09:45:22,932 signals: user None added Справа №: 7/21/1; Сума оплати: 100; Дата оплати: 2022-01-04; Замовник: enterprise1
INFO 2022-01-23 09:45:22,961 signals: user None updated body1
INFO 2022-01-23 09:45:23,069 signals: user None added malcwkkfqvgmbwd768v4gn8f63f49tb6
INFO 2022-01-23 09:45:23,083 signals: user None added 86y7qzb4058ed9wajuqbz5t756sz1dmk
INFO 2022-01-23 09:45:23,092 signals: user None deleted malcwkkfqvgmbwd768v4gn8f63f49tb6
INFO 2022-01-23 09:45:23,103 signals: user None updated user1
INFO 2022-01-23 09:45:23,108 signals: user None updated 86y7qzb4058ed9wajuqbz5t756sz1dmk
.INFO 2022-01-23 09:45:23,381 signals: user None updated body1
test settings - /home/oleh/Documents/test_output/
INFO 2022-01-23 09:45:23,396 signals: user None added wucx5j3gd0esfm10twhf1vrtgxy8gjl7
INFO 2022-01-23 09:45:23,406 signals: user None added x0l3976s8x2hn2z8zwurilmjlzeokfk7
INFO 2022-01-23 09:45:23,412 signals: user None deleted wucx5j3gd0esfm10twhf1vrtgxy8gjl7
INFO 2022-01-23 09:45:23,417 signals: user None updated user1
INFO 2022-01-23 09:45:23,422 signals: user None updated x0l3976s8x2hn2z8zwurilmjlzeokfk7
test settings - /home/oleh/Documents/test_output/
INFO 2022-01-23 09:45:23,477 views: '/home/oleh/Documents/certDB_output/body1/enterprise1/2022/7_21_1 від 01-01-2022' moved to '/home/oleh/Documents/certDB_output/body1/enterprise2/2022/7_21_1 від 02-01-2022' successfully.
INFO 2022-01-23 09:45:23,499 signals: user None updated body1 Договір №:7/21/1, від: 2022-01-02, Заявник: enterprise2, вартість: 150.0
test settings - /home/oleh/Documents/test_output/
.
----------------------------------------------------------------------
Ran 2 tests in 0.910s

OK
Destroying test database for alias 'default'...

The folders were created in certDB_output not in test_output folder


As your code is currently written, settings are read only once at import time.

Remove the output_path = settings.CERTIFICATION_WORKS_ROOT and use settings.CERTIFICATION_WORKS_ROOT in your get_path method.

Or, patch case.views.output_path in your test.


Django advices against setting an alias of your settings, but thats what you did. See docs

Finally, avoid aliasing your settings as module-level constants as override_settings() won’t work on such values since they are only evaluated the first time the module is imported.

So inside get_path you should replace outout_path with settings.CERTIFICATION_WORKS_ROOT and it will work