django - get latest object with model method in template - python

I have a model with method.
class Book(models.Model):
title = models.TextField()
class Review(models.Model):
content = models.TextField()
book = models.ForeignKey(Book,related_name="book_reviews")
def lastreview(self):
return self.objects.order_by('-id')[:1]
but once I use this method in template
{{book.book_reviews.lastreview.content}}
it is showing nothing..
what am i missing here?

I believe you are trying to retrieve the latest review of a book (which was not clear from your question). The related reviews for a book can be accessed by book.book_reviews. It is a QuerySet rather than a single Review object, hence {{ book.book_reviews.lastreview }} will fail.
I would recommend moving the lastreview method directly under Book, like:
class Book(models.Model):
title = models.TextField()
def lastreview(self):
try:
return self.book_reviews.order_by('-id')[0]
except IndexError:
return None
Now you can access the latest review of a book in your template by
{{ book.lastreview.content }}
Note: I recommend adding a DateTimeField to Review, as finding the latest review based on id can be misleading. For e.g., someone can edit an old review and it will not be shown as the latest.

Related

Django how to add query results foreign key model to queryset

How can I get the Author model objects into a queryset through the foreign key of B model? I would like to use the Author objects in my template.
#Models.py
class Book(models.Model):
name = models.CharField(max_length=5)
class Author(models.Model):
# lots of fields
class B(models.Model):
author = models.ForeignKey(Author)
book = models.ForeignKey(Book)
selected_book = "ABC"
book = Book.objects.get(name=selected_book)
original_queryset = B.objects.filter(name=book)
for i in original_queryset:
print(i.author) # returns what i want
queryset = # get all i.author objects somehow
return render(request,"template.html", {"queryset": queryset}
Remove the for loop. then add the following line after the original_queryset = B.objects.filter(name=book) line->
queryset = original_queryset.author
If this doesn't work then let me know. I hope I can help you.
You can rename your B model's author field to authors, that makes your code more meaningful because ForeignKey field can store many data. In your code, you have made your B model's author field as a ForeignKey field, which means books can have multiple authors. You can see the django documentation of ForeignKey reference.
If you change as I told you then don't forget to run migration(python manage.py makemigrations and python manage.py migrate command in your cmd) and change the line queryset = original_queryset.author to queryset = original_queryset.authors
Another approach
You can pass the original_queryset in the context of the template,(i.e: {'queryset':original_queryset }) then in your template.html, you can add tages like this:
{% for book in queryset %}
<ul>
{% for author in book.author %}
<li>author.name</li>
....
{% endfor %}
</ul>
{% endfor %}
By doing these, you can place your books and authors in your template nicely. If it still shows error, message me, I hope I can help you.

Calling Model function in template not working

I'm trying to get the category of a skill in a template.
From the post I read, I can't directly get information from a foreign key in a template.
Instead, I add a function on CharacterSkill models to get the Skill category
Models.py
class Character(models.Model):
name = models.CharField(max_length=70)
class Skill(models.Model):
name = models.CharField(max_length=70)
cat1 = '01'
SKILLSET_CHOICE = ((cat1:'cat1'))
skillset_choice = models.CharField(
max_length=2,
choices = SKILLSET_CHOICE,
default='',
blank=True,
null=True,
)
class CharacterSkill(models.Model):
character = models.ForeignKey(Character, on_delete=models.CASCADE)
skill = models.ForeignKey(Skill, on_delete=models.CASCADE)
def skillcategory(self):
return Skill.objects.get(id = self.skill).skillset_choice
Template
skillsetchoice {{item.skillcategory}}
But I get an error :
Exception Type: TypeError
Exception Value:
int() argument must be a string or a number, not 'Skill'
I tried to inpect value with the shell console where I can get back the category id but when I use it in template, nothing is working
Hope you can help me!
This has nothing to do with calling it from the template.
self.skill is already an instance of Skill. There is no need to query that model explicitly.
def skillcategory(self):
return self.skill.skillset_choice
And in fact this method is pretty pointless; you certainly can do it directly in the template:
skillsetchoice {{ item.skill.skillset_choice }}
Replace self.skill with self.skill.id (in older versions of Django your code would work by the way):
def skillcategory(self):
return Skill.objects.get(id = self.skill.id).skillset_choice
But this is much better:
def skillcategory(self):
return self.skill.skillset_choice
But do you really need this method? You can use:
{{ item.skill.skillset_choice }}
If you want to display cat1, then (get_foo_display):
{{ item.skill.get_skillset_choice_display }}

django like integration not working

I want to integrate like model in my app. Then this Q/A really helped me to start over it.
class Like(models.Model):
user = models.ManyToManyField(User, related_name='likes')
article = models.ForeignKey(Article)
created = models.DateTimeField(auto_now_add=True)
total_likes = models.IntegerField(default=0)
But later i found one problem
Cannot resolve keyword 'slug' into field. Choices are: content, creation_date, id, like, title, user, user_id
Well now started question what is really slug field here ? in name="{{ article_slug }}". Well nothing printed in html page [name=""] And then i found
slug = request.POST.get('slug', None)
article = get_object_or_404(Article, slug=slug)
liked, created = Like.objects.create(article=article)
this code is causing above issue.So i changed the code to slug=slug ==> content=slug then this time i am getting different error..
<p>No Article matches the given query.</p>
Ah .. this time i got it.. Now i changed to name="{{ id }}" .. hm nothing happened same error..
silly me.. definitely i am missing something really very simple. Anybody got it?
get_object_or_404 works with a specific, unique field that is specified on the model.
Therefore ensure that the slug field is specified on your Article model class. Example:
class Article(models.Model):
slug = models.SlugField(max_length=50)
# remaining fields

Trouble handling generic relationship in django

I want to model a situation and I´m having real trouble handling it. The domain is like this: There are Posts, and every post has to be associated one to one with a MediaContent. MediaContent can be a picture or a video (for now, maybe music later). So, what I have is:
mediacontents/models.py
class MediaContent(models.Model):
uploader = models.ForeignKey(User)
title = models.CharField(max_length=100)
created = models.DateTimeField(auto_now_add=True)
def draw_item(self):
pass
class Meta:
abstract = True
class Picture(MediaContent):
picture = models.ImageField(upload_to='pictures')
class Video(MediaContent):
identifier = models.CharField(max_length=30) #youtube id
posts/models.py
class Post(models.Model):
...
# link to MediaContent
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
media_content = generic.GenericForeignKey('content_type', 'object_id')
What i eventually want to do, is beeing able to call methods like:
post1.media_content.draw_item()
>> <iframe src="youtube.com" ...>
post2.media_content.draw_item()
>> <img src="..."/>
Is this the correct aproach, does it work? Can the template be agnostic of the object underneath?
Your approach looks good to me. You just need to override the draw_item method in your Picture and Video models. Your template will look something like
{% for post in posts %}
{{ post.media_content.draw_item }}
{% endfor %}
and it doesn't matter which model the generic foreign key points to, as long as it has a draw_item method defined.

Django ManyToMany Template Questions

Good Morning All,
I've been a PHP programmer for quite some time, but I've felt the need to move more towards the Python direction and what's better than playing around with Django.
While in the process, I'm come to a stopping point where I know there is an easy solution, but I'm just missing it - How do I display manytomany relationships in a Django Template?
My Django Model: (most of the fields have been removed)
class Category(models.Model):
name = models.CharField(max_length=125)
slug = models.SlugField()
categories = models.ManyToManyField(Category, blank=True, null=True)
class Recipe(models.Model):
title = models.CharField('Title', max_length=250)
slug = models.SlugField()
class Photo(models.Model):
recipe = models.ForeignKey(Recipe)
image = models.ImageField(upload_to="images/recipes", blank=True)
So, there is the basic models I'm using in my application called "recipes."
With that said, there are two questions I'm looking for answers on:
How would I go about displaying the categories for a recipe on it's details page?
How would I go about displaying the image for the recipe on it's details page?
If I go into the Python shell, and input the following, I do get a result:
>>> photos = Photo.objects.filter(recipe=1)
>>> photos
[<Photo: Awesome Pasta>]
>>> for photo in photos:
... print "Photo: %s" % photo.logo
...
Photo: images/recipes/2550298482_46729d51af__.jpg
But when I try something like the following in my template, I get an error saying "Invalid block tag: 'photo.image'."
{% for photo in photos %}
{% photo.image %}
{% endfor %}
Although, even if that did work, the ID is still hard coded into the view, how would you go about having this dynamic for each recipe?
Details Page View.py snippet:
def details(request, slug='0'):
p = get_object_or_404(Recipe, slug=slug)
photos = Photo.objects.filter(recipe=1)
return render_to_response('recipes/recipes_detail.html', {'p': p, 'photos': photos})
Thanks in advance for the help and understanding for what is probably a very simple question to all of you!
UPDATE: When removing the additional fields in the models, I forgot the categories field for the Recipes model.
From what I can see, I think you've got a small syntax error:
{% photo.image %}
should instead be:
{{ photo.image }}
The {% %} notation is used for django template tags. Variables, on the other hand, are expressed with the {{ }} notation.
To make it dynamic, you can take advantage of the fact that your Photo model has a foreign key to Recipe. This means that there will be a reverse relation from the Recipe instance you've loaded using the slug back to the set of photos:
def details(request, slug='0'):
p = get_object_or_404(Recipe, slug=slug)
photos = p.photo_set.all()
Hopefully that will work for you. Glad to see you're enjoying working with Django!

Categories