how do I make a query of a user's uploaded files - django

I'm a django newbie trying to finish a upload/download app. I am Using django-registration-redux for user reg/auth and have the following simple model. I've read the docs but haven't been able figure out how to query on a User's related fields namely, fields of a model with foreignkey to User.
here's my model:
from django.contrib.auth.models import User
FileUploads(models.Model):
owner = models.ForeignKey(User)
docfile = models.FileField(nul=True)
docfileuuid = models.UUID()
My question being: Having a specific username, How can I query the list of his/her docfiles?
What I want to accomplish is when the user logs in and navigates through a view let's call it 'localhost:/yourfiles', s/he can be provided a list of his files.
In case of having no owner with foreign key to user, I used the following code to retreive the path to the all uploaded files:
obj = FileUploads.objects.all
uploads = [i.docfile for i in]
Now instead of all the docfiles, I want the ones that belong to the logged-in user.
I read the docs and tried things like:
obj = User.objects.all()
obj.fileuploads_set.all()
But no luck

When a user logs in your application, you do have user object in request.user
In your views.py,
def file_list_view(request):
# This gives you list of file objects.
files = FileUploads.objects.filter(owner=request.user)
return render_to_response('my_template.html', {'files': files})
In your template file
<ul>
{% for file in files %}
<li>{{ file.file_name }}</li>
{% endfor %}
</ul>
Hope this helps.

To get all files belong to a user by querying the username, do:
FileUploads.objects.filter(owner__usename='amir')
In your views.py, you would do:
uploads = FileUploads.objects.filter(owner=request.user)

You can create a simple function view with a context dictionary. Filter the files in your model by the current user logged in which you can get by request.user. And then in your template use a for loop to print all file urls that user has, and by using the {% empty %} template tag to show a message whenever a user doesn't have any files uploaded.
views.py
#login_required
def userfiles(request):
context_dict = {}
files = FileUploads.objects.filter(owner=request.user)
context_dict['files'] = files
return render(request, 'users_files.html', context_dict, )
the template:
{% for file in files %}
file.docfile.url
{% empty %}
You don't have any files uploaded yet.
{% endfor %}

Related

Display query set object in django template

I have a model Post that I'm trying to display all the posts onto a template. I'm including the post.html onto the home.html....
I found a similar problem to my question but the objects still are not getting displayed link
I firt tried the to use python manage.py shell to create an object. So first I did this.
Post.objects.all()
<QuerySet [<Post: test>, <Post: admin>]>
then I tried to create a new posts.
Post.objects.create(user="test", content="New comment")
but got this error:
ValueError: Cannot assign "'test'": "Post.user" must be a "User" instance.
Tried to troubleshoot and couldn't resolve it. So I just decided to write the code in the posts/views.py and it didn't work as well. I figure this is the root of my problem why the objects aren't showing up in the templates.
This is my posts/posts.views
def posts_list(request):
# if request.user.is_authenticated():
queryset = Post.objects.all()
context = {
"object_list": queryset,
"user": "username"
}
return render(request, "posts.html", context)
This is my templates/post.html
<!DOCTYPE html>
<html lang="en">
<body>
<h1>What's on your mind, {{ user }}</h1>
{ % for obj in object_list %}
{{obj.user}}<br/>
{{obj.content}}<br/>
{{obj.timestamp}}<br/>
{% endfor %}
</body>
</html>
You have asked two questions here. I'll answer both of them below:
Displaying your posts
First, you need to make sure that you are passing a user object to your template. Assuming that user info is stored in request.user, you can do so as follows:
views.py:
def posts_list(request):
if request.user.is_authenticated:
user = request.user
queryset = Post.objects.all()
context = {
"object_list": queryset,
"user": user
}
return render(request, "home.html", context)
home.html:
<html>
<h1>Homepage</h1>
{% if user.is_authenticated %}
<h1>What's on your mind, {{ user }}</h1>
{ % for obj in object_list %}
{{obj.user}}<br/>
{{obj.content}}<br/>
{{obj.timestamp}}<br/>
{% endfor %}
Logout
{% endif %}
</html>
Adding a post for a user
You need to get a user object to pass to your creation method, rather than using the string "test". The reason your attempt is failing is because you are passing the function a string ("test") where it is expecting a user object.
This line gets a user (arbitrarily grabs the first one in your list):
u = User.objects.all()[0]
This line imports the datetime module, which you'll need to generate date and datetime objects for your create method:
import datetime
And this line creates a post for that user:
Post.objects.create(user=u, content="New comment", publish=datetime.date.today(), updated=datetime.datetime.now(), timestamp=datetime.datetime.now())
Normally in request, django automatically add requested user. If that user has related permission to add new Post then following code should work
Post.objects.create(user=request.user, content="New comment")
When you are creating a foreign key, you are referring a model.
suppose there are two models A and B. B has following fields - x, y, z. Now, x field is a foreign key, which is referring model A.
Now whenever you want to create an object of B, then the value of x field should be an object of A. Little bit like this -
post1 = Post(user = an object of User Model, content = "your value")
so create an object of User first. Then write it there. otherwise it will give error.

Add filename to formset for display purpose only

I have a model which contains a number of user uploaded files that other than the file itself also contain a description and some other meta information.
class ArchiveFile(models.Model):
archive_file = models.FileField(upload_to=grab_archive_folder, default=None, blank=False)
description = models.CharField(max_length=255)
What I want is for a user to (1) upload new files. And (2) be able to edit the descriptions of all files associated with the user, including the recently uploaded. The uploading of new files is done via AJAX / JQuery and new forms (as part of a formset) are generated dynamically.
In order to do be able to edit the descriptions in an efficient matter, it would help for a user to know of what file it is changing the description, and so I would like the filename to be displayed.
My initial solution was the following:
forms.py
class ArchiveDataForm(ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['archive_file'].widget.attrs['disabled'] = True
class Meta:
model = ArchiveFile
fields = ['archive_file','description']
views
def archive_data_update(request):
if request.method == 'GET':
ArchiveDataFormSet=modelformset_factory(ArchiveFile, form=ArchiveDataForm, extra=0)
archive_formset = ArchiveDataFormSet(queryset=ArchiveFile.objects.filter(user_id=request.user.id)
template = 'archive_data_edit.html'
template_context = {
'archive_formset': archive_formset,
...
}
return render(request, template, template_context)
if request.method == 'POST':
ArchiveDataFormSet=modelformset_factory(ArchiveFile, form=ArchiveDataForm, extra=0)
archive_formset = ArchiveDataFormSet(request.POST, queryset=ArchiveFile.objects.filter(user_id=request.user.id)
if archive_formset.is_valid():
for archive_form in archive_formset:
archive_form.save()
return HttpRespone('ok')
template
{% for archive_form in archive_formset %}
{{ archive_form.archive_file.value }}
{{ archive_form.description }}
{% endfor %}
My issue is that I am getting validation errors on the dynamically created forms, saying that no file is present. Which I suppose is correct since all I do is inject the filename to the dynamically created form via my AJAX/JQuery. Is there a way I can ignore this validation for the purpose of this form only? or is there an easier/different way to display the filenames?
Some comments:
If you only want to edit the descriptions you should not include as a form field the archive_file field.
You could instead pass in your view the instance of the form to the context of the request. And then interpolate the title of the file in the template.
If you could provide your view code, we can discuss an actual implementation.
UPDATE:
Looking at the source code of model form, you hava always available the instance of the object of the form. why don't you try using that?
As in:
# template
{% for archive_form in archive_formset %}
{{ archive_form.instance.archive_file.filename }}
{{ archive_form.description }}
{% endfor %}

Django user permission inside template

I created a custom auth permission in django via admin site, and i added that permission to a user (not a group), now i want to ask if the request user in a template has it but nothing works.It's not a duplicate, i already checked similar questions and none of this work:
{% if perms.auth.add_something %}
{% if 'auth.add_something' in request.user.get_all_permissions %}
{% if request.user.has_perm('add_something') %}
I add my view:
class NotificationSelectView(View):
template = 'myapp/notification_read.html'
def get(self, request, *args, **kwargs):
t = tree(request)
req_var_list = []
analist = notifications_list(request.user)
level = LevelProcess.objects.get(
level_hierarchical = 3
)
subprocess= Process.objects.filter(level = level)
user = request.user
t.update({
'subprocess': subprocess,
'analist':analist,
})
return render(request, self.template, t)
The idea it's to make it inside template, not to use more code in views.
Any ideas ?, thanks in advance.
django in template it uses the variable perms for the permissions of the logged in user so you can use inside template
{% if perms.auth.add_something %}
{{do_smth}}
{% endif %}
from the django documentation there is a section Authentication data in templates which describes also permissions in templates

How to use models associated with a user in Django when rendering an HTML page

I'm in the learning stages of django. I just dived into a project to learn the framework and am having a series of questions throughout the process.
I basically want to have individual pages for users who create a task list and have them post tasks to their own page.
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class UserProfile(models.Model):
# This line is required. Links UserProfile to a User model instance.
user = models.OneToOneField(User)
# The additional attributes we wish to include.
website = models.URLField(blank = True)
# Override the __unicode__() method to return out something meaningful!
def __unicode__(self):
return self.user.username
class TaskItem(models.Model):
taskn = models.CharField(max_length = 400)
usern = models.ForeignKey(User)
In my template, if the user has their task entered, how do I call it to render onto the page?
My View:
def profile_page(request, username):
user = User.objects.get(username=username)
taskitems = user.taskn_set.all()
return render_to_response('profile.html', {}, context)
Current issue:
'User' object has no attribute 'taskn_set'
{{ request.user.taskitem_set.all }} would give you all the related task items. Now, to display it in your template:
{% for task_item in user.taskitem_set.all %}
{{ task_item.task_n }}
{% endfor %}
would display the list of tasks.
Here is the documentation on reverse-queries on foreign key (related_name) Also, read this
you would do something like this:
{% for task in user.taskitem_set.all %}
{{ task.task_n }}
{% endfor %}
This will fetch all TaskItem instances related to your user. (notice the extra database query)
While i don't know how your view works, i will assume that you are making the right checks to make sure that every user can only see his own tasks.
One performance trick you will find most useful is to use prefetch_related('taskitem_set'), this will prefetch the TaskItem instances as long as your UserProfile instance with one query:
user = User.objects.filter(id=user_id).prefetch_related('taskitem_set')
You can tune the code to match your preferences.
Hope this helps!

Django display hyperlink only to the creator of the object

I'm working on an project that let users create blogs and allow other users to comment on each other blogs.When a user creates a blog , their are certain ability that the blog owner can do such as deleting their own comments and the way I'm deleting comments is via hyperlink passing value id .
Everyone can see each other blogs but I want to only show the deletion hyperlink to the owner of the blog , so only the user who created the blog. How can I do this? via template
My models
class Blog(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=100)
created = models.DateTimeField(auto_now_add=True)
description = models.TextField()
def Bloglook(request ,animal_id):
Blog = Blog.objects.get(pk=animal_id)
return render(request,'blog.html',{blog':blog})
my blog.html
{% if blog %}
{{blog.name%}}
{% endif %}
How Can I only show this link to the person who created the blog?
Delete blog
Use RequestContext to pass to template which passes request.user variable to template, which you can use to check for owner of blog.
Change your view to use RequestContext as
def Bloglook(request ,animal_id):
Blog = Blog.objects.get(pk=animal_id)
return render_to_response('blog.html',{blog':blog},
context_instance = RequestContext(request))
Then in template do
{% if blog.owner == request.user %}
Delete blog
{%endif%}
{% if request.user==blog.user %} Delete blog{% endif %}
Edited:
This will also be hidden from unautenticated users. Only if user is the owner then he will see the deletion link
Also, you can continue using render, there is no need to change to render_to_response.