Since a few weeks I am learning Python and Django. Up to this point it has been enough to read the questions and the answers of other users.But now the moment of my first own question has come.
I will try to describe my problem as best i can. My problem is that I cant query or get the data I want.
I want to get the url of the first object of class Image which is associated by ForeignKey to a Gallery, which is associated by ForeignKey to the class Entry.
Here the models.py so far:
class BlogEntry(models.Model):
...
title = models.CharField(max_length=100)
...
class Gallery(models.Model):
entry = models.ForeignKey('BlogEntry')
class Image(models.Model):
gallery = models.ForeignKey('Gallery')
picture = models.ImageField(upload_to='img')
The View:
def view(request):
return render_to_response('mainview.html', {
'entryquery': BlogEntry.objects.all(),
}
)
The Template:
{% for item in entryquery %}
<h1>{{ item.title }}</h1>
<img src="{{ item.WHAT TO ENTER HERE? :) }}" />
{% endfor %}
It is clear what I want?
Could somebody help me and when possible write a short explanation?
greetings
Bastian
You can access related members just like other attributes in a template, so you can do something like: item.gallery_set.all.0.image_set.all.0.picture.img. However, it might be easier to define a method on BlogEntry that looked up and returned the appropriate picture, so that you could just do item.first_image or something like that
class BlogEntry(models.Model):
...
title = models.CharField(max_length=100)
...
class Gallery(models.Model):
entry = models.ForeignKey('BlogEntry',related_name="galleries")
class Image(models.Model):
gallery = models.ForeignKey('Gallery',related_name='images')
picture = models.ImageField(upload_to='img')
You have to add related_name in foreign key in gallery model and in template view:
{% for g in blogentry.galleries.all %}
{{g.name}}
{%for i in g.images.all %}
<img src="{{i.picture.url}}">{{i.picture}}</img>
{% endfor %}
{% endfor %}
Related
I have two models related by a Foreign key as follows. (Only shown important fields here.)
in model:
class Category(models.Model):
name = models.CharField(max_length=50, unique=True)
description = models.TextField()
...
class Price(models.Model):
category = models.ForeignKey(Category) # referred to above model
sub_type = models.CharField(max_length=4, choices=CHOICE_SUB_TYPE)
price = models.DecimalField()
...
I'm going to display Categories in a ListView along with related pricing details. In order do that, I need to set related pricing objects for each Category object. What is the best and efficient way to do this?
Your code is fine as it is, in templates, you have access to related models. When listing categories in your template you can:
<ul>
{% for cat in categories %}
<li>{{ cat.name }}</li>
<ul>
{% for price in cat.price_set.all %}
{{ price.price }}
{% endfor %}
</ul>
{% endfor %}
</ul>
For displaying categories when showing details for a price, you might want to Use a Single object Mixin with a ListView.
Recommended: Related object reference.
I am learning Django,
I am having a problem with fetching data from 2 different models with the same view.
My models are as follow :
#python_2_unicode_compatible
class Destination(models.Model):
roadtripname = models.CharField(max_length=100)
def __str__(self):
self.roadtripname
#python_2_unicode_compatible
class Trajectories(models.Model):
roadtripname = models.ForeignKey(Destination, on_delete=models.CASCADE)
place_text = models.CharField(max_length=100)
def __str__(self):
return self.place_text
my view class is this :
class IndexView(generic.ListView):
template_name = 'roadtrip/index.html'
context_object_name = 'roadtrip_list'
def get_queryset(self):
return Destination.objects.filter()
my html is :
{% for roadtrip in roadtrip_list %}
{{ roadtrip.roadtripname }}
{% endfor %}
I have tried to return my 2 models like this :
return Destination.objects.filter(), Trajectories.objects.filter()
and then in html doing
{% for roadtrip in roadtrip_list[0] %}
{{ roadtrip.roadtripname }}
{% endfor %}
but this does not work, I do not know how to be able to access both the Destination and Trajectories models. Could anyone point me in the right direction?
I could just loop through the data from the second set(trajectories) and save in an javascript array when it's equal to the select value.
You could but that is just awful and you're just opening yourself up to allow a client to modify something that they really don't need to.
With every django many-to-x relationship you can find all objects related to another with _set so just keep your initial get_queryset the same (returning destination) and then get trajectories for each object.
{% for roadtrip in roadtrip_list %}
{% for trajectory in roadtrip.trajectories_set.all %}
{# Use trajectories #}
{% endfor %}
{{ roadtrip.roadtripname }}
{% endfor %}
*I'm aware there are very simple optimizations that could be made here for performance improvements but I'm intentionally not including them
I have the following models. I am trying to get the newlistitem model to inherit the same image from the above, if that makes sense. I see that I passed through user as a parameter when calling listitem.user and it works fine, but can't seem to grab the picture of the related object.
HTML Render
I am returning both objects to the form and call
{% for item in listitems %}
<div id = "indivlistitem">
<b>{{item.list_name|title}}</b>
<li><img src="/media/{{ item.list_picture }}"/></li>
<li>{{item|title}}</li>
</div>
{% endfor %}
#MODELS
from django.db import models
from django.contrib.auth.models import User
class newlist(models.Model):
user = models.ForeignKey(User)
list_name = models.CharField(max_length = 100)
picture = models.ImageField(upload_to='profiles/')
def __str__(self):
return self.list_name
class newlistitem(models.Model):
user = models.ForeignKey(User)
list_name = models.ForeignKey(newlist)
list_item = models.CharField(max_length = 200)
list_picture = models.ImageField(newlist.picture)
def __str__(self):
return self.list_item
First things first, list_picture = models.ImageField(newlist.picture)
is not going to work. However, it did provide some insight into what you're trying to do.
Since you already have a foreign key to a list in the newlistitem model (your list_name field), you can access the picture that it's linked to by traversing the foreign key, as such.
You'll note that I've also used the url property that all ImageFields contain, to automatically populate the URL of the picture:
{% for item in listitems %}
<div id = "indivlistitem">
<b>{{item.list_name|title}}</b>
<li><img src="{{ item.list_name.picture.url }}"/></li>
<li>{{item|title}}</li>
</div>
{% endfor %}
UPDATE
Some of the pictures that you are trying to access are blank, so you will need to validate that there is an image associated with each entry.
{% for item in listitems %}
<div id = "indivlistitem">
<b>{{item.list_name|title}}</b>
{% if item.list_name.picture %}
<li><img src="{{ item.list_name.picture.url }}"/></li>
{% endif %}
<li>{{item|title}}</li>
</div>
{% endfor %}
I need to understand a bit better how do FK/m2m relationships work.
I've prepared Images model for uploading images and it has an additional feature - it can be categorized by adding to a specific gallery (m2m relation to gallery).
To access gallery name I just had to do a query set for example:
Images.objects.filter(gallery__gallery_name = '')
I'd like to reverse the query a little bit so from Gallery model I can access pictures which are in specific gallery (gallery_name).
How I can do that?
Models:
class Images(models.Model):
image = models.ImageField(upload_to=update_filename, blank=True, null=True, verbose_name="Obrazek")
gallery = models.ForeignKey('Gallery', blank=True, null=True)
class Gallery(models.Model):
gallery_name = models.CharField(max_length=128)
gallery_description = models.TextField(blank=True, null=True)
View:
def index(request):
p = Gallery.objects.filter(gallery_name="main").order_by('-id')
return TemplateResponse(request, 'gallery.html',
{'gallery': p,
},)
Template:
{% for n in gallery.all %}
<h2 class="center">{{n.gallery_name}}</h2>
<hr>
{% for n in gallery.images_set %}
<div class="grid_4">
{{ n.image }}
</div>
{% endfor%}
Try something along the lines of:
# models.py
class Gallery(models.Model):
name = models.CharField(max_length=30)
description = models.CharField(max_length=200, null=True)
images = models.ManyToMany(Image)
class Image(models.Model):
title = models.CharField(max_length=30)
caption = models.CharField(max_length=200, null=True)
image = models.ImageField(upload_to=SOMEPLACE_FOR_MEDIA)
From here you should be able to do things like:
image = Image.objects.get(title="Girl Holding Cheese")
related_galleries = image.gallery_set.all()
or something similar as needed to pull what you want. The same goes the other way. To pull all images in a gallery you would do
gallery = Gallery.objects.get(name="Cheesy Wimmin")
related_images = gallery.images.all()
Though the assignments at the end aren't necessary, I usually just pass gallery.images.all() or image.gallery_set.all() directly. Note the "_set" at the end of the reference from the object that does not contain the M2M definition.
On the subject of direct usage, you can do compound references like
Image.objects.get(title="Girl Holding Cheese").gallery_set.all()
as well, but you have to decide when this makes code more clear and concise and when it just makes it more confusing to read later.
I hope this put you in the right direction.
Update
In your comment below you noticed that you cannot do
images = Images.objects.filter(gallery_set="Cheesy Wimmins")
related_galleries = images.gallery_set.all()
This is because you would be trying to filter() or all() on a queryset, not an individual model. So to make this work you can use a for loop in your template. Something like
# views.py
galleries = Gallery.objects.all()
return render(request, 'some/template.html', {'galleries': galleries})
And then
<!-- templates/some/template.thml -->
{% for gallery in galleries %}
<div class="gallery">
<h2>{{ gallery.name }}</h2>
{% for item in gallery.images.all %}
<div class="image">
{{ item.image }}
</div>
{% endfor %}
</div>
{% endfor %}
or something like this. Of course, you need to do whatever formatting steps you want to make this look right, but that's a way to get at your data.
The problem is with the {% for n in gallery.images_set %} bit in your template. images_set is a related manager, not a queryset. To get a queryset, you need to call all or another of the DBAPI methods that return querysets. So, just change it to gallery.images_set.all, and you're good.
gallery is a QuerySet - it doesn't have a images_set.
This is where naming your variables more appropriately can easily start preventing these problems: for example, galleries would be more appropriate for a list of Gallery objects... then, galleries.images_set would immediately raise red flags.
Anyways, you need to call images_set on what you've called n
{% for n in gallery.all %}
<h2 class="center">{{n.gallery_name}}</h2>
<hr>
{% for n in n.images_set.all %}
<div class="grid_4">
{{ n.image }}
</div>
{% endfor%}
I'm a little confused by the Django lingo. So I have 3 models: Post, UserProfile(User), Favorite. Favorite keeps track of which Posts a User has favorited.
Post--->Favorite<---User/UserProfile
Favorite model:
class Favorite(models.Model):
user = models.ForeignKey(User, unique=False)
post = models.ForeignKey(Post, unique=False)
def __unicode__(self):
return self.user.username
UserProfile model:
class UserProfile(models.Model) :
user = models.ForeignKey(User, unique=True)
def get_favorites(self):
if self.user:
return self.user.favorite_set.all()
In my post_list view I pass all Posts to my template, and in the template I have a for loop that displays all Posts.
{% for post in post_list %}
<hr/>
<div id=”post_{{ post.id }}”>
{% include 'posts/_post.html' %}
</div>
{% endfor %}
Now in that for loop I would like to put a logic that will display "Favorited!" if the logged-in User has favorited the Post. I think the conventional SQL is something like this:
SELECT favorite.post FROM favorite WHERE favorite.user = user.id
So that in the template loop I can do
{% if post in the.above.SQL.query%}Favorited!{% endif %}
Now I just can't translate that to Django lingo for some reason. Your help is much appreciated!
The thing to recognise is that your Favorite model is actually the through table of a many-to-many relationship between Post and User. Django can actually manage that automatically if you declare a ManyToManyField somewhere. Personally, I would do that on UserProfile - so the relationship actually becomes one between Post and UserProfile:
class UserProfile(models.Model):
favorites = models.ManyToManyField(Post, related_name='favorited_by')
Now you don't need your get_favorites method, as it is available via userprofile.favorites.all(). You could just use this as-is in the template:
{% if post in userprofile.favorites.all %}Favorited!{% endif %}
but this will end up being extremely inefficient, as you'll be doing the same identical query for each post in your list of posts. So, use the {% with %} tag to get the favorites once before the loop:
{% with userprofile.favorites.all as favorite_posts %}
{% for post in post_list %}
{% if post in favorite_posts %}Favorited{% endif %}
...
{% endfor %}
{% endwith %}
While Daniel makes good point, i'll just post the query you wanted :)
Post.objects.filter(favorite__user=user)
Since its many to many relationships,
fav_post = user.favourite.all() you can pass this fav_post to context. Then in the template, you will need to iterate that context key