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.