When I display a blog post in HTML using a for loop
{% for post in posts %}
<div class="blogpost">
<h3><strong>{{post.title}}</strong></h3>
<img class="thumbnail" src="{{author.imageURL}}">
<h7>{{post.date}} - {{post.author}}</h7>
<br>
<hr>
<br>
{{post.context|linebreaks}}<br><br>
</div>
<br>
{% endfor %}
it works perfectly fine, except the authors profile picture does NOT get displayed.
I get the posts by getting all posts in my views.py from my models.py. The thing is that the profile picture of the user posting the blog isn't stored in the "post" model in the database. It is stored in the "Customers". Everybody should be able to read and post blogs. The admin (me) can later delete unwanted posts.
I have tried making a for loop using an array key:value in JavaScript. That is not very secure, because everybody just gets all users and all profilepictures through the whole database. That might not be a good idea.
This is my models.py
class Customer(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, null=True, blank = True)
name = models.CharField(max_length=200, null=True)
email = models.EmailField(max_length=200, null=True)
about = models.CharField(max_length=100, null=True)
image = models.ImageField(null=True, blank=True)
#property
def imageURL(self):
try:
url = self.image.url
except:
url = 'placeholder.png'
return url
def __str__(self):
return self.name
class Post(models.Model):
title = models.CharField(max_length=200, null=True)
context = models.TextField(max_length=250, blank=True,
validators=[MaxLengthValidator(250)])
author = models.CharField(max_length=200, null=True)
from datetime import date
date = models.DateField(("Date"), default=date.today)
views.py
def homepage(request):
if request.user.is_authenticated: # Everybody has to be logged in
posts = Post.objects.all()
authors = Customer.objects.filter()
context = {'posts':posts, 'authors':authors}
return render(request, 'store/homepage.html', context)
That means that I want the user to see the persons profile picture in the corner of the blog post.
First I think you need to link the author in the Post model to a Customer with a foreignkey:
Then you can acces author fields like
{{ post.author.xyz }}
Currently your context contains authors as a queryset:
authors = Customer.objects.filter()
context = {'posts':posts, 'authors':authors}
But in your template you use it as if it were a single Customer:
<img class="thumbnail" src="{{author.imageURL}}">
And be aware of the typo "author" and "authors"
It is unclear what you meant by {{author.imageURL}} as author is QuerySet( that results in collection of authors).
You probably meant the related author to post which would be post.author
Other than that you should pass image URL to template and not ImageField string representation as documented
So it should be something in a line of
{{ post.author.imageURL.url }}
I am trying to use Django's default permissions to only show the link to the blog post page if they have the blog post permissions.
The wonderful Django documentation provides the following:
Assuming you have an application with an app_label foo and a model named Bar,
to test for basic permissions you should use:
add: user.has_perm('foo.add_bar')
change: user.has_perm('foo.change_bar')
delete: user.has_perm('foo.delete_bar')
view: user.has_perm('foo.view_bar')
My app is named about
Here is my model:
# models.py
class BlogPost(models.Model):
title = models.CharField(max_length=120)
description = models.TextField(max_length=250, null=True)
image = models.ImageField(upload_to='blog/main')
content = HTMLField()
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
draft = models.BooleanField(default=False)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("post-detail", kwargs={"pk": self.id})
Here is my HTML where I am trying to filter
# base.html
{% if user.has_perm('about.add_blogPost') %}
<li {% if url_name == 'post' %}class="nav-item active"{% else %}class="nav-item"{% endif %}>Add Post</li>
{% endif %}
Whenever I follow it just as the documentation has written, I get:
Could not parse the remainder: '('about.add_blogPost')' from 'user.has_perm('about.add_blogPost')'
What am I doing wrong?
try
{% if user.has_perm 'about.add_blogPost' %}
I'm using django2 and I get an error when I access this url:
http://127.0.0.1:8000/hotes/12/access/7/update
I get an error 404 "None access object was found"
To make a long story short:
I want to update an object linked to another. To do so, I have to send through the link, both primary keys (12 and 7 in the url). Also, I use the generic view "UpdateView" given by Django.
This is the path concerned in my project.urls:
urlpatterns = [
path('hotes/<int:pk>/access/<int:access_pk>/update/',views.AccessUpdateView.as_view(), name='access_update'),
path('hotes/add',views.host_add, name='host_add'),
path('hotes/<int:pk>/', include([
path('edit',views.HostUpdateView.as_view(), name='host_update'),
path('delete',views.host_delete, name='host_delete'),
])),
path('hotes/<int:pk>/add/', include([
path('access',views.access_add, name='access_add'),
path('oncall',views.onCall_add, name='onCall_add'),
path('network',views.network_add, name='network_add'),
])),
path('hotes/<int:pk>/',views.host_view, name='host_view'),
path('hotes/',views.hosts_view, name='hosts_view'),
path('', views.home, name='home'),
path('admin/', admin.site.urls),
]
I want the second primary key to be used in my view "AccessUpdateView".
This is a part of my models.py:
class Host(models.Model):
name = models.CharField(max_length=30, unique=True)
usage = models.CharField(max_length=30, blank=True)
function = models.CharField(max_length=30, blank=True)
production = models.NullBooleanField(blank=True, null=True)
place = models.CharField(max_length=30, blank=True)
type = models.CharField(max_length=30, blank=True)
processor = models.DecimalField(max_digits=3, decimal_places=2, null=True, blank=True)
storage = models.CharField(max_length=10, blank=True)
memory = models.CharField(max_length=10, blank=True)
dns_inner = models.CharField(max_length=50, blank=True)
dns_extern = models.CharField(max_length=50, blank=True)
os = models.ForeignKey(Os, null=True, related_name='hosts', on_delete=models.SET_NULL, blank=True)
class Access(models.Model):
service = models.CharField(max_length=20)
client_access = models.NullBooleanField(blank=True, null=True)
ip = models.GenericIPAddressField()
login = models.CharField(max_length=30, blank=True)
password = models.CharField(max_length=50, blank=True)
host = models.ForeignKey(Host, related_name='access', on_delete=models.CASCADE)
As you can see on host can have multiple access but an access in linked to only one host.
This is the view concerned:
class AccessUpdateView(UpdateView):
model = Access
fields = ('service','client_access','ip','login','password', )
template_name = 'access_update.html'
pk_url_kwarg = 'access_pk'
context_object_name = 'access'
def form_valid(self, form):
access = form.save(commit=False)
host_id = self.kwargs['pk']
access.host_id = host_id
access.save()
return redirect('host_view', pk=host_id)
EDIT: new error when I try to access the url:
NoReverseMatch at /hotes/12/access/7/update/
Reverse for 'host_view' with arguments '('',)' not found. 1 pattern(s) tried: ['hotes\/(?P[0-9]+)\/$']
EDIT:
The error was coming from "access_update.html"
I removed the href in the Hote link which contained {% url host.pk %}
{% extends 'base.html' %}
{% load widget_tweaks %}
{% block title %}Modifier Acces{% endblock %}
{% block breadcrumb %}
<li class="breadcrumb-item">Hotes</li>
<li class="breadcrumb-item">Hote</li>
<li class="breadcrumb-item active">Modification Acces</li>
{% endblock %}
{% block contenu %}
<form method="post" novalidate>
{% csrf_token %}
{% include 'includes/form.html' %}
<button type="submit" class="btn btn-success">Modifier</button>
</form>
{% endblock %}
The question is what is the right way to write the pk of the host in the url?
(host_id doesn't work)
If you want to use access_pk, then you should set pk_url_kwarg = 'access_pk' in the view.
In your form_valid method, you are using host without defining it. If pk from the URL is the host id, then you can access it with self.kwargs['pk'].
def form_valid(self, form):
access = form.save(commit=False)
host_id = self.kwargs['pk']
access.host_id = host_id
access.save()
return redirect('host_view', pk=host_id)
Inside the template for the AccessUpdateView, you have access to access since that is the object that is being updated. If you want to use the host or its id, you should access it via access.
{% url 'host_view' access.host_id %}
I have the following problem: A project can have multiple Roles, How do I show the roles field in a template? project.role shows blank and the problem is even after using _set.all in the template, I still do not get the contents from the database to show.
Model.py
class Project(models.Model):
"""
Information for each Project
"""
project_name = models.CharField(max_length=255, blank=True, null=True, unique=True)
project_description = models.TextField(null=True, blank=True)
project_url = models.URLField(max_length=200, null=True, blank=True)
#For Admin Purposes and filtering, to keep track of new and old in the database by administrative users
date_added = models.DateTimeField(auto_now_add=True, null=True, blank=True, verbose_name=_('Date added'))
last_modified = models.DateTimeField(auto_now=True, null=True, blank=True, verbose_name=_('Last modified'))
class Role(models.Model):
"""
Information for Role
"""
role = models.CharField(max_length=255, blank=True, null=True)
project_role = models.ManyToManyField(Project)
View.py
class ProjectView(ListView):
template_name = '_projects.html'
model = Project
def get_context_data(self, **kwargs):
context = super(ProjectView, self).get_context_data(**kwargs)
context['projects'] = Project.objects.all()
return context
Template
{% for project_info in projects %}
{{project_info.project_name}}
</br>
{{project_info.project_description}}
</br>
{{project_info.project_url}}
</br>
{% for rolling in project_info.project_role_set.all %}
{{rolling}}
{% endfor %}
{% endfor %}
Try this:
{% for rolling in project_info.role_set.all %}
{{rolling}}
{% endfor %}
I am new to Django. I want to display latest data entered from models to the website.
models.py
class Service(models.Model):
service_name = models.CharField(max_length=200)
service_code = models.IntegerField(default=0, unique=True)
views.py
def Latest(return):
latest_services = Service.objects.order_by('service_name')
index.html
{{ service_name }}
Latest Services Goes here
When I run the code nothing is displayed!
You need to iterate over the queryset:
<ul>
{% for service in latest_services %}
<li>{{ service.service_name }}</li>
{% endfor %}
</ul>
Anyway, if you want to display the latest entries, you should add a new field to your model with the date. For example:
class Service(models.Model):
created_on = models.DateTimeField(auto_now=True)
service_name = models.CharField(max_length=200)
service_code = models.IntegerField(default=0, unique=True)
And then in your query:
latest_services = Service.objects.order_by('created_on')