Requests for django in the case of a foreign key - python

I have two tables, Author and Book, Each book is written by a mutliple author, by against an author can create a (one) book, I want to get the book list created by a single author.
In my template, I would view the authors who have written one book
my models.py
class Book(models.Model):
user = models.OneToOneField(User,related_name='user')
name = models.CharField(default=0)
def __unicode__(self):
return u'%s' % self.user
class author(models.Model):
name_auth = models.CharField(max_length=256)
Book = models.ForeignKey(compte)
def __unicode__(self):
return u'%s' % (self.name_auth)
my view.py
Book1 =Book.objects.filter(user=request.user).values()
Book1_id= Book1.id
author = Author.objects.filter(pk=Book1_id).values
reponse[author]=author
my template
{% for t in author %}
<td>{{ t.name }}</td>
{% endfor %}

The logic in your models is incorrect given your statement...
"A book can have multiple authors"
You need to use a ManyToManyField to represent the authors of a book:
class Author(models.Model):
user = models.OneToOneField(User)
def __unicode__(self):
return self.user.get_full_name()
class Book(models.Model):
authors = models.ManyToManyField(Author)
name = models.CharField(max_length=500)
def __unicode__(self):
return self.name
# views
from django.shortcuts import render, get_object_or_404
def book_detail(request, book_id):
book = get_object_or_404(Book, id=book_id).prefetch_related('authors')
return render(request, 'book_detail.html', {'book': book})
# book_detail.html
{% for author in book.authors.all %}
{{ author }}
{% endfor %}

Related

Django templates: data filtering by foreign key

I'm new to Django and I have a problem I can't seem to solve. Long story short, I created a text based app that helps me create a meal plan and generates a shopping list. And I'm trying to recreated with django.
Here are my models:
class Recipe(models.Model):
name = models.CharField(max_length=40)
def __str__(self):
return self.name
class Category(models.Model):
name = models.CharField(max_length=20)
def __str__(self):
return self.name
class Ingredient(models.Model):
name = models.CharField(max_length=20)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
def __str__(self):
return self.name
class IngredientSet(models.Model):
recipe = models.ForeignKey(Recipe, on_delete=models.SET_NULL, null=True)
ingredient = models.ForeignKey(Ingredient, on_delete=models.DO_NOTHING)
quantity = models.FloatField()
def __str__(self):
return self.ingredient.name
Now, on my List Views I want to display the names of stored recipes as links. Each recipe link should call a Detail View which will display selected recipe's sets of ingredients. I can't figure out how to access those by their foreign key(which points to a recipe).
One can access reverse relations by using the model name in lowercase with _set appended. For Recipe and IngredientSet you can write recipe.ingredientset_set.all() to get all the instances of IngredientSet related to a recipe. One can customize this name by setting the related_name e.g.:
class IngredientSet(models.Model):
recipe = models.ForeignKey(Recipe, on_delete=models.SET_NULL, null=True, related_name="ingredient_sets")
ingredient = models.ForeignKey(Ingredient, on_delete=models.DO_NOTHING)
quantity = models.FloatField()
def __str__(self):
return self.ingredient.name
Now you can write recipe.ingredient_sets.all().
To loop over this in the template one can simply write:
{% for ingredient_set in recipe.ingredient_sets.all %}
{{ ingredient_set.ingredient.name }}
{{ ingredient_set.quantity }}
{% endfor %}
Note: This will make a query to the database for each recipe to get it's ingredient set. You can use prefetch_related [Django
docs]
if you want to reduce the amount of queries made.
assuming that you want to display the names of stored recipes in a html template as links:
views.py
from .models import Recipe, Ingredient, IngredientSet
from django.shortcuts import render
def recipes(request):
recipes_for_template = Recipe.objects.all()
return render(request, 'main/recipes.html', {"recipes": recipes_for_template})
def ingredients(request, cod_recipe):
ingredients_sets = IngredientSet.objects.filter(recipe=cod_recipe)
ingredients_to_template = []
for ingredient_set in ingredients_sets:
ingredient_obj = Ingredient.objects.get(id=ingredient_set.id)
dict_of_ingredient = {
"name": ingredient_obj.name,
"quantity": ingredient_set.quantity
}
ingredients_to_template.append(dict_of_ingredient)
return render(request, 'main/ingredients.html', {"ingredients": ingredients_to_template})
where main is the name of the app
recipes.html
<table>
<thead>
<th>Recipe</th>
</thead>
<tbody>
{% for recipe in recipes %}
<tr>
<td>
{{recipe.id}}
</td>
</tr>
{% endfor %}
</tbody>
</table>
ingredients.html
{% for ingredient in ingredients %}
{{ingredient.name}}
{{ingredient.quantity}}
{% endfor %}
urls.py
from django.urls import path
from . import views
app_name = "main"
urlpatterns = [
path('recipe/', views.recipes, name='recipes'),
path('recipe/<int:cod_recipe>/', views.ingredients, name='ingredients'),
]
I think this is it, any doubts i will be glad to answer.

How to pass multiple values from models.py to HTML via views.py in Django

I have a following models.py for my Django blog, I made a following views.py to pass the value of the slug for my URL parameter.
However I am struggling to create a model in views to get other data(person & description) from Category class.
I have tried some patterns by myself but can not pass them to HTML. (always Error or not showing)
Can you please give me some idea of how to solve this.
models.py
class Category(models.Model):
person = models.CharField(max_length=20)
description = models.TextField()
slug = models.SlugField()
def __str__(self):
return self.person
views.py
def blog_category(request, category):
posts = Post.objects.filter(categories__slug__contains=category).order_by("-created_on").distinct()
context = {"category": category, "posts": posts}
return render(request, "blog_category.html", context)
HTML(Localhost:8000/slug)
{{ person }}
{{ description }}
this is full code of my models.py
class Category(models.Model):
person = models.CharField(max_length=20)
description = models.TextField()
slug = models.SlugField()
def __str__(self):
return self.person
class Recommender(models.Model):
recommender_name = models.CharField(max_length=20)
slug = models.SlugField()
def __str__(self):
return self.recommender_name
class Post(models.Model):
book_title = models.CharField(max_length=255)
author = models.CharField(max_length=255)
book_link = models.CharField(max_length=255)
recommenders = models.ForeignKey("Recommender", on_delete=models.CASCADE,)
source = models.TextField()
source_link = models.CharField(max_length=255)
created_on = models.DateTimeField(auto_now_add=True)
last_modified = models.DateTimeField(auto_now=True)
categories = models.ManyToManyField("Category", related_name="posts")
slug = models.SlugField()
def __str__(self):
return self.book_title
posts = Post.objects.filter(categories__slug__contains=category).order_by("-created_on").distinct()
Is going to return a queryset. It can have more than one instance of the model class (since you are using filter). In your context you are sending this queryset as posts to your templates.
So in your HTML you can use something like this. You need to use a for loop since there can be more than one item in posts.
{% for post in posts %}
{% for category in post.categories.all %}
{{ category.person }}
{{ category.description }}
{% endfor %}
{% endfor %}
I would look at this example.
Namely, if you render the template like it is shown in the example, you should be able to do
{{ category.person }} {{ category.description }}

Django many-to-many

class Actor(models.Model):
name = models.CharField(max_length=50)
def __str__(self):
return self.name
class Movie(models.Model):
title = models.CharField(max_length=50)
actors = models.ManyToManyField(Actor)
def __str__(self):
return self.title
how can I access to the movies of an actor from Actor object in a template ?
I need to do it in both directions.
This worked from movies to actors.
{{movie.actors.all}}
just put related_name into actors field
actors = models.ManyToManyField(Actor, related_name="actor_movies")
and then in template:
{{ actor.actor_movies.all }}
or if you dont want related_name:
template:
{{ actor.movie_set.all }}

How can I display content in a model object in template?

How can I display country, and city of an UserType1 object in template?
class UserType1(models.Model):
user=models.OneToOneField(User,parent_link=True,primary_key=True)
country = models.CharField(max_length=50)
city = models.CharField(max_length=50)
def __str__(self):
return str(self.user)
def get_country(self):
return self.country
def get_city(self):
return self.city
I have the below in views.py
def profile(request,userid):
basic_info = User.objects.get(pk=int(userid))
profile = UserType1.objects.filter(user=int(userid))
template_name = 'users/profile.html'
return render(request, template_name, {'userid':userid,'basic_info':basic_info, 'profile':profile})
and the following in template
{% if profile %}
{{ profile.get_city }}
{{ profile.city }}
{% endif %}
Neither worked. Thanks!
It looks like you are accessing properties on a queryset, rather than a model instance, as you haven't called get on UserType1.
Try:
profile = UserType1.objects.get(user=int(userid))
As an aside though, a small change would simplify your code a little:
user = models.OneToOneField(User, parent_link=True, primary_key=True, related_name='profile')
...
basic_info = User.objects.get(pk=int(userid))
profile = basic_info.profile

I can't display detail_page with absolute_url?

When I got this error I understood that I didn't learn URL -HTML- views-model relationship. First, let me show my codes.
This is my views.py:
def category_detail(request, category_name):
links = Link.objects.filter(category__name=category_name)
return render_to_response("category_detail.html", {"links":links}, context_instance=RequestContext(request))
This is models.py:
class Category(models.Model):
name = models.CharField(_("Category"), max_length=255)
user = models.ManyToManyField(User)
def __unicode__(self):
return "%s %s" %(self.user, self.name)
def admin_names(self):
return ', '.join([a.username for a in self.user.all()])
admin_names.short_description = "User Names"
def get_absolute_url(self):
return "/category/%s" % self.name
class Link(models.Model):
user = models.ForeignKey(User)
posted_at = models.DateTimeField(auto_now_add=True)
url = models.URLField()
title = models.CharField(max_length=255, null=True, blank=True)
category = models.ForeignKey(Category)
def __unicode__(self):
return "%s %s %s" %(self.url, self.title, self.category)
This is HTML page:
<div id="profilemenu">
index<p>
{% for category in categories %}
<p>{{category.name }}
{% endfor %}
<p>
</div>
and urls.py:
url(r'^category/(?P<category_name>.*)', 'link.views.category_detail', name="category_detail"),
When I click a category name to open category_detail.html, the URL in browser is like :
http://127.0.0.1:8000/category`/
I can't get categoryname. Please can you tell me my stupid mistake? :\ Thanks for time.
If you are using the namespace in your urls you would need to reference it without quotes in the template.
<p>{{category.name }}
Note: You'll want to ensure the namespace is fully qualified. If you have embedded namespaces you should separate them with :.
<p>{{category.name }}
Hopefully this solves your problem.
You should follow get_absolute_url reference:
def get_absolute_url(self):
from django.core.urlresolvers import reverse
return reverse('link.views.category_detail', args=[str(self.name)])
html
{{ category.name }}

Categories

Resources