'Unable to access filefield file via URL with Django
tldr: Problems with accessing filefield's URL attribute led me to realize that I also have to check how to serve media files in debug mode with django's runserver. I have no clue how to continue.
Long version:
I am a Django newbie and totally lost how to access a filefield object with the browser.
Here is my settings.py in the project root:
import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
MEDIA_ROOT = os.path.join(BASE_DIR, 'rgeingabe/documents/')
MEDIA_URL = ''
#STATIC_URL = 'static/'
#STATIC_ROOT = os.path.join(BASE_DIR, 'rgeingabe/static')
I also set the DEBUG mode to true.
Here is the project's urls.py:
from django.conf.urls import include, url
from django.contrib import admin
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^rgeingabe/', include('rgeingabe.urls')),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
I hope that it is right to include that static information in the project's urls.py. First I tried to do that in the app's urls.py, but I guess that was wrong.
Next, to the models.py:
class Document(models.Model):
beschreibung = models.CharField(max_length=255, blank=True)
datei = models.FileField(upload_to='')
hochgeladen_am = models.DateTimeField(auto_now_add=True)
gehoert_zu_rg = models.ForeignKey('Pkvjanosch', on_delete=models.CASCADE)
def save(self, rgauswahl, *args, **kwargs):
d = Pkvjanosch.objects.get(rg_id = rgauswahl)
neuer_dateiname = d.rgsteller + " " + d.rgdatum.strftime("%d.%m.%Y")
self.datei.name = neuer_dateiname
super(Document, self).save(*args, **kwargs)
d.scanablageort = neuer_dateiname
d.save()
I try to access the download with a view. Here comes the app's views.py:
def uebersichteingaben_alle(request):
eingaben_alle_liste = get_list_or_404(Pkvjanosch)
alle_uploaddateien = get_list_or_404(Document)
context = {
'eingaben_alle_liste': eingaben_alle_liste,
'alle_uploaddateien': alle_uploaddateien
}
return render(request, 'rgeingabe/eingaben_alle.html', context)
And finally I tried a dozen approaches how to access the object with a template. So, I startet with something like upload.url, but this did not work. Neither did approaches like "{% url upload %}", "{% url upload.datei %}", "{{upload.datei.url}}, and many more. It is as if upload.url is just empty. Here is the template:
<html>
<body>
<h1>Übersicht aller Eingaben</h1>
{% if eingaben_alle_liste %}
<table style="border-style:solid;border-width:3px;" rules="all">
<tr>
<th>ID</th>
<th>Rechnungssteller</th>
<th>Rechnungsdatum</th>
<th>Rechnungsbetrag</th>
<th>TK Übernahme</th>
<th>Continentale Übernahme</th>
<th>Abrechnungszeitraum</th>
<th>Anmerkungen</th>
<th>Scan</th>
</tr>
{% for eintrag in eingaben_alle_liste %}
<tr>
<td><a href="{%url 'rg_janosch:rgupdate' eintrag.rg_id %}">{{ eintrag.rg_id }}</a></td>
<td>{{ eintrag.rgsteller }}</td>
<td>{{ eintrag.rgdatum }}</td>
<td style="text-align:right;">{{ eintrag.rgbetrag }}</td>
<td style="text-align:right;">{{ eintrag.tkbetrag}}</td>
<td style="text-align:right;">{{ eintrag.contibetrag }}</td>
<td style="text-align:center;">{{ eintrag.rg_zeitraum }}</td>
<td>{{ eintrag.anmerkung }}</td>
{% if eintrag.scanablageort %}
{% for upload in alle_uploaddateien %}
{% if upload.gehoert_zu_rg_id == eintrag.rg_id %}
<td><a href="documents/{{ upload.datei }}">Scan</a></td>
<td>upload.datei: {{upload.datei}}</td>
{% endif %}
{% endfor %}
{% else %}
<td> </td>
{% endif %}
</tr>
{% endfor %}
</table>
{% else %}
<p>Keine Einträge vorhanden.</p>
{% endif %}
</body>
</html>
Solution 1:[1]
Solved (at least partially).
To everyone who might have a similar problem: I changed the lines in settings.py to
MEDIA_ROOT = os.path.join(BASE_DIR, 'rgeingabe/documents/')
MEDIA_URL = '/documents/'
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'rgeingabe/static')
The end of my project's urls.py read now like this:
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Finally in the template I could use this:
<td><a href="{{ upload.datei.url }}">{{ upload.datei.url }}</a></td>
I am so happy that it works now.
Now I have to think about if I find it good that instead of overwriting files, new files are written to disk with some kind of appendix in the name. And I have to figure out how to preserve the file extension while renaming the files in the upload process. Have a nice day everyone!
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | MDoe |
