Learning multi tables joining info django - python

While i find this post Django views.py Version of SQL Join with Multi Table Query helpful. It does not seem to help me with understading joining tables. I had earlier help on a question and I thought I got it. I am trying to do the following show (current) players on the Boston Penguins.
Code I have currently trying to pull it is
Player.objects.filter(team__all_teams__contains='boston', player__curr_team__contains="Penguins")
Which by reasoning anyway puts me in the Player.objects of my model and should be filtering from my team all the teams with Boston which there is on and then should pull all the current players for that team.
Even better than just giving me an answer is a link to a video or document that better explains this so I can study it better to learn the call functions.
Models.py
from django.db import models
class League(models.Model):
name = models.CharField(max_length=50)
sport = models.CharField(max_length=15)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Team(models.Model):
location = models.CharField(max_length=50)
team_name = models.CharField(max_length=50)
league = models.ForeignKey(League, related_name="teams")
class Player(models.Model):
first_name = models.CharField(max_length=15)
last_name = models.CharField(max_length=15)
curr_team = models.ForeignKey(Team, related_name="curr_players")
all_teams = models.ManyToManyField(Team, related_name="all_players")
views.py only line i need help with rest works fine if i take out that line
"bostonp" : Player.objects.filter(team__all_teams__contains='boston', player__curr_team__contains="Penguins") ,
index.html only section that doesnt work take it out and it works
<h5>Question 2</h5>
{% for whatever in bostonp %}
<li>{{whatever.team_name}}</li>
{% endfor %}
</ol>

Try this (this will fetch player instances):
bostonp = Player.objects.filter(curr_team__team_name__contains='Penguins')
And then in your template:
{% for player in bostonp %}
<li>{{ player.first_name }} {{ player.last_name }}</li>
{% endfor %}

Related

Django models referencing each other

I have two models and I want to put an if condition in my template to get the desired output.
I have the first model
class Subject(models.Model):
name = models.CharField(max_length=50)
books = models.ForeignKey('Books')
And the second one
class Books(models.Model):
name = models.CharField(max_length=50)
subject = models.ForeignKey(Subject, on_delete=models.CASCADE)
And a view
def View(request):
subjects = Subject.objects.all()
return render('my_html.html",{'subjects':subjects})
In my model, I have wanted to do this.
{% for subject in subjects %}
{% if subject.books.count > 0 %}
{{ subject.name }}
{% endif %}
{% endfor %}
I thought the only way is to have the models referencing each other for my plan to work but I also think that looping will require more resources. Is there a better way of doing this either thro' the view or just in the models?
You only need to ForeignKey from Book to Subject, so:
class Subject(models.Model):
name = models.CharField(max_length=50)
# no books
class Books(models.Model):
name = models.CharField(max_length=50)
subject = models.ForeignKey(Subject, on_delete=models.CASCADE)
then you can filter the subjects such that it only retrieves Subjects with at least one book:
def view(request):
subjects = Subject.objects.filter(books__isnull=False).distinct()
return render(request, 'my_html.html', {'subjects': subjects})
this will make a LEFT OUTER JOIN on the table of the Book model, and check if there is at least one book. You thus do not need to filter in the template (which is not a good idea anyway).

How can i get all related object's manytomany related field's records in Django by single query

class Author(models.Model):
name = models.CharField(max_length=50)
class Chapter(models.Model):
book = models.ForeignKey(Album, on_delete=models.CASCADE)
author = models.ManyToManyField("Author")
class Book(models.Model):
author = models.ManyToManyField("Author")
I can get Author.objects.get(id=1).chapter_set.all() and append each chapters author to the List but how can i achieve this by query in Django
you can follow this.
for fetching data in python you can use like this way.
fetch = Chapter.objects.all()
#and then for fetch the author
for chapter in fetch:
author_fetch = chapter.author.all()
#and now you can access the all data from author
print(author_fetch[0].name)
and for showing data to html you don't need to call author_fetch. you can directly call it in html. Here is an example
{% for chapter in object_list %}
{% for author in chapter.author.all %}
{{author.name}}
{% endfor %}
{% endfor %}

Is it possible to create a for loop inside a main for loop inside django templates?

I'm just learning django part time and I'm stuck on a problem that I just can't seem to find a solution to. I feel it is probably pretty simple, but I just can't seem to see it right now.
In django I have the following table
class category(models.Model):
category = models.CharField(max_length=100)
def __str__(self):
return f"{self.id} is {self.category}"
class knowledge(models.Model):
name = models.CharField(max_length=16)
location = models.URLField(max_length=1024)
title = models.TextField(blank=True, max_length=512)
description = models.TextField(max_length=1024)
category = models.ForeignKey(category, on_delete=models.CASCADE, related_name="content")
def __str__(self):
return f"{self.id}{self.name} {self.location} {self.description}"
class notes(models.Model):
note = models.TextField(blank=True, max_length=1024, default='none')
date_added = models.DateTimeField(blank=True, default=timezone.now)
knowledge = models.ForeignKey(knowledge, on_delete=models.CASCADE, related_name="mynotes")
def __str__(self):
return f"Added on {self.date_added}"
For my views I have
def kbs(request, category_id):
# get all the objects in the category table with the id specified
cate = category.objects.get(id=category_id)
# once you have the category id get all the objects from the knowledge table using the related name content
know = cate.content.all()
# for each id in know create a list of notes?
return render(request, "knowledge/category.html", {"cate": cate, "know": know,})
I can loop over all the items in the knowledge table and display them in my template. I wanted to add some notes to each knowledge article from another table. I added the notes table and referenced the knowledge table. In the template instead of displaying the id, I would like to loop over all the notes associated with that id and list those notes there.
here is my template
{% for knowledge in know %}
<h5{{knowledge.title}}</h5>
<p>{{ knowledge.description|linebreaks }}</p>
<p> {{ knowledge.id }}</p>
{{knowledge.name}}
{% endfor %}
I imagine there are two things that I need to do. I need to pass in a list of all the notes to my template from my views, then when it comes to the id I should be able to use templating to list all the items in my notes for that particular knowledge id. Perhaps a for loop nested in the main loop. I'm sure there must be an easy solution, I just can't seem to be able to figure it out. Can anyone assist?
Use the value of the related_name attribute to get the ForeignKey values of an object, in your template do something like this:
{% for knowledge in know %}
{{ knowledge }}
{% for note in knowledge.mynotes.all %} # btw I recommend renaming the 'mynotes' to something that is easier to understand like just 'notes'
{{ note }}
{% endfor %}
{% endfor %}

Django HTML 'for loop' not displaying any of the objects in a set

so I am having trouble with my for loop which is meant to display all the tasks allocated to a user. There are four tasks allocated to them, as you can see on this imgur link . However it does not show them on the site.
Here is my detail.html file:
<h1>{{user.fullName}}</h1>
<h4>Username: {{user.userName}}</h4>
<ul>
{% for i in userName.i_set.all %}
<li> {{ i.taskName }} </li>
{% endfor %}
</ul>
Here is my models.py:
from django.db import models
class User(models.Model):
userName = models.CharField(max_length=30)
password = models.CharField(max_length=100)
fullName = models.CharField(max_length=50)
def _str_(self):
return self.fullName
class Task(models.Model):
userName = models.ForeignKey(User, on_delete=models.CASCADE)
taskName = models.CharField(max_length=30)
scores = models.CharField(max_length=100) # score should default be set to x/10 until changed
def _str_(self):
return str(self.userName) + ' - ' + self.taskName
I know its a pain to help someone you don't know but I'd really appreciate it as ive been working on this problem for an hour and managed nothing and I'm really eager to learn what the problem is... thanks so much and have a nice day!
Based on the code you have provided your for loop code is completely wrong, try to change it to:
{% for i in user.task_set.all %}
More better is to use related_name in ForeignKey for ease of access:
userName = models.ForeignKey(User, on_delete=models.CASCADE, related_name='tasks')
Then you can access related tasks for user in template like this:
{% for i in user.tasks.all %}

Django relational database in view

I have a django application where I have few manytomany fields and im trying to show these relation records in my listing, however it all comes blank
so this is my model:
class Genre(models.Model):
genre_name = models.CharField(max_length=50)
genre_slug = models.SlugField(max_length=300)
genre_meta = models.TextField(max_length=300)
genre_description = models.TextField(max_length=300)
listing = models.BooleanField(default=True)
def __unicode__(self):
return self.genre_name
class Movie(models.Model):
movie_name = models.CharField(max_length=50)
movie_slug = models.SlugField(max_length=300)
movie_description = models.TextField(null=True, max_length=300)
movie_category = models.ManyToManyField(Category, related_name='category')
movie_genre = models.ManyToManyField(Genre, blank=True, related_name='genre')
listing = models.BooleanField(default=True)
def __unicode__(self):
return self.movie_name
this is my view
def AllMovies (request):
movies= Movie.objects.all().order_by('movie_name')
context = {'movies': movies}
return render_to_response('all.html', context, context_instance=
RequestContext(request))
and this is my template
{% for movie in movies %}
{{ movie }}
{% for genre in movies.genre.all %}{{ genre_name }}{% endfor %}
{% endfor %}
so there are three concerns here:
1- All I get is blank in my template
2- What would be the best option to show items which have been ticked as listed and hide the rest in template
3- This is a data bank so im sure we will need to use load more button in my template, but if i want to show 30 of items instead of all
Try this:
{% for movie in movies %}
{{ movie }}
{% for genre in movie.movie_genre.all %}{{ genre_name }}{% endfor %}
{% endfor %}
You were trying to iterate over movies.genre.all, which is wrong because:
movies is a queryset, you should use movie instead, as it is a Model instance
genre is not a field in the Movie model, you should use movie_genre, which is a ManyToManyField you are looking for
I believe you didn't understand the related_name attribute. It doesn't modify the behavior of the field (in this case: movie_genre). Instead, it changes the name of an attribute in a related model (in this case: Genre). For example, you can use it to get all related movies:
>>> genre = Genre.objects.get(name='Drama')
>>> genre.genre.all()
[<Movie>, <Movie>, ...]
As you can see, your choice of a related_name wasn't so good. Something like movies would be more appropriate.
Please, read the documentation once again, as you probably didn't understand Django's logic around relations (foreign keys, many-to-many, etc.).
Besides, here are a few style-related tips:
don't use movie_ and genre_ prefixes in field names - e.g. it is obvious that genre_name is a name of a genre, since it is defined inside Genre model
try to follow PEP8 (http://legacy.python.org/dev/peps/pep-0008/), as it is a standard in the Python community
read about class-based views (https://docs.djangoproject.com/en/dev/topics/class-based-views/) - you may find them very helpful

Categories

Resources