Django - Reverse a queryset - django

I have very basic view with queryset, but for some reason I cannot reverse it.
def home(request):
posts = Post.objects.all().reverse()
return render(request, "home.html", {'posts': posts})
For some reason no matter how I change code - instanses from queryset always rendering in same order.
Below there are lines of code that I already tried and which didn't worked for some reason:
Post.objects.all().reverse()
Post.objects.order_by('-date')
Post.objects.order_by('date').reverse()
home.html:
{% for post in posts %}
{{ post.title }}
{{ post.content }}
{% endfor %}
models.py:
class Post(models.Model):
title = models.CharField(max_length=100, unique=True, blank=True, null=True)
image = models.URLField(blank=True, null=True, unique=True)
content = models.TextField(blank=True, null=True)
date = models.DateField(auto_now=False, auto_now_add=True)
#To make in name, not objXXX
def __str__(self):
return self.title

I believe the queryset you're looking for is Post.objects.all().order_by("-date"):
def home(request):
posts = Post.objects.all().order_by("-date")
return render(request, "home.html", {"posts": posts})
It is considered a best practice to avoid putting ordering on a Django model, as it can force unnecessary sorting operations in the database when you don't need them. When necessary, I put default ordering on Django Admin definitions, instead of the model. Good luck!

If it is the ordering that you are looking for try (in models.py):
class Meta:
ordering = ('-date',)
If not, it does not mean much to reverse something that isn't ordered, try (in views.py):
This
post = Post.objects.filter("<filter name>").reverse()
instead of
post = Post.objects.all.order_by("<field name>").reverse()

Related

Django display multiple uploaded files

I am trying to display multiple uploaded file URLs but I'm not sure how to do it. I am a form that the users can use to upload multiple files that are working perfectly but now I want to be able to display these files. For instance, a company can have more than one file.
class InternationalCompany(models.Model):
International_company_Name = models.CharField(max_length=50)
International_company_Id = models.CharField(max_length=50)
options = (
('Yes', 'Yes'),
('No', 'No'),
)
Does_it_have_a_Financial_Dealers_License = models.CharField(max_length=20, choices=options, null=True)
Register_Office = models.TextField(max_length=500, null=True)
Beneficial_owner = models.CharField(max_length=100, null=True)
Beneficial_owner_id = models.FileField(upload_to='passport/pdf/',null=True)
expire_date = models.DateField(null=True)
BO_Phone_number = models.IntegerField(null=True)
BO_Email_Address = models.EmailField(null=True)
BO_Residential_Address = models.TextField(max_length=200, null=True)
def __str__(self):
return self.International_company_Name
class SupportDocuments(models.Model):
Supporting_Documents = models.FileField(upload_to='support_doc/pdf/', null=True)
internationalcompany = models.ForeignKey(InternationalCompany, on_delete=models.CASCADE)
def __str__(self):
return self.Supporting_Documents.url
I try something like this but it only displayed one url of the file instead of the multiple urls for the files that are associate with that company.
{%for company in doc%}
<tr>
<td></td>
<td>{{company.internationalcompany.Beneficial_owner}}</td>
<td>{{company.Supporting_Documents.url}}</td>
</tr>
{%endfor%}
I have also try out this but it doesn't display anything.
{%for company in doc.Supporting_Documents.all%}
{{company.url}}
{%endfor%}
def supporting_doc(request, company_id):
doc = SupportDocuments.objects.filter(id=company_id)
return render(request, 'supporting_doc.html', locals())
First of all, it might be better to use context rather than locals() as discussed here
Second, the way you get the doc queryset is wrong. id=company_id The id of SupportingDocuments is different from company_id. What you really need to do is internationalcompany.id=company_id.
so views.py:
def supporting_doc(request, company_id):
documents = SupportDocuments.objects.filter(internationalcompany.id=company_id)
context = { "documents": documents}
return render(request, 'supporting_doc.html', context)
in template:
{% for doc in documents %}
{{ doc.internationalcompany.Beneficial_owner}}
{{ doc.Supporting_Documents }}
{% endfor %}
On a side note, it may be better to use all lowercases in fields. This way, it is easy to distinguish fields and models.

How to create link for one of the category in Django

I'm coding a news website.I have 'category' in News model.
I want to get all the news in one of the categories named 'opinion' in my index.html. And create detail page link for each of them.
I can the title ,author, etc of the news mentioned above .But my brain really junks,I don't know how to create a link points to opinion_new.html or news_detail.htlm for each of them.I have a link for regular news to point to news_detail.htlm.
If you don't quite understand what I'm asking, please also read my last question How to get all the post in the same category in Django you so much!
here is part of my News model:
class News(models.Model):
category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name="cate", blank=True, verbose_name='分类')
here is my Category model:
class Category(models.Model):
name = models.CharField(max_length=40) # 分类名
class Meta:
verbose_name = "分类"
verbose_name_plural = verbose_name
def __str__(self):
return self.name
here is part of my view:
class NewsView(View):
def get(self, request):
opinion_news = News.objects.filter(category="opinion")
return render(request, 'index.html', {
'opinion_news': opinion_news,
})
here is part of my index.html
{% for opinion in opinion_news %}
<li class="media">
<a href='?'> <h>{{opinion.title}}</h></a>
</li>
{% endfor %}
here is part of my already works well news_detail view.
def newsDetailView(request, news_pk):
news = get_object_or_404(News, id=news_pk)
category = news.category
tags = news.tag.annotate(news_count=Count('news'))
all_comments = NewsComments.objects.filter(news=news)
news.comment_nums = all_comments.count()
news.save()
return render(request, "news_detail.html", {
'news': news,
'tags': tags,
'category': category,
})
here is my url for news_detail.html
path('-<int:news_pk>', views.newsDetailView, name="news_detail"),

How to display comments and it's replies in django templates?

I want to display comment and it's replies in the template. But there is an issue, every reply may have some other replies. The below snippet is my Comment and CommentReply model:
class Comment(models.Model):
author = models.ForeignKey(Profile, related_name="c_sender", on_delete=models.CASCADE, unique=False)
comment = models.CharField(max_length=500, unique=False)
created_date = models.DateTimeField(auto_now_add=True)
edited_date = models.DateTimeField(blank=True, null=True)
def __str__(self):
return self.comment
#property
def replys(self):
return CommentReply.objects.filter(comment_id=self)
class CommentReply(models.Model):
comment_id = models.ForeignKey(Comment, related_name='sender', on_delete=models.CASCADE)
reply_id = models.ForeignKey(Comment, related_name='reply', on_delete=models.CASCADE)
Updated:
Also I have a model for WorksComments that every comments that related to Work model saved there.
class WorkComment(models.Model):
work_id = models.ForeignKey(Work, on_delete=models.CASCADE, related_name='e_exercise', unique=False)
comment_id = models.ForeignKey(Comment, related_name='e_comment', unique=False)
The below snippet is my view:
comments = WorkComment.objects.filter(work_id=work).all()
return render(request, 'work.html', {'comments': comments})
My question is how to display comments and it's replies under it, and every reply may have some other replyies that I want to display them too.
First things first... put this in your bookmarks; https://ccbv.co.uk/
You're going to want a Detail View here I suspect in order to display the details of an instance.
Setup URLs...
from django.conf.urls import url
from work.views import WorkDetailView
urlpatterns = [
url(r'^(?P<id>[-\d]+)/$', WorkDetailView.as_view(), name='work-detail'),
]
And a view;
from django.views.generic.detail import DetailView
from django.utils import timezone
from work.models import Work
class WorkDetailView(DetailView):
model = Work
def get_context_data(self, **kwargs):
context = super(WorkDetailView, self).get_context_data(**kwargs)
context['comments'] = WorkComment.objects.filter(work_id=self.object.id).all()
return context
Then a simple view might be work/work_detail.html:
<h1>{{ object.title }}</h1>
<p>{{ object.content }}</p>
<h2>Comments</h2>
{% for comment in comments %}
{{ comment }}
{% endfor %}

View returns 404 when including a queryset despite the object being valid

I'm using the following URL pattern to pass a primary key for a model to the view class detailed below it. The primary key of the related model, "Host", is either a valid IP address or FQDN.
URL Pattern:
ValidIpAddressRegex = "(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])"
ValidHostnameRegex = "(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])"
url(r"^host/(?P<pk>({}|{}))/$".format(ValidIpAddressRegex, ValidHostnameRegex),
views.HostView.as_view(),
name="host")
View class:
class HostView(generic.DetailView):
model = Host
template_name = 'report_viewer/host.html'
context_object_name = 'related_findings'
def get_queryset(self):
"""Return all related findings"""
host = get_object_or_404(Host, name=self.kwargs["pk"])
return host.get_findings() # A function on the model to return related records from another model
Relevant template:
<ul>
{% for finding in related_findings %}
<li><strong>{{ finding.plugin_id }}</strong> {{ finding.plugin_name }}</li>
{% empty %}
<li>No findings!</li>
{% endfor %}
</ul>
Host model:
class Host(models.Model):
name = models.CharField(max_length=255, primary_key=True)
os_general = models.CharField(max_length=255, blank=True, verbose_name="Generic OS Identifier")
os_specific = models.CharField(max_length=255, blank=True, verbose_name="Reported OS Name")
ssh_fingerprint = models.CharField(max_length=255, blank=True, verbose_name="SSH Fingerprint")
mac_address = models.CharField(max_length=17, blank=True, verbose_name="MAC Address")
ip_address = models.GenericIPAddressField(blank=True, null=True, verbose_name="IP Address")
fqdn = models.CharField(max_length=255, blank=True, verbose_name="Fully Qualified Domain Name")
netbios_name = models.CharField(max_length=255, blank=True, verbose_name="NetBIOS Name")
def __str__(self):
return self.name
def get_findings(self):
findings = Finding.objects.filter(targets=self)
return findings
class Meta:
ordering = ['name']
The result of a valid URL is "No finding found matching the query", raised by views.HostView. The view below works successfully, invoking the {% empty %} condition, which suggests that I'm either constructing the get_object_or_404 request incorrectly, or perhaps the "pk" variable is being mangled and is not a valid key.
I'd appreciate any thoughts on a solution. Or indeed an alternative method to achieve the same outcome.
Turns out the solution was a great deal simpler than expected. I was attempting to use the get_queryset function with the generic DetailView, when it's meant to be used with ListView.
I rewrote the model to use the get_context_data function instead.
class HostView(generic.DetailView):
model = Host
template_name = 'report_viewer/host.html'
def get_context_data(self, **kwargs):
"""Return all related findings"""
context = super(HostView, self).get_context_data(**kwargs)
context['host'] = get_object_or_404(Host, name=self.kwargs["pk"])
context['findings'] = context['host'].get_findings()
return context
Which then allows me to access the relevant Host model and all its related Finding models in the template.

ModelForm with OneToOneField in Django

I have two models in Django that are related with a OneToOneField (PrinterProfile and PrinterAdress).
I am trying to do a form with PrinterProfileForm, but for some reason it does NOT pass the PrinterAddress fields into the form (it's not rendered by Django "magic" in the template).
What should I do so that my PrinterProfileForm include as well the fields from PrinterAddress (its related OneToOneField)?
Thanks a lot
class PrinterProfile(TimeStampedModel):
user = models.OneToOneField(User)
phone_number = models.CharField(max_length=120, null=False, blank=False)
additional_notes = models.TextField()
delivery = models.BooleanField(default=False)
pickup = models.BooleanField(default=True)
# The main address of the profile, it will be where are located all the printers.
class PrinterAddress(TimeStampedModel):
printer_profile = models.OneToOneField(PrinterProfile)
formatted_address = models.CharField(max_length=200, null=True)
latitude = models.DecimalField(max_digits=25, decimal_places=20) # NEED TO CHECK HERE THE PRECISION NEEDED.
longitude = models.DecimalField(max_digits=25, decimal_places=20) # NEED TO CHECK HERE THE PRECISION NEEDED.
point = models.PointField(srid=4326)
def __unicode__(self, ):
return self.user.username
class PrinterProfileForm(forms.ModelForm):
class Meta:
model = PrinterProfile
exclude = ['user']
You have to create second form for PrinterAddress and handle both forms in you view:
if all((profile_form.is_valid(), address_form.is_valid())):
profile = profile_form.save()
address = address_form.save(commit=False)
address.printer_profile = profile
address.save()
Of course in the template you need to show both forms under one <form> tag :-)
<form action="" method="post">
{% csrf_token %}
{{ profile_form }}
{{ address_form }}
</form>
Complementing the accepted answer:
If you have custom clean methods, you need to add a try/except case. For the example presented if address had a clean() method to validate something you needed to change it to:
def clean(self):
try:
printer_profile = self.printer_profile
except ObjectDoesNotExist:
pass
else:
...code to validate address...