In Django, how to retrieve an id to use in a dynamic link?

I have a Django app. In my sidebar I have a navigation link that goes to a list of reports. That link needs an id to get the correct list of reports.

The <li> element in base.html that links to the ga_reports page is below. This link needs the app_config.id to resolve correctly. With this element {{ app_config.id }} does not exist because {{ app_config }} does not exist. I will add that on the Reports page, this link works as {{ app_config }} gets created.

Why does {{ app_config }} exist on the Reports page but not on the parent page?

                <li class="relative px-12 py-3">
                    <a class="inline-flex items-center w-full text-sm font-semibold transition-colors duration-150 hover:text-gray-800 dark:hover:text-gray-200 "
                        href="/base/ga_reports/{{ app_config.id }}">
                        <span class="ml-4">Reports</span>
                    </a>
                </li>

These are entries from base/urls.py

    path('app_config', app_config_views.app_config, name='app_config'),
    ...
    path('ga_reports/<int:app_config_id>', ga_views.ga_reports, name='ga_reports'),

The AppConfiguration model is included on base/views.py

from .models import AppConfiguration

This is base/ga_views.py

@login_required
def ga_reports(request, app_config_id):
    app_config = AppConfiguration.objects.filter(id = app_config_id).first()
    if not app_config:
        messages.error(request, "Invalid Configuration")
        return redirect('app_config')
        
    return render(request, 'base/ga_reports.html', {'app_config': app_config})

This is app_config_views.py.

@login_required
def app_config(request):
    app_configs = []
    for app_type in APP_TYPE:
        app_type_subscription = UserSubscription.objects.filter(user_id = request.user.id, app_type = app_type[0], is_active = True, is_expired = False).first()
        app_configuration = AppConfiguration.objects.filter(user_id = request.user.id, app_type = app_type[0], is_deleted = False, is_verified = True).first()
        is_subscribed = True if app_type_subscription else False #add more configurations?
        if app_configuration and is_subscribed:
            app_configuration.is_active = True
            app_configuration.save()
            print("Done")        
        is_app_configured = True if (is_subscribed and app_configuration) or (not is_subscribed) else False
        cancel_subscription_url = app_type_subscription.cancel_url if is_subscribed and app_type_subscription else ''
        
        app_configs.append({
            'app_type_k': app_type[0],
            'app_type_v': app_type[1],
            'app_type_subscription': app_type_subscription,
            'app_configuration': app_configuration,
            'is_subscribed': is_subscribed,
            'is_app_configured': is_app_configured,
            'cancel_subscription_url': cancel_subscription_url
        })

    app_config_id = 0
    content = {
        'app_config_id': app_config_id,
        'app_configs': app_configs
    }

    app_config = None
    if app_config_id != 0:
        app_config = AppConfiguration.objects.filter(id = app_config_id).first()
        if not app_config:
            messages.error(request, "Invalid Configuration")
            return redirect('app_config')

    content.update({"app_config": app_config})

    if request.method == 'POST':
        form = AppConfigurationForm(data=request.POST, instance=app_config)
        if form.is_valid():
            app_config = form.save(commit=False)
            app_config.user_id = request.user.id
            app_config.is_active = True
            app_config.save()
            if app_config_id != 0:
                messages.success(request, "Configuration Updated!")
            else:
                messages.success(request, "Configuration Added!")
            return redirect('app_config')

        else:
            for field_name, error_list in json.loads(form.errors.as_json()).items():
                error_message = error_list[0]["message"]
                error_message = error_message.replace('This field', f'This field ({field_name})')

                content.update({f'{field_name}_error': True})
                messages.error(request, error_message)


    return render(request, 'base/app_configurations.html', content)

As is, the block where you set an app_config object can never execute:

# app_config_views.py
# [...]
    app_config_id = 0      # <-- 1. Because of this,
    content = {
        'app_config_id': app_config_id,
        'app_configs': app_configs
    }

    app_config = None
    if app_config_id != 0: # <-- 1. (cont.) this check will always fail
                           # Which means that the below indentation never executes
        app_config = AppConfiguration.objects.filter(id = app_config_id).first()
        if not app_config:
            messages.error(request, "Invalid Configuration")
            return redirect('app_config')

    # Which means that `app_config` is `None` when the below line executes
    content.update({"app_config": app_config}) 

Your code is basically guaranteeing that app_config will never exist when the template gets rendered.

Вернуться на верх