Django template renders all my files at once - python

I am stuck with this issues for a while now. It goes like this: I have a model with lectures. I want that for every lecture to be able to upload multiple files, so I created a model that has FileField. So in my template, I want that for every lecture, the files would be displayed and downloadable as well. The Issue is that every lecture displays all the files that have ever been uploaded in the admin panel. Here is my code:
class Lecture(models.Model):
course = models.ForeignKey('Course', on_delete=models.CASCADE, default='', related_name='lectures')
lecture_category = models.IntegerField(choices=((0, "Classes "),
(1, "Seminars"),
), default=0)
lecture_title = models.CharField(max_length=100)
content = models.TextField()
files = models.OneToOneField('FileUpload', on_delete=models.CASCADE, null=True, blank=True, )
def __str__(self):
return str(self.lecture_category)
class FileUpload(models.Model):
files = models.FileField(upload_to='documents', null=True, blank=True)
def __str__(self):
return str(self.files)
def file_link(self):
if self.files:
return "<a href='%s'>download</a>" % (self.files.url,)
else:
return "No attachment"
file_link.allow_tags = True
file_link.short_description = 'File Download'
<ul>
{% regroup lectures by get_lecture_category_display as category_list %}
<h3>Lectures</h3>
<ul>
{% for category in category_list %}
<strong>
<li>{{ category.grouper }}</li>
</strong>
<ul>
{% for c in category.list %}
.............
<li>{{ c.lecture_title }}</li>
<li>{{ c.content }}</li>
{% for file in files %}
{% if file.files %}
<li><a href='{{ MEDIA_URL }}{{ file.files.url }}'>download</a></li>
{% endif %}
{% endfor %}
{% endfor %}
</ul>
{% endfor %}
</ul>
</ul>
def courses(request, slug):
query = Course.objects.get(slug=slug)
context = {'courses': Course.objects.filter(slug=slug),
'lectures': query.lectures.order_by('lecture_category'),
'files': FileUpload.objects.all(),
}
return render(request, 'courses/courses.html', context)
Here is the current output: https://i.imgur.com/Hu2NcHJ.png

Stop fetching the files as a separate queryset:
def courses(request, slug):
query = Course.objects.get(slug=slug)
context = {'courses': Course.objects.filter(slug=slug),
'lectures': query.lectures.order_by('lecture_category'),
}
return render(request, 'courses/courses.html', context)
You can then follow the one-to-one field from lecture to files.
{% for lecture in category.list %}
<li>{{ lecture.lecture_title }}</li>
<li>{{ lecture.content }}</li>
{% if lecture.files %}
<li><a href='{{ MEDIA_URL }}{{ lecture.files.files.url }}'>download</a></li>
{% endif %}
{% endfor %}
Since it's a one-to-one field to a single file upload, it would make more sense to name the field file instead of files:
file = models.OneToOneField('FileUpload', on_delete=models.CASCADE, null=True, blank=True)
You would then have to update the template to use lecture.file instead.

Related

The 'Thumbnail' attribute has no file associated with it. Django {% if %} {% else%} {% endif %}

The 'Thumbnail' attribute has no file associated with it.
I have tried Django {% if %} {% else %} {% endif %} in my HTML list and it works on the page, but when I do the same for a detailview HTML it doesn't work and returns "The 'Thumbnail' attribute has no file associated with it."
** Models.py **
class Article(models.Model):
Title = models.CharField(max_length=150)
Thumbnail = models.ImageField(blank=True, null=True)
Author = models.ForeignKey(Author, on_delete=models.CASCADE)
Content = QuillField()
Date = models.DateField(auto_now_add=True)
slug = AutoSlugField(populate_from='Title')
** Views.py**
class ArticlesDetailView(DetailView):
model = Article
template_name = 'articles_app/articles_detail.html'
def get_context_data(self, **kwargs):
latest = Article.objects.order_by('-id')[0:3]
context = super().get_context_data(**kwargs)
context['latest'] = latest
return context
** HTML - List (articles_list.html) ** It works perfectly fine here!!!
<img src=" {% if articles.Thumbnail %}
{{ articles.Thumbnail.url }}
{% else %}
{% static 'img/add-ons/article_thumbnail_default.jpg' %}
{% endif %} " alt="..." class="card-img-top">
** HTML - Detail (articles_detail.html) ** It doesn't work here.
{% for obj in latest %}
<img src="{% if obj.Thumbnail %}
{{ obj.Thumbnail.url }}
{% else %}
{% static 'img/add-ons/article_thumbnail_default.jpg' %}
{% endif %} " alt="..." class="card-img-top">
{% endfor %}
What am I doing wrong? Please help!
try object.Thumbnail instead of obj.Thumbnail, I think that will solve your problem.

how to add comments to an article in django(Python)?

I'm new to Django, I repeat after the tutorial, but I just can not display comments even from the database in html.
urls.py
static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
settings
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
models.py
from django.db import models
class Post(models.Model):
photo = models.ImageField(upload_to='media/photos/',null=True, blank=True)
name_barber = models.CharField(max_length=30)
description = models.TextField(blank=True, null=True)
def __str__(self):
return self.description[:10]
class Comment(models.Model):
post = models.ForeignKey(Post, related_name='comments', on_delete=models.CASCADE)
name = models.CharField(max_length=255)
body = models.TextField()
date_add = models.DateTimeField(auto_now_add=True)
def __str__(self):
return '%s - %s' % (self.post, self.name)
html file
} </style>
{% for post in posts %}
<img src="{{MEDIA_URL}}{{post.photo.url}}" width="800" />
<h3>{{ post.name_barber}}</h3>
<p>{{ post.description}}</p>
{% endfor %}
<h3> Comments.. </h3>
{% if not post.comments.all %}
no comments yet...Add one
{% else %}
{% for comment in post.comments.all %}
<strong>
{{ comment.name }}
{{ comment.date_add }}
</strong>
{{comment.body }}
{% endfor %}
{% endif %}
after adding a comment through the admin panel, the page displays: no comments yet..
What is the problem please tell me??
Remove the if/else condition and use the {% empty %} tag with your forloop.
{% for comment in post.comments.all %}
<strong>
{{ comment.name }}
{{ comment.date_add }}
</strong>
{{comment.body }}
{% empty %}
no comments yet...Add one
{% endfor %}

How can I get the user profile detail to work properly in django

I am trying to include a profile feature in a simple blog site. I have created a profile model using the one to one link for the user field, also created a function view for the profile detail with corresponding template name but i keep getting a 404 error.
user = models.OneToOneField(User, on_delete=models.SET_NULL, null=True)
username = models.CharField(max_length=15, default='Anonymous')
dp = models.ImageField(null=True)
country = models.CharField(max_length=20, null=True)
age = models.IntegerField(null=True)
joined = models.DateTimeField( auto_now_add=True)
class Meta:
ordering = ['joined']
def __str__(self):
return self.username
def get_absolute_url(self):
return reverse('profile_detail', args=[str(self.id)])
#receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.profile.save()```
views.py
def profile_detail(request, pk):
user = get_object_or_404(User, pk=pk)
context = {'user': user}
return render(request, 'milk/profile_detail.html', context)
profile_detail.html
{% extends 'milk/base.html' %}
{% block title %}
{% endblock %}
{% block content %}
<h2>{{ user.get_full_name }}</h2>
<ul>
<li>Username: {{ user.username }}</li>
<li>Location: {{ user.profile.country }}</li>
<li>Age: {{ user.profile.age }}</li>
</ul>
{% endblock %}
template referencing
<em>{{user.get_username }}</em>
urls.py
path('profile/<int:pk>/', views.profile_detail, name='profile_detail'),
you can display current user info like this without passing through context
{% extends 'milk/base.html' %}
{% block title %}
{% endblock %}
{% block content %}
<h2>{{ request.user.profile.get_full_name }}</h2>
<ul>
<li>Username: {{ request.user }}</li>
<li>Location: {{ request.user.profile.profile.country }}</li>
<li>Age: {{ request.user.profile.profile.age }}</li>
</ul>
{% endblock %}
or
instead of 'get_object_or_404' try
user = User.objects.get(id=pk)

how to categorize sql inputs according to models in django

I want to learn django and I should categorize my sql inputs according to my models.
For example I have some models like this:
class Author(models.Model):
authorName = models.CharField(max_length=30)
def __str__(self):
return self.authorName
class Book(models.Model):
author = models.ForeignKey(Authors, on_delete=models.CASCADE)
bookName = models.CharField(max_length=60)
downloadLink = models.FileField()
downloadCount = models.IntegerField(default=0)
def __str__(self):
return self.bookName
and I want to an output in my .html file like this;
Sherlock Holmes
A Study in Scarlet
The Sign of the Four
The Hound of the Baskervilles
Suzanne Collins
The Hunger Games
Catching Fire
Mockingjay
I tried this code in my html file but it doesn't work
<ul>
{% for author in all_authors %}
<h2>{{ author.authorName }}</h2>
{% for book in all_books %}
{% if book.author == author.authorName %}
<li>{{ book.bookName }}</li>
{% endif %}
{% endfor %}
{% endfor %}
</ul>
My output is;
Sherlock Holmes
Suzanne Collins
Here is my view.py file;
def books(request):
return render(request,'../templates/library/library-template.html', {
'all_authors': Author.objects.all(),
'all_books': Book.objects.all(),
})
How can I fix it? Or are there any different solution for fix this?
Thank you.. :)
Your if statement will never be true, you are comparing an object and a string
{% if book.author == author.authorName %}
So you could change this to
{% if book.author == author %}
But this is still wasteful, you can just use the reverse lookup so you won't need the if statement at all
<ul>
{% for author in all_authors %}
<h2>{{ author.authorName }}</h2>
{% for book in author.book_set.all %}
<li>{{ book.bookName }}</li>
{% endfor %}
{% endfor %}
</ul>

Django Querying Self-referential Many-To-Many relations

I am trying to get a list of all manuscripts in my db, print out the shelfmarks for each of them and in case that they are linked to other manuscripts also print out the shelfmarks of those manuscripts.
Here is what my models look like:
class MSS(models.Model):
shelfmark = models.CharField(max_length=50)
MSSLink = models.ManyToManyField('self',through='MSSLink',symmetrical=False)
[...]
class MSSLink(models.Model):
link1 = models.ForeignKey('MSS', related_name='First_MSS')
link2 = models.ForeignKey('MSS', related_name='Second_MSS')
[...]
Here is the code in views.py
def show_all_MSS(request):
all_MSS = MSS.objects.select_related().all() # get all MSS
t = loader.get_template('list.html')
c = Context({'all_MSS': all_MSS, })
return HttpResponse(t.render(c))
The question is then what to do in my template. I thought about doing something like this, but I don't know how I can test whether the current MS in the for-loop has been linked to another MS and if so how to display those shelfmarks:
{% if all_MSS %}
<ul>
{% for i in all_MSS %}
<li>{{ i.shelfmark }}</li>
{% if i.MSSLink %}
<p>This MS is linked to the following MSS: {{ i.MSSLink.link1 }}</p>
{% endif %}
{% endfor %}
</ul>
{% else %}
<p>No MSS found</p>
{% endif %}
Your models are a bit complicated - you can probably get rid of MSSLink:
class MSS(models.Model):
shelfmark = models.CharField(max_length=50)
links = models.ManyToManyField('self', symmetrical=False, blank=True)
def __unicode__(self):
return self.shelfmark
and add this to your template:
{% if i.links.all %}
<ul>
{% for l in i.links.all %}
<li>{{ l.shelfmark }}</li>
{% endfor %}
</ul>
{% endif %}

Categories