Reputation: 21
I'm new in python and programming in general. I have this project to create a simple library to add new authors and upload books. I must also display the uploaded book details(total words, most common words, different words, etc.) when I open the book. Now to do this I know that I first must open the uploaded book in readmode, but I don't know how to access the file that I uploaded.
This is my models:
from django.db import models
from authors.models import Author
class Book(models.Model):
author = models.ForeignKey(Author, on_delete=models.CASCADE)
book_name = models.CharField(max_length=50)
genre = models.CharField(max_length=50)
files = models.FileField(upload_to='books/files/')
def __str__(self):
return self.book_name()
This is my forms:
from django import forms
from .models import Book
class BookForm(forms.ModelForm):
class Meta:
model = Book
fields = ('book_name', 'author', 'genre', 'files')
My views:
def create(request):
if request.method == 'POST':
form = BookForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect('books:home')
elif request.method == 'GET':
form = BookForm()
return render(request, 'books/create.html', {
'form': form
})
def detail(request, pk):
book = get_object_or_404(Book, pk=pk)
return render(request, 'books/detail.html', context={'book': book})
My details.html:
{% extends 'base.html' %}
{% block title %} {{ book.book_name }} {% endblock %}
{% block content %}
<p>Book title: {{ book.book_name }}</p>
<p>Genre: {{ book.genre }}</p>
<p>Author:
<a href="{% url 'authors:detail' book.author.pk %}">{{ book.author.full_name }}</a>
</p>
<p><button type="button"><a href="{{ book.files.url }}" target="_blank">Shkarko</a></button></p>
{% endblock %}
I want it to be shown in details.html.
Thanks in advance!
Upvotes: 1
Views: 1555
Reputation: 21
I asked my professor how to access the file and he told me that this method worked for him to read the uploaded file:
content = open(self.files.path, encoding="ISO-8859-1").read()
Now as for my original request to first read and then find the total words, different words and most common words of the book that I uploaded(it worked for .txt files for me), here are my Models, Views and html files:
Models:
from django.db import models
from string import punctuation, whitespace
from authors.models import Author
class Book(models.Model):
author = models.ForeignKey(Author, on_delete=models.CASCADE)
book_name = models.CharField(max_length=50)
genre = models.CharField(max_length=50)
files = models.FileField(upload_to='books/files/')
def __str__(self):
return self.book_name()
def total_words(self):
d = dict()
content = open(self.files.path, encoding="ISO-8859-1").read()
words = content.split()
for word in words:
word = word.strip(punctuation + whitespace)
word = word.lower()
d[word] = d.get(word, 0) + 1
return sum(d.values())
def different_words(self):
d = dict()
content = open(self.files.path, encoding="ISO-8859-1").read()
words = content.split()
for word in words:
word = word.strip(punctuation + whitespace + '“”')
word = word.lower()
d[word] = d.get(word, 0) + 1
return len(d)
def most_common_words(self, num=10):
d = dict()
content = open(self.files.path, encoding="ISO-8859-1").read()
words = content.split()
for word in words:
word = word.strip(punctuation + whitespace + '“”')
word = word.lower()
d[word] = d.get(word, 0) + 1
t = []
for word, freq in d.items():
t.append((freq, word))
t.sort(reverse=True)
return t[:num]
Views:
def detail(request, pk):
book = get_object_or_404(Book, pk=pk)
instance = Book.objects.get(pk=pk)
instance.total_words()
instance.different_words()
instance.most_common_words()
return render(request, 'books/detail.html', context={'book': book, 'instance': instance})
detail.html :
{% extends 'base.html' %}
{% block title %} {{ book.book_name }} {% endblock %}
{% block content %}
<p>Book title: {{ book.book_name }}</p>
<p>Genre: {{ book.genre }}</p>
<p>Author:
<a href="{% url 'authors:detail' book.author.pk %}">{{ book.author.full_name }}</a>
</p>
<p><b>Total words in book:</b></p>
<p>{{ instance.total_words }}</p>
<p><b>Different words in book:</b></p>
<p>{{ instance.different_words }}</p>
<p><b>Most common words in book:</b></p>
<p>{{ instance.most_common_words }}</p>
<p><button type="button"><a href="{{ book.files.url }}" target="_blank">Shkarko</a></button></p>
{% endblock %}
Thank you to the people that tried helping me on this question!
Upvotes: 1
Reputation: 1001
Am Assuming if your file is a PDF you can write your code in this manner to allow readability. reading a fileis pretty simple and you can work around it with this example !
Django view function returns the FileResponse.
You need to import it from django.http before using.
Open file in the ‘rb’ mode using Python open() method.
You have to provide the complete or relative path to your PDF file.
FileResponse content-type should be ‘application/pdf’.
Make sure, you have a PDF file present in your project static directory.
It is not good practice to hardcode the file path. File path of the static files can vary while deploying production build.
from django.http import FileResponse
import os
def show_file(request):
filepath = os.path.join('static', 'sample.pdf')
return FileResponse(open(filepath, 'rb'), content_type='application/pdf')
As you can also write your view as a classview to allow users read the book from your detail view
class DisplayPdfView(BaseDetailView):
def get(self, request, *args, **kwargs):
objkey = self.kwargs.get('pk', None) #1
pdf = get_object_or_404(Pdf, pk=objkey) #2
fname = pdf.filename() #3
path = os.path.join(settings.MEDIA_ROOT, 'docs\\' + fname)#4
response = FileResponse(open(path, 'rb'), content_type="application/pdf")
response["Content-Disposition"] = "filename={}".format(fname)
return response
Upvotes: 0