Filter on many-to-one model - python

I want to be able assign users vehicle registrations, and when the user logs into the website their home page should have a list of vehicle regs they own.
However I cannot get the model class to filter on the foreign key.
views.py
#login_required
def home(request):
# This is the basic user landing Page
veh_list = Vehicle.objects.filter(UserProfile.user)
return render(request, 'portal/home.html', {"veh_list": veh_list})
model.py
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class UserProfile(models.Model):
# This line is required. Links UserProfile to a User model instance.
user = models.OneToOneField(User)
# The additional attributes we wish to include.
compName = models.CharField(max_length = 20)
milkco = models.IntegerField()
# Override the __unicode__() method to return out something meaningful!
def __unicode__(self):
return self.user.username
class Vehicle(models.Model):
vehid = models.CharField(max_length = 10)
company = models.ForeignKey(UserProfile, default = 1)
class Meta:
db_table = "vehicle"
def __unicode__(self):
return self.vehid
home.html
<!DOCTYPE html>
{% extends 'portal/base.html' %}
{% block title %}{{user.first_name }} {{ user.last_name }} Portal{% endblock %}
{% block content %}
<p>This is the home Page</p>
{% if user.is_authenticated %}
<h4>Optiload says... hello {{ user.first_name }} {{ user.last_name }}!</h4>
{% endif %}
{% for veh in veh_list %}
{{ veh}}
{% endfor %}
{% if user.is_authenticated %}
Logout<br/>
{% endif %}
{% endblock %}
Could someone help me with where I'm going wrong?
Thanks

Django offers a powerful and intuitive way to “follow” relationships in lookups, taking care of the SQL JOINs for you automatically, behind the scenes. To span a relationship, just use the field name of related fields across models, separated by double underscores, until you get to the field you want.
So your query should look like
veh_list = Vehicle.objects.filter(company__user=request.user)
Reference

You cannot make queries with unnamed arguments:
Vehicle.objects.filter(UserProfile.user)
In this case you want:
Vehicle.objects.filter(company=[your user])

Related

How do I iterate ManyToMany field in Django template tag?

I have an object that contains a Many-to-Many field. I'm trying to iterate this field in Django template, but apparently I can't. Let me show you the code first.
models.py:
class Book(models.Model):
title = models.CharField(max_length = 100, blank=True)
category = models.ManyToManyField(Category)
def __str__(self):
return self.title
views.py:
def book_list(request):
books = Book.objects.all().order_by('-pk')
context = {
'books' : books,
}
return render(request, 'contents/book_list.html', context)
Template file:
{% for b in books %}
<div>
{{b.title}}
{% for cat in b.category %}
{{cat}}
{% endfor %}
</div>
{% endfor %}
Now I get 'ManyRelatedManager' object is not iterable error. How do I iterate the field and show all the category in each object?
It's because if you call b.category it returns only the relation object. To get its values (category objects) you have to add .all. Like this:
{% for b in books %}
<div>
{{ b.title }}
{% for cat in b.category.all %}
{{cat}}
{% endfor %}
</div>
{% endfor %}
By the way, I've also changed c.title to b.title, because I assume you want this book title, not something from global.

Django: How to query based on a ForiegnKey and display related data for each ForeignKey?

I am brand new to Django and to programming and I'm trying to make a page that will display the Workout with all the associated Exercises listed under each work out.
For example:
Chest
Chest Press
Incline Press
Flat Flyes
Shoulders
Shoudler Press
Arnold Press
Back/Legs
Wide Grip Pull Up
Neutral Grip Pull Up
Bent Over Row
Here is my code:
models.py
class Workout(models.Model):
title = models.CharField(max_length=100)
def __str__(self):
return self.title
class Exercise(models.Model):
workout = models.ForeignKey(Workout, on_delete=models.CASCADE, related_name='workouts')
title = models.CharField(max_length=100)
weight = models.DecimalField(decimal_places=0, max_digits=10000)
date_posted = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.title
views.py
def home(request):
context = {
'workouts': Workout.objects.all()
}
return render(request, 'workouts/home.html', context)
def workout(request):
context = {
'workouts': Workout.objects.all(),
'exercises': Exercise.objects.all()
}
return render(request, 'workouts/workout.html', context)
workout.html
{% extends 'workouts/base.html' %}
{% block content %}
{% for workout in workouts %}
<h1>{{ workout.title }}</h1>
{% for exercise in exercises %}
<h3>{{ exercise.title }}</h3>
<p>{{ exercise.weight }}</p>
{% endfor %}
{% endfor %}
{% endblock content %}
In my view.py I have it set to Exercise.objects.all() which just displays all of the exercises under each Workout title, I can figure out how to get only the exercises that are associated with the Workout.
Like I said I am brand new to all of this and I'd appreciate any help! Thanks!
You can define property to Workout model to retrieve exercises related to the instance. Just add a new method with property decorator to retrieve Exercises related with that Workout.
class Workout(models.Model):
title = models.CharField(max_length=100)
def __str__(self):
return self.title
#property
def exercises(self):
return self.workouts.all()
Then you can use exercises in your html file like:
{% extends 'workouts/base.html' %}
{% block content %}
{% for workout in workouts %}
<h1>{{ workout.title }}</h1>
{% for exercise in workout.exercises %}
<h3>{{ exercise.title }}</h3>
<p>{{ exercise.weight }}</p>
{% endfor %}
{% endfor %}
{% endblock content %}
Another approach may be grouping Exercises with workouts in your view and pass them to template. For more information, you can check regroup
When you define FK relationship between two models, Django adds a manager to target model to query related objects. When you use this manager, you basicly run a query something like Exercise.objects.filter(workout_id=workout_instance_id). This is a queryset, so you can join with features of queryset features like filter, first and extra. You can use a plenty of queryset features on related objects. This is basicly the power of Django ORM mechanism. You can find a bit more in documentation if you need to.

How to order by a field from the `through` table for a M2M relationship in Django?

I have two models — Note and Pinboard — with a many to many relationship in a Django app. Those two models are related trough another model — Pin — so I can store additional information about the relationship.
I want to show the related Note instances in the DetailView for Pinboard. That's not the problem. But I want to prefetch the notes and also order them on the position field from the through table.
Any hints on how to archive this (prefetch + ordering on third table)?
Example
This is what I have so far… it works in the sense, that I don't have to query for each entry, but I found no way to order the Note instances by their position without more queries for each instance.
Models
from django.db import models
class Note(models.Model):
title = models.CharField(max_lenght=200)
content = models.TextField()
class Pinboard(models.Model):
title = models.CharField(max_lenght=200)
notes = models.ManyToManyField(
Note, blank=True, related_name='pinboards', through='Pin'
)
class Pin(models.Model):
class Meta:
ordering = ['position', ]
get_latest_by = 'position'
pinboard = models.ForeignKey(Pinboard, related_name='note_pins')
note = models.ForeignKey(Note, related_name='pinboard_pins')
position = models.PositiveSmallIntegerField(default=0)
View
from django.views.generic import DetailView
class PinboardDetailView(DetailView):
model = Pinboard
queryset = Pinboard.objects.prefetch_related('notes')
Template
{% extends 'base.html' %}
{% block content %}
<h1>{{ pinboard.title }}</h1>
{% if pinboard.notes.all.exists %}
<ol>
{% for note in pinboard.notes %}
<li>{{ note.title }}</li>
{% endfor %}
</ol>
{% else %}
<p>Nothing here yet…</p>
{% endif %}
{% endblock content %}
I suggest you use a Prefetch object.
class PinboardDetailView(DetailView):
model = Pinboard
queryset = Pinboard.objects.prefetch_related(
Prefetch(
'notes',
Note.objects.order_by('pinboard_pins__position'),
)
)
By the way, you don't need to use prefetch_related at all on a DetailView as it will result in the same number of queries.
Plus, since you're already fetching the pinboard.notes I suggest you use {% if pinboard.notes.all %} instead of {% if pinboard.notes.all.exists %}.

Showing one-to-many relationship in Django views

I am making a django blog and want to show a list of comments for each blog post, but I have trouble figuring out how to reference the comments in the views and the templates.
My models are defined like this:
class Issue(models.Model):
title = models.CharField(max_length=255)
text = models.TextField()
author = models.ForeignKey(User)
def __unicode__(self):
return self.title
class Comment(models.Model):
commenter = models.ForeignKey(User)
issue = models.ForeignKey(Issue)
text = models.TextField()
and my views like this
class IssueDetail(DetailView):
model = Issue
context_object_name = "issue"
template_name = "issue_detail.html"
def get_context_data(self, **kwargs):
context = super(IssueDetail, self).get_context_data(**kwargs)
context['comments'] = Comment.objects.all()
return context
class CommentDetail(DetailView):
model = Comment
context_object_name = "comment"
template_name = "comment_detail.html"
and finally the issue_detail.html template
{% block content %}
<h2>{{ issue.title }}</h2>
<br/>
<i>As written by {{ issue.author.first_name }}</i>
<br/><br/>
<blockquote> {{ issue.text }}</blockquote>
<h3>Comments</h3>
{% for comment in comments %}
<li>{{comment}}</li>
{% endfor %}
{% endblock %}
This allows me to reference the fields of the comment inside the Issue template, but basically then I want the comments to have a template of their own that will be rendered inside the for loop. What is the correct way to do this in Django?
The comments are already available in your template because of the model relationship you defined. You can delete the get_context_data in IssueDetail.
Your issue_detail.html template could look like this:
{% for comment in issue.comment_set.all %}
{% include 'comment_detail.html' %}
{% endfor %}
Your comment_detail.html template could look like this:
<ul>
<li>{{ comment.issue }}</li>
<li>{{ comment.text }}</li>
</ul>
what if this we were using a different model
product = models.ForeignKey(Customer)
how would we do the CRUD opertions from the templates an the views.py

Django foreignkey relationships in templates

I've seen some examples of how to do this on SO but none of them have guided me towards the glory I so desire.
Here are the fields I'm working with:
models.py
class ServerFunctions(models.Model):
server_function = models.CharField(max_length=12)
class Meta:
verbose_name_plural = "Server Function"
def __unicode__(self):
return self.server_function
class Inventory(models.Model):
server_function = models.ForeignKey(ServerFunctions, null=False, blank=False)
views.py
def show_details(request, host_id=1):
host_info = Inventory.objects.filter(id=host_id).values()
return render_to_response('templates/details.html', {'host_info': host_info})
templates/details.html
This gives me the column value from the Inventory table (3) like it should
{{ info.server_function_id }}
This gives me no output at all.
{% for func in info.serverfunctions_set.all %}
{{ func.server_function }}
{% endfor %}
I'm stuck, nothing I've tried seems to work. Thanks for reading.
You are using info.serverfunction_set.all in your template which would be correct if you were traversing a reverse relationship (i.e. you had a ServerFunction and wanted all the related Inventory items). But you aren't, you have a simple forward relationship between Inventory and a ServerFunction:
{% for info in host_info %}
{{ func.server_function.server_function }}
{% endfor %}

Categories

Resources