Django reverse foreign key relation doesn't work - python

Hello i am struggling already since 2 days to get a reverse relation going.
I am trying to get pictures of "bilder" into related "doku".
The site returns the {{doku.name}} but nothing from the loop from the related model "bilder"
I tried almost everything i have found on the internet, but maybe I just have overseen something?
here is my models.py:
class Doku(models.Model):
name = models.CharField(max_length=1000)
inhalt = models.TextField(blank=True, null=True)
erstellungsdatum = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name = "Dokumentation"
verbose_name_plural = "Dokumentationen"
def __str__(self):
return self.name
class Bilder(models.Model):
doku = models.ForeignKey(Doku, on_delete=models.CASCADE)
name = models.CharField(max_length=1000)
bilder = models.ImageField(upload_to="bilder/doku/")
def __str__(self):
return self.name
my views.py
#login_required(login_url='login')
def Dokus(request):
doku = Doku.objects.all()
context = {'doku':doku}
return render(request, "doku/index.html", context)
and my template:
{% for doku in doku %}
{{ doku.name }}
{{ doku.bilder.name }}
{% for bilder in doku.bilder_set.all %}
<img src="{{ bilder.bilder.url }}">
<p>{{ bilder.name }}</p>
{% endfor %}
{% endfor %}
EDIT: here's my urls.py:
from django.urls import path
from . import views
from django.contrib.auth import views as auth_views
app_name = "apps"
urlpatterns = [
path('doku/', views.Dokus, name="Doku"),
path('doku/create', views.DokuCreate.as_view(), name="DokuCreate"),
path('doku/detail/<int:pk>', views.DokuDetail.as_view(), name="DokuDetail"),
path('doku/update/<int:pk>', views.DokuUpdate.as_view(), name="DokuUpdate"),
path('doku/delete/<int:pk>', views.DokuDelete.as_view(), name="DokuDelete"),
path('doku/picadd', views.BilderCreate.as_view(), name="DokuBilderCreate"),
]

{{ doku.bilder.name }} isn't going to work. Remove that.
Similarly, {{dokubilder.dokubilder.url}} isn't going to work because there is no dokubilder in your template context.
For the models you have posted, looping through {% for bilder in doku.bilder_set.all %} in your template should work. If it doesn't, you'll need to provide more information about how to reproduce the problem.
I would suggest that you use different variable names for the instance and the queryset, e.g. {% for doku in docku_list %}. If you change it to docku_list, remember to update your view.
{% for doku in dokus %}
{{ doku.name }}
{% for bilder in doku.bilder_set.all %}
<p>{{ bilder.name }}</p>
{% endfor %}
{% endfor %}

Related

How can I get my html to display my django model?

I'm trying to get my django model to be shown in the footer of my base.html but I can't get it to show up. I've looked at a few videos and I can't figure out where I'm going wrong. I know that the model works as I've made 4 entries in my database and I can view them on the admin page. The code also doesn't show any errors so I have nothing to go off of there. Here it is:
Models.py
class SocialMediaPlatform(models.Model):
name = models.CharField(max_length=50, blank=True, null=True)
font_awesome_class = models.CharField(max_length=50, blank=True, null=True)
base_url = models.CharField(max_length=50, blank=True, null=True,
default='https://instagram.com/ or https://tiktok.com/#')
def __str__(self):
return self.base_url
Views.py
def social_media_base_view(request):
context = {}
smbase = SocialMediaPlatform.objects.all()
context['smbase'] = smbase
return render(request, 'base.html', context)
Urls.py
urlpatterns = [
path('', views.social_media_base_view),
]
Admin.py
#admin.register(SocialMediaPlatform)
class SocialPlatformAdmin(admin.ModelAdmin):
list_display = ('name', 'font_awesome_class', 'base_url')
base.html
{% for smlink in smbase %}
<a href="{{ smlink.name }}">
<i class="{{ smlink.font_awesome_class }}">
</a>
{% endfor %}
Look what you are passing as context:
def social_media_base_view(request):
...
smbase = SocialMediaPlatform.objects.all()
context['smbase'] = smbase
return ...
It's QuerySet of SocialMediaPlatform objects. It means, that you can render them one by one with for loop:
{% for smlink in smbase %}
{{ smlink.name }}
{% endfor %}
You don't need to call SocialMediaPlatform model additionaly.
in your view you use:
return render(request, 'index.html', context)
i can not see, if you are defined index.html
Somethere in index you should have
{% extends base.htm %}
The second, i am agree with #Shabble:
{% for smlink in smbase %}
<a href="{{ smlink.name }}">
<i class="{{ smlink.font_awesome_class }}">
</a>
{% endfor %}
The last:
Try to use Django-GCBV TemplateView. Or ListView, in your case it is better:
somethere in views.py
Class MyListView(ListView):
model = SocialMediaPlatform
template_name = index.html
somethere in urls.py
urlpatterns = [
path('', MyListView.as_view()),
]
somethere in index.html
{% for smlink in object_list %}
<a href="{{ smlink.name }}">
<i class="{{ smlink.font_awesome_class }}">
</a>
{% endfor %}

My HTML page won't print my django variable

First of all sorry for my bad english but i'm french.
I am currently working on a django app and i'm trying to make my HTML page work but it won't and i dont know why.
I followed the tutoriel but i edited some of the code to fit my purpose. And now my page won't print out my variable.
I have python 2.7.5 and Django 1.11.29
My html page
Now this is my code for the HTML :
{% if True %}
<p> Vrai </p>
<li>{{ Thriller.title }}</li>
{% else %}
<p> faux </p>
{% endif %}
<ul>
<p> Paragraphe : </p>
<li>{{ Thriller.title }}</li>
<li>{{ Thriller.id }}</li>
</ul>
My code for the Django part :
This is in the models.py file :
from django.db import models
import datetime
from django.utils.encoding import python_2_unicode_compatible
from django.utils import timezone
class Artist(models.Model):
name = models.CharField(max_length=200, unique=True)
def __str__(self):
return self.name
class Album(models.Model):
reference = models.IntegerField(null=True)
created_at = models.DateTimeField(auto_now_add=True)
available = models.BooleanField(default=True)
title = models.CharField(max_length=200, unique=True)
picture = models.URLField()
artists = models.ManyToManyField(Artist, related_name='albums', blank=True)
def __str__(self):
return self.title
This is in the views.py file :
from __future__ import unicode_literals
from django.shortcuts import render
from django.http import HttpResponse
from .models import Album, Artist, Contact, Booking
from django.template import loader
def index(request):
albums = Album.objects.order_by('-created_at')
context = {'albums = ': albums}
template = loader.get_template('polls/index.html')
return HttpResponse(template.render(context, request))
This is also my first post here and i dont really know if the post is good or not so forgive it if it's not good !
You can ask me anything you want. Thank's !
You need to call your context variable in the template instead of {{ Thriller.title }} because you did not specify Thriller in the context of your view.
Your context in the index() view:
context = {'albums = ': albums}
Edit this to:
context = {'albums': albums}
and then in your template, for example to loop over all the album titles:
added the if statement:
{% for album in albums %}
{% if album.title == "Thriller" %}
<p>{{ album.title }}</p>
{% endif %}
{% endfor %}
Try this change to your context
context = {'albums': albums}
Then in your template do...
{% for album in albums %}
<p>{{ album.title }}</p>
{% endfor %}

How do you get queryset objects related to queryset passed to templates in Django

I have these two models and as you can see they have a relationship.
class Post(models.Model):
text = models.TextField()
class PostImage(models.Model):
post = models.ForeignKey(Post, default=None, on_delete=models.CASCADE)
image = models.FileField(upload_to = 'media/',blank=True, null=True)
As far as I understand if I query posts and push them to a template and post, I would expect to use something like this in my templates to retrieve the images URL attached to the posts but it doesn't seem to work.
{% for post in posts %}
{% for post_image in post.post_image_set.all %}
{{post_image.image.url}}
{% endfor %}
{% endfor %}
What am I doing wrong?
Here is my views.py file.
views.py
# Create your views here.
def index(request):
posts=Post.objects.filter(approved=True).order_by('-published_date')
context = {"posts":posts}
return render(request, 'post/home.html',context)
The default related name for a foreign key relational is the name of the model (PostImage) but in your template for loop you called it post_image Following relationships “backward”
change
{% for post_image in post.post_image_set.all %}
into
{% for post_image in post.postimage_set.all %}
Template code (with change)
{% for post in posts %}
{% for post_image in post.postimage_set.all %}
{{post_image.image.url}}
{% endfor %}
{% endfor %}

How to access model.field in template? django

I started learning django few days ago and trying to build my first blog.
My problem is that I decided to add an extra field for my categories (subheading), which I want to be in my template, but can't understand how to do it.
my models.py
from django.db import models
class Category(models.Model):
name = models.CharField(max_length=20)
subheading = models.CharField(max_length=160)
def __str__(self):
return self.name
class Post(models.Model):
title = models.CharField(max_length=255)
body = models.TextField()
link = models.TextField()
categories = models.ManyToManyField("Category", related_name="posts")
def __str__(self):
return self.title
views.py
from django.shortcuts import render
from blog.models import Post, Category
def blog_category(request, category):
posts = Post.objects.filter(
categories__name__contains=category
).order_by(
'title'
)
context = {
"category": category,
"posts": posts
}
return render(request, "blog_category.html", context)
The only way category.name or category.subheading are displayed in template (by the teacher) is inside {% for post in posts %} {% endfor %}:
{% for post in posts %}
{% for category in post.categories.all %}
{{ category.subheading }}
{% endfor %}
{% endfor %}
In this case, if there are 10 posts on category page, subheading repeats 10 times. I only need to print 1 to describe category.
Is there a way to call category.subheading outside of {% for post in posts %} ? Or somehow to print only one result.
p.s. sorry for my primitive English level.
You can do this with a Prefetch object [Django-doc]:
from django.db.models import Prefetch
def blog_category(request, category):
posts = Post.objects.filter(
categories__name__contains=category
).prefetch_related(
Prefetch(
'categories',
Category.objects.filter(name__contains=category)
to_attr='relevant_categories'
)
).order_by(
'title'
)
# …
In your template, you can then render this with:
{% for post in posts %}
{% for category in post.relevant_categories %}
{{ category.subheading }}
{% endfor %}
{% endfor %}
Not sure to understand what you want to do but you can search and access to Category elements by doing something like that:
categories=Category.objects.filter(name='NameYouWanttoSearch').values_list('subheading')
can add a model manager to the categories , take single instance and call it in templates instead of all.
class CategoryManager(models.Manager):
def single_category(self):
return self.get_queryset()[:1]
class Category(models.Model):
name = models.CharField(max_length=20)
subheading = models.CharField(max_length=160)
objects = CategoryManager()
def __str__(self):
return self.name
and in templates
{% for post in posts %}
{% for category in post.categories.single_category %}
{{ category.subheading }}
{% endfor %}
{% endfor %}

How to acces the the django ManyToMany Field in django Template

I have set of attributes in my Models from which one of the attribute is of Type ManyToMany Field. I am able to access all the Attributes in Template instead one which is ManyToMany Field.
I have tried following in my template
{% for post in all_posts %}
{{ post.likes }}
{% endfor %}
models.py
class Posts(models.Model):
title = models.CharField(max_length=250, blank=False)
content = models.CharField(max_length=15000,
help_text="Write Your thought here...")
creation_time = models.DateTimeField(auto_now_add=True, editable=False)
likes = models.ManyToManyField(User, blank=True, related_name='likes')
views.py
def home(request):
template = loader.get_template('home.html')
all_posts = Posts.objects.all()
context = {
'all_posts': all_posts,
}
return HttpResponse(template.render(context, request))
When i Use {{ post.likes }} what renders on page is auth.User.None
You will have to traverse over all the likes for the selected post
Try something like this:
{% for post in all_posts %}
{% for like in post.likes.all %}
{{ like }}
{% endfor %}
{% endfor %}

Categories