I have two models with One-to-Many relationship; Listing, and Bids.
Is it possible to retrieve and display a list of Bid objects' bid_price in Listing's str method?
The code provided below crashes the server and I am not sure of the correct keywords to search for.
I understand how listing.bid_set works in the Shell or view, but I am not sure how to make it work here.
class Listing(models.Model):
title = models.CharField(max_length=64)
def __str__(self):
bid_objects = Bid.objects.all().filter(listing__id=self.id)
price_list = []
for bid_object in bid_objects:
price_list.append(bid_object.bid_price)
return f"{self.title}, {price_list}"
class Bid(models.Model):
listing = models.ForeignKey(Listing, on_delete=models.CASCADE, related_name="listing_bids")
bid_price = models.DecimalField(max_digits=6, decimal_places=2)
Thanks for your help.
Since you specified related_name='listing_bids', it means you access the related Bids with self.listing_bids:
class Listing(models.Model):
title = models.CharField(max_length=64)
def __str__(self):
bid_objects = self.listing_bids.values_list('bid_price', flat=True)
return f'{self.title}, {bid_objects}'
Related
I am building a Blog App and I am trying to sort or order_by in list which contains multiple queries.
models.py
class BlogPost(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=30)
date = models.DateTimeField(auto_now_add=True)
class Comments(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
blog_of = models.ForeignKey(BlogPost, on_delete=models.CASCADE)
body = models.CharField(max_length=30, default='')
date_added = models.DateTimeField(auto_now_add=True)
views.py
def mypage(request):
query_1 = list(BlogPost.objects.filter(user=request.user).order_by('-date'))
query_2 = list(Comment.objects.filter(user=request.user).order_by('date_added'))
results = sorted(chain(query_1, query_2),key=attrgetter('date') , reverse=True)
context = {'results':results}
return render(reques, 'mypage.html', context)
But is showing
'Comment' object has no attribute 'date'
And I think this is because date field name is different in both model and i am sorting with only one, But i have no idea how can I sort with different field name.
Any help would be much Appreciated. Thank You
Or just add it as a property:
class Comments(models.Model): # do NOT give a model a plural name!
# ....
#property
def date(self):
return self.date_added
# or if it is a datetimefield
# return self.date_added.date()
ALso you can just write a more customized sorting key (e.g. in case the involved models are from third-party apps).
def order(obj):
try:
return obj.date
except AttributeError:
return obj.date_added
# ...
results = sorted(chain(query_1, query_2), key=order, reverse=True)
This question is in relation to project 2 of the cs50 course which can be found here
I have looked at the following documentation:
Django queryset API ref
Django making queries
Plus, I have also taken a look at the aggregate and annotate things.
I've created the table in the template file, which is pretty straight forward I think. The missing column is what I'm trying to fill. Image below
These are the models that I have created
class User(AbstractUser):
pass
class Category(models.Model):
category = models.CharField(max_length=50)
def __str__(self):
return self.category
class Listing(models.Model):
owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
title = models.CharField(max_length=200)
description = models.TextField()
initial_bid = models.IntegerField()
category = models.ForeignKey(Category, on_delete=models.CASCADE)
date_created = models.DateField(auto_now=True)
def __str__(self):
return self.title
class Bid(models.Model):
whoDidBid = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
list_item = models.ForeignKey(Listing, default=0, on_delete=models.CASCADE)
bid = models.IntegerField()
category = models.ForeignKey(Category, on_delete=models.CASCADE)
date = models.DateTimeField(auto_now=True)
def __str__(self):
return_string = '{0.whoDidBid} {0.list_item} {0.bid}'
return return_string.format(self)
This is the closest I could come to after a very long time. But the result I get is just the number 2. Ref image below
Listing.objects.filter(title='Cabinet').aggregate(Max('bid'))
Where 'Cabinet' is a Listing object that I have created. And placed two bids on them.
So the question is, how do I get the Maximum bid value(i.e. 110 for this case) for a particular listing? Using the orm. I think if I used a raw sql query, I could build a dict, send it to the template with the queryset. Then while looping through the queryset, get the value for the key, where the key is the name of the listing or something along those lines. Nah, I would like to know how to do this through the ORM please.
Here's answer #1
Bid.objects.filter(list_item__title='Cabinet').prefetch_related('list_item').aggregate(Max('bid'))
What happens when you try this (sorry, I don't have any objects like this to test on):
Bid.objects.values(list_item__title).prefetch_related('list_item').annotate(Max('bid'))
Hello guys I have one query in my Django project.
First of all, You can see that I have two Django models named BookSeller and Book
Bookseller model
class BookSeller(models.Model):
user_name = models.CharField(max_length=200)
user_email = models.CharField(max_length=200)
user_password = models.CharField(max_length=200)
user_phone = models.CharField(max_length=100)
user_photo = models.ImageField(upload_to='book/seller_photos/%Y/%m/%d/', blank=True)
user_address = models.CharField(max_length=300)
user_state = models.CharField(max_length=100)
user_city = models.CharField(max_length=100)
def __str__(self):
return self.user_name
Book Model
class Book(models.Model):
book_owner = models.ForeignKey(BookSeller, related_name='book_seller', on_delete=models.CASCADE)
book_category = models.CharField(max_length=200)
book_title = models.CharField(max_length=200)
book_price = models.IntegerField()
book_edition = models.CharField(max_length=200)
book_author = models.CharField(max_length=200)
book_old = models.IntegerField()
book_page = models.IntegerField()
book_description = models.TextField(max_length=200)
book_image_1 = models.ImageField(upload_to='book/book_photos/%Y/%m/%d', blank=True)
book_image_2 = models.ImageField(upload_to='book/book_photos/%Y/%m/%d', blank=True)
book_image_3 = models.ImageField(upload_to='book/book_photos/%Y/%m/%d', blank=True)
book_image_4 = models.ImageField(upload_to='book/book_photos/%Y/%m/%d', blank=True)
def __str__(self):
return self.book_title
Want to DO: In my project I want to find books by that book seller's city.
For example, if I write city name 'Silicon Valley' in my search field then it should show me all "Books" that's Sellers(BookSeller) belonging to Silicon Valley.
Query: So my query is how can I do that Django Query set, because I can't find out any query which can do this task.
If you guys have any other solution then please suggest me!!!
For finding the books by some book seller's city you can simly filter the Book instances like so:
Book.objects.filter(book_owner__user_city="Silicon Valley")
One other problem I noticed is that I think you misunderstand related_name attribute in ForeignKey.
The related_name attribute specifies the name of the reverse relation from the BookSeller model back to Book model.
If you don't specify a related_name, Django automatically creates one using the name of your model with the suffix _set.
For instance more appropriate related name in your FK would be books, and without defining it would default to book_set.
book_owner = models.ForeignKey(BookSeller, related_name='books', on_delete=models.CASCADE)
Here is an example, lets assume you have 1 instance of BookSeller and 2 isntances of Book with FK to that instance of BookSeller.
my_book_seller = BookSeller(...)
my_book_1 = Book(book_owner=my_book_seller, ...)
my_book_2 = Book(book_owner=my_book_seller, ...)
Now in your case doing the my_book_seller.book_seller.all() (since you defined the related_name to be book_seller) would return you the two Book instances belonging to my_book_seller. This doesn't make much sense.
On the other hand having the related_name='books' you would get the same books by doing my_book_seller.books.all().
You can find more info in docs.
You can do that like this
Book.objects.filter(book_owner__user_city="Silicon Valley")
and you learn more about various kinds of joining at
this link
You can get the desired results doing something like
books_by_seller_city = Book.objects.filter(book_owner__user_city='Silicon Valley')
Note the use of __ which tells the ORM to look at the referenced model attribute.
You can do with q look ups also, in that case you can add more fields in your query.
queryset = Book.objects.filter(Q(book_owner__user_city__icontains=query)|
.................)
the code did not return all of the item's name based on employee..? how to solve this probem? did the models wrong? or the query?
MODELS.PY
class Employee(models.Model):
name = models.CharField(max_length=100)
telephone_number = models.CharField(max_length=20)
address = models.TextField()
email = models.EmailField()
class Item(models.Model):
code = models.CharField(max_length=4)
name = models.CharField(max_length=100)
kind = models.CharField(max_length=100)
description = models.TextField()
class Inventory(models.Model):
employee = models.ForeignKey(Employee, on_delete=models.CASCADE)
item = models.ForeignKey(Item, on_delete=models.CASCADE)
def get_absolute_url(self):
return reverse('inventaris-detail', kwargs={'pk': self.pk})
VIEWS.PY
how can i get all of the employee's item ?
query_set = Inventory.objects.all()
for query in query_set:
output.append([
query.employee.name,
query.item.name
])
i need something like query.employee.items_set.all() .. ?
You want to get all of the items from an employee? The following should achieve that:
employee = Employee.objects.all()[0] # Just get a random employee, you can do this with more employees too if you want
employees_items = [inventory.item for inventory in employee.inventory_set.all()]
Your code does not logically make a lot of sense though, to be honest. Most likely, there should be a field on a Item class which is a FK to Inventory. Your item class should probably be:
class Item(models.Model):
code = models.CharField(max_length=4)
name = models.CharField(max_length=100)
kind = models.CharField(max_length=100)
description = models.TextField()
inventory = models.ForeignKey(Inventory, on_delete=models.CASCADE)
(Of course this will not work since Inventory is defined after this class, but you can just put Inventory above it or use one of the other many methods to solve this problem)
Good luck!
I have following models:
class EnMovielist(models.Model):
content_ID = models.CharField(max_length=30)
release_date = models.CharField(max_length=30)
running_time = models.CharField(max_length=10)
actress = models.CharField(max_length=300)
series = models.CharField(max_length=30)
studio = models.CharField(max_length=30, null=True)
director = models.CharField(max_length=30)
def __str__(self):
return self.content_ID
class EnActress(models.Model):
name = models.CharField(max_length=100, null=True)
movielist = models.ManyToManyField(EnMovielist, related_name='movies')
def __str__(self):
return self.name
I got error when I try to this in Django shell,
b = EnActress.objects.values_list('name', flat=True)
a = EnMovielist.objects.filter(actress__contains=b).values_list('content_ID')
b.movielist.add(a)
AttributeError: 'QuerySet' object has no attribute 'movielist'
How can I django queryset add into many-to-many field?
I have no idea why this is happening.. Any help appreciated! :)
You should not be using values_list if you intend to add a new relation afterwards. From the docs:
values() and values_list() are both intended as optimizations for
a specific use case: retrieving a subset of data without the
overhead of creating a model instance
[Emphasis mine]
It's hard to tell what you're up to without having a good description of what you want to achieve.
You should call m2m add from instance and adding entity should be also model instance. Otherwise your expression doesn't make sense.
b = EnActress.objects.get(pk=some_pk) # get an instance, not queryset
a = EnMovielist.objects.get(pk=some_pk) # also instance
b.movielist.add(a)