Fetch Django models in list view to show both - python

I have this models:
Article:
class Article(models.Model):
sku = models.CharField(
max_length=5,
primary_key=True,
validators=[MinLengthValidator(5)]
)
ean = models.CharField(
max_length=13,
unique=True,
validators=[MinLengthValidator(13)]
)
parent = models.ForeignKey(
'Article',
related_name='children',
null=True,
blank=True,
on_delete=models.PROTECT
)
...
and ArticleTranslations:
class ArticleTranslation(models.Model):
LANGUAGE_CHOICES = (
(settings.ENGLISH, _("english")),
(settings.FRENCH, _("french")),
(settings.GERMAN, _("german")),
(settings.ITALIAN, _("italian")),
(settings.PORTUGUESE, _("portuguese")),
(settings.SPANISH, _("spanish")),
)
article = models.ForeignKey(
'Article',
on_delete=models.CASCADE,
related_name='translations',
)
I need to return both, combined to show the 2 items in a Django Templates HTML for. Need to have the item and the foreign key and see it in the same iterations. I wanna do it with the methods of the class List View and django, and not doing something bad.
I have this ListView:
def get_queryset(self):
queryset = (Article.objects
.all()
.prefetch_related('translations')
.order_by('-sku'))
print(queryset)
return queryset
And in my HTML, need to show the foreign key values:
{% extends "base.html" %}
{% block content %}
{% for article in article_list %}
<div class="container">
<h2>{{ article.translations.NEED_TO_SHOW_THAT_PARAMETER }}</h2>
</div>
{% endfor %}
{% endblock content %}

In your view you're already getting right data. So in your template you can simply loop through the Article objects and it's foreign key values (as they can be accessed using related_name)
you're using {% for article in article_list %} so I believe you have context_object_name = 'article_list' set in your views.
I'm guessing extra fields for translations model which you're probably wanting to access. If your model looks something like this:
class ArticleTranslation(models.Model):
LANGUAGE_CHOICES = (
(settings.ENGLISH, _("english")),
(settings.FRENCH, _("french")),
(settings.GERMAN, _("german")),
(settings.ITALIAN, _("italian")),
(settings.PORTUGUESE, _("portuguese")),
(settings.SPANISH, _("spanish")),
)
article = models.ForeignKey(
'Article',
on_delete=models.CASCADE,
related_name='translations',
)
language = models.CharField(max_length=10, choices=LANGUAGE_CHOICES)
Then in your template you can do:
{% extends "base.html" %}
{% block content %}
{% for article in article_list %}
<div class="container">
{% for object in article.translations.all %}
<h2>Chosend language - {{ object.language }}</h2>
{% endfor %}
</div>
{% endfor %}
{% endblock content %}
Explanation:
article.translations.all will give you all translations for one article, using this you can get the field value

Related

How do I show navbar items based on a model field in Django?

I have a Blog model that looks like this:
class Blog(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
slug = models.SlugField(max_length=200, unique=True)
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='blogs')
parent = models.CharField(max_length=50, choices=PARENT_TUTORIALS)
def get_absolute_url(self):
return reverse("blog_list", args=[str(self.parent), str(self.slug)])
I can succesfully display all the blogs on a table of contents via my table.html template:
{% for blog in blog_list %}
<li>{{blog.title}}</li>
{% endfor %}
However, I want to show only those blogs that have the same Blog.parent value as the current blog page. For example, the page example.com/biology/page1, has biology as a parent. When the user is on that page, the table of contents should show only the pages that have biology as a parent.
Why not just add an if statement like so?
template.html
{% for blog in blog_list %}
{% if blog.parent == current_blog.parent %}
<li>{{blog.title}}</li>
{% endif %}
{% endfor %}
Another option is to filter with js, something like (untested):
template.html
{% for blog in blog_list %}
<li class="blog-list-item {{blog.parent}}">
{{blog.title}}
</li>
{% endfor %}
script.js
$('.blog-list-item').filter(':not(.biology)').hide();

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 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 %}

Related Objects Reference Django

Given the following code:
Models.py
class Advertisement(models.Model):
title = models.CharField(null=True, blank=True, max_length=30)
created_by = models.ForeignKey(User)
class Gallery(models.Model):
advertisement = models.ForeignKey(Advertisement, related_name='images')
image = models.ImageField(upload_to=image_directory_path, help_text="Your ad image (Recommended size: 1024x768)")
creation_date = models.DateTimeField(editable=False, default=timezone.now)
Views.py
def do_foo(request):
search_result = Advertisement.objects.all().order_by('-creation_date')
return render(request, 'content_search.html',
{
'search_result': search_result
})
page.html
{% for ad in search_result %}
{% for ad_image in ad.gallery_set %}
<img src="{{ ad_image.image.url }}">
{% endfor %}
{% endfor %}
How do I access the backwards relation between Advertisement and Gallery? I tried ad.gallery_set and ad.images_set but I could not get the images.
I tried to follow what they say here Django Relation Objects Reference and in this topic.
Your code has related_name="images". So ad.images it is.
Edit: as shredding notes correctly, you can't use that directly if you want to loop over it, and need to add .all to get a queryset object:
{% for ad_image in ad.images.all %}
<img src="{{ ad_image.image.url }}">
{% endfor %}
Maybe related name "galleries" would be a bit more clear.

django categories: How to get children of a category using django-categories?

I am using django-categories to implement music related app. I want artist as my category and his/her songs as children
models.py
from django.db import models
from django_extensions.db.fields import AutoSlugField
from categories.models import CategoryBase
class Artist(CategoryBase):
cat = models.CharField(max_length=255, blank=True)
def __unicode__(self):
return self.name
class Song(models.Model):
title = models.CharField(max_length=255,)
slug = AutoSlugField(populate_from='title', unique=True)
description = models.TextField()
cat = models.ForeignKey(Artist, blank=True)
def __unicode__(self):
return self.title
In templates, artist_details.html
{% extends 'base_post.html' %}
{% load category_tags %}
{% block page_content %}
<h1>{{ artist.name }}</h1>
{% if artist.children.count %}
<h2>Subcategories</h2>
<ul>
{% for child in artist.children.all %}
<li>{{ child }}</li>
{% endfor %}
</ul>
{% endif %}
The template is getting rendered coz I can see artist's name. But i am unable to fetch the children. I checked the docs but I could not find much stuff related to fetching children.
There is data for both models in my DB, I added relevant info via admin interface. Can anyone tell me what I am missing ?
Also I open to using better packages. You can give any suggestions that implements categories.
SOLUTION: From django docs https://docs.djangoproject.com/en/1.6/topics/templates/#accessing-method-calls
thanks mariodev
Even using django-categories, you can't have songs as children of artists. Artists just do not form a category.
What you instead want is something like this:
from django.db import models
from django_extensions.db.fields import AutoSlugField
from categories.models import CategoryBase
class MusicCategory(CategoryBase):
# add extra fields, like images, "featured" and such here
pass
class Artist(CategoryBase):
name = CharField(max_length=255,)
categories = models.ManyToManyField(MusicCategory, related_name="artists")
def __unicode__(self):
return self.name
class Song(models.Model):
slug = AutoSlugField(populate_from='title', unique=True)
title = models.CharField(max_length=255,)
artist = models.ForeignKey(Artist, related_name="songs", on_delete=models.PROTECT)
categories = models.ManyToManyField(MusicCategory, related_name="songs")
description = models.TextField()
def __unicode__(self):
return self.title
and with some templates
{% extends 'base_post.html' %}
{% load category_tags %}
{% block page_content %}
<h1>{{ artist.name }}</h1>
{% if artist.songs.all.exists %}
<h2>Songs</h2>
<ul>
{% for song in artist.songs.all %}
<li>{{ song }}</li>
{% endfor %}
</ul>
{% endif %}
REF: https://django-categories.readthedocs.org/en/latest/custom_categories.html#creating-custom-categories

Categories