I'm a newcomer to django and I'm trying to create a user system where different users can log in and upload and view their documents. The upload and viewing works except users are able to see each others documents as well. How can I make it so that users are only able to see documents uploaded by them?
The following question also talk about the same problem but I'm unable to understand how the issue was fixed: How to show user posted blog in user profile page as a my post list section in Django 3?
I realize I've to use foreign keys in my models but I'm not sure how to implement it. Here's snippets of my code so far:
Document Model for upload with user foreign key
class Document(models.Model):
user = models.ForeignKey(User, default = 1, null = True, on_delete = models.SET_NULL)
docfile = models.FileField(upload_to='documents/%Y/%m/%d')
User model
class User(models.Model):
name = models.CharField(max_length=255)
author = models.ForeignKey(User, default = 1, null = True, on_delete = models.SET_NULL)
id = models.IntegerField(primary_key=True)
email = models.EmailField(max_length=500, unique=True)
username = models.CharField(max_length=255, unique=True)
password = models.CharField(max_length=255)
document function in views.py
def my_view(request):
print(f"Great! You're using Python 3.6 . If you fail here, use the right version.")
message = 'Upload as many files as you want!'
# Handle file upload
if request.method == 'POST':
form = DocumentForm(request.POST, request.FILES)
if form.is_valid():
newdoc = Document(docfile=request.FILES['docfile'])
newdoc.user = request.user;
newdoc.save()
# Redirect to the document list after POST
return redirect('my-view')
else:
message = 'The form is not valid. Fix the following error:'
else:
form = DocumentForm() # An empty, unbound form
# Load documents for the list page
documents = Document.objects.all()
# Render list page with the documents and the form
context = {'documents': documents, 'form': form, 'message': message}
return render(request, 'list.html', context)
html code for the documents. I know for certain that this code is meant to show all documents in the database and does nothing to filter out the documents but all my tries to change that lead to errors so this is the only working version.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Minimal Django File Upload Example</title>
</head>
<body>
<!-- List of uploaded documents -->
{% if documents %}
All documents in the database:
<ul>
{% for document in documents %}
<li><a href="{{ document.docfile.url }}">{{ document.docfile.name }}</a></li>
{% endfor %}
</ul>
{% else %}
<p>No documents.</p>
{% endif %}
<!-- Upload form. Note enctype attribute! -->
<form action="{% url "my-view" %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ message }}
<p>{{ form.non_field_errors }}</p>
<p>{{ form.docfile.label_tag }} {{ form.docfile.help_text }}</p>
<p>
{{ form.docfile.errors }}
{{ form.docfile }}
</p>
<p><input type="submit" value="Upload"/></p>
</form>
<div>To go back home, <a href="{% url 'authApp:home' %}">Click Here</a></div>
</body>
</html>
CodePudding user response:
Simply add an condition inside your loop:
{% for document in documents %}
{% if document.user == request.user %}
<li><a href="{{ document.docfile.url }}">{{ document.docfile.name }}</a></li>
{% endif %}
{% endfor %}
With this every User
can see only Document
objects, that are set to him in ForeignKey
field user
.
CodePudding user response:
If you want to display to user only documents created by request user, you can filter your Document queryset by user ForeignKey:
# Load documents for the list page
documents = Document.objects.filter(user=request.user)
# Render list page with the documents and the form
context = {'documents': documents, 'form': form, 'message': message}
return render(request, 'list.html', context)
This way, you are excluding non user documents on DB level, which is much faster than iterating over every single document and checking if user is matching to request user