I’m getting an error, but only when loading a specific template.
dir structure:
Project Name -> assets -> static ->(with the following 2 subdirectories):
-> css -> styles.css
-> images -> favicon.png
I have a 3 basic pages, all of which extend the same layout:
home - data entry
dashboard - displays dashboard
welcome - welcome message that allows you to navigate to home or dashboard
All three apply the proper css static files, however:
- When I go to home, terminal displays:
[02/Nov/2024 14:32:13] "GET /ISO22301/home/ HTTP/1.1" 200 20384
Not Found: /static/css/styles.css
[02/Nov/2024 14:32:13] "GET /static/css/styles.css HTTP/1.1" 404 2553
[02/Nov/2024 14:32:13] "GET /static/static/css/styles.css HTTP/1.1" 304 0
and renders properly. None of the other files display the error message and also render properly.
Their templates terminal output is:
[02/Nov/2024 14:41:53] "GET /ISO22301/dashboard/ HTTP/1.1" 200 18874
[02/Nov/2024 14:41:53] "GET /static/static/css/styles.css HTTP/1.1" 304 0
so it appears to be something with my directory structure and /static/static/css vs /static/css. I have tried various variants in settings and the templates without fixing the issue.
- In addition, favicons are only loaded if I go directly via url to the dashboard page, not form the input button on home.
settings.py:
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
STATIC_URL = 'static/'
#STATICFILES_DIRS = [BASE_DIR / "static"] # I've added and remved this to no effect
STATIC_ROOT = os.path.join(BASE_DIR, 'assets/')
Templates
layout
{% load static %}
<!DOCTYPE html>
<html lang = "en">
{% csrf_token %}
<head>
<link rel="stylesheet" href="{% static 'static/css/styles.css' %}">
<title>{{ browsertab }}</title>
<link rel="shortcut icon" type="image/png" href="{% static 'static/images/favicon.png' %}" >
<h1>{{ dashboard_title }}</h1>
{% block content %}
{% endblock %}
</body>
</html>
Dashboard
{% extends "ISO22301/layout.html" %}
{% block content %}
<table>
<body>
<!--Create flexbox to render header graphic-->
<div class="container" style="top: 5%;">
<!--Create LOO shape and iterate through rows>-->
{% for objtext in rows %}
<tr><td>
<!--Create row of topic shapes and spacer between shapes and apply status color-->
<!--Create pointed arrow and space to Outcome-->
{% for a_text in objtext %}
{% if a_text.objective_position == 1 %}
<div class="item_LoO_Name">
{{ a_text.objective_text|linebreaks}}</div>
{% else %}
{% if a_text.objective_position != 10 %}
<div class="space"></div>
<a href="{% url 'testpage' %}">
<div class="Objective" style= 'background-color:{{ a_text.objective_background }}'>
{{ a_text.objective_text|linebreaks}}</div>
</a>
{% else %}
<div class="space"></div>
<div class="triangle-right"></div>
<div class="spaceblank"></div>
<div class="item_Outcome_Name">
{{ a_text.objective_text|linebreaks}}</div>
{% endif %}
{% endif %}
{% endfor %}
{% endfor %}
<div>
{% if data_entry_button == 1 %}
<a href="{% url 'home' %}">
<button>Go to Data Entry</button>
</a>
{% endif %}
</td>
</div>
</tr>
</div>
</div>
</form>
{% endblock %}
home
{% extends "ISO22301/layout.html" %}
{% block content %}
<form method='POST' action='{% url 'home' %}' enctype='multipart/form-data'>
{% csrf_token %}
<table>
<head>
<th>Project</th>
{% for n in objheader %}
<th>Objective</th>
{% endfor %}
<th>Outcome</th>
</head>
<body>
{% if messages %}
{% for message in messages %}
{% if message.tags == 'success' %}
<div class="alert alert-success alert-dismissible" role="alert">
<a href="{% url 'home' %}">
<button type="button" class="buttonmessage" data-dismiss="alert" aria-label="Close">
{{ message|safe }} <span aria-hidden="true">×</span>
</button>
</a>
</div>
{% endif %}
{% endfor %}
{% endif %}
{% for formset in formset_list %}
{{ formset.management_form }}
<tr>
{% for form in formset %}
<td> {{ form.objective_text }} {{ form.objective.as_hidden }} {{ form.id.as_hidden }}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
<div>
<input type='submit' name= 'Save' value='Save Data'>
</div>
<div>
<input type='submit' name= 'Dashboard_Test' value='Go to Dashboard Test'>
<div>
<input type='submit' name= 'Dashboard' value='Go to Dashboard'>
</div>
</div>
</form>
{% endblock %}
relevant part of views.py:
def home(request):
#Identify current dashboard
n=1# Dashboard id number returned from button_id in GET data
request.session['dashboard_id'] = n #assign dashboard_id the value n
dashboard_id = request.session.get('dashboard_id') # This how you retireve the id in any view
# Add the formset to context dictionary
context_items = createcontext(dashboard_id)
formset_list = context_items[0]
objheader = context_items[1]
browsertab = context_items[2]
dashboard = context_items[3]
context = {
'formset_list': formset_list,
'objheader': objheader,
'browsertab': browsertab,
'dashboard_title' : dashboard,
}
if request.method == "POST":#Creat a formset of teh POST data filterd by dashbaor and iterated over 6 rows
formset_list=[ObjectivesFormSet(request.POST,prefix=f'row-{I}',
queryset=Objectives.objects.filter(
dashboard = dashboard_id, row=I
).order_by('id'))
for i in range(1,7)
]
for formset in formset_list: # Check if formset is valid
if formset.is_valid():
for form in formset:# loop through all the forms to save the data
form.save()
context = {
'formset_list': formset_list,
'objheader': objheader,
'browsertab': browsertab,
'dashboard_title' : dashboard,
} # update context to include new data
if request.POST.get('Dashboard'): #sets "'Dashboard_Test' button to 0 to not display it
context_items = createdashboard(dashboard_id)
data2 = context_items[0]
rows = context_items[1]
data_entry_button = 0 #changes button value to 1 to display button when page called from data entry "Dashboard Test' button"
context = {
'objective_text': data2,
'rows': rows,
'browsertab': browsertab,
'dashboard_title' : dashboard,
'data_entry_button': data_entry_button
}
return render(request, 'ISO22301/dashboard.html', context)
elif request.POST.get('Dashboard_Test'):
context_items = createdashboard(dashboard_id)
data2 = context_items[0]
rows = context_items[1]
data_entry_button = 1 #changes button vlue to 1 to display button when page called from data entry "Dashboard Test' button"
context = {
'objective_text': data2,
'rows': rows,
'browsertab': browsertab,
'dashboard_title' : dashboard,
'data_entry_button': data_entry_button
}
return render(request, 'ISO22301/dashboard.html', context)
elif request.POST.get('Save'):
messages.success(request, "Data Saved")
return render(request, 'ISO22301/home.html', context)
else: # GET request
return render(request, 'ISO22301/home.html', context)
def dashboard(request): #creates data for use in flexbox without data entry button
dashboard_id = 1 #Temporary placeholder
#dashboard_id = request.session.get('dashboard_id') # This how you retireve the id in any view
context_items = createdashboard(dashboard_id)
data2 = context_items[0]
rows = context_items[1]
layout_text = layouttext(dashboard_id)
browsertab = layout_text[0]
dashboard = layout_text[1]
data_entry_button = 0
context = {
'objective_text': data2,
'rows': rows,
'browsertab': browsertab,
'dashboard_title' : dashboard,
'data_entry_button': data_entry_button,
}
return render(request, 'ISO22301/dashboard.html', context)