I've two models. One is
class Pin(models.Model):
title = models.CharField(max_length=255)
def __str__(self):
return self.title
another is
class Content(models.Model):
pin = models.ForeignKey(Pin, on_delete = models.CASCADE)
content_type = models.CharField(max_length=2)
content = models.TextField()
I want show the list of Pin's if the Pin's title or Content's content contains the search query.
For a single Pin there can be multiple Content, and I want to show the list of Pins if the title of Pin or the content of a Content match.
I can generate result if the Pin's title contains the query. Anyone can help me?
General syntax of filtering is :
<ModelName>.objects.filter(
Q(<ForeignKeyField>__<field_name>__<filter_method>=<query>) |
Q(<field_name>__<filter_method>=<query>)
)
`|' here is OR operator
distinct() is used so that the identical querysets are again filtered in resulting queryset.
def get_pin_list(request, q):
pins = []
if q:
querysets = Content.objects.filter(Q(pin__title__icontains=q) |
Q(content__icontains=q)
).distinct('pin')
pins = [queryset.pin for queryset in querysets]
return render(request, 'some_page.html', {'pins': pins})
In case if it doesn't works for MySQL:
def get_pin_list(request, q):
pins = []
if q:
querysets = Content.objects.filter(Q(pin__title__icontains=q) |
Q(content__icontains=q)
).distinct()
pins = [queryset.pin for queryset in querysets]
pins = list(set(pins))
return render(request, 'some_page.html', {'pins': pins})
Try this way.
from django.db.models import Q
query = request.GET.get("q")
if query:
queryset_list = Content.objects.filter(
Q(pin__title__icontains=query)|
Q(content_type__icontains=query)|
Q(content__icontains=query)
).distinct()
Related
so,i have a List of all mobile phones whose brand name is one of the incoming brands. The desired brand names will be entered. The number of entries is unknown and may be empty. If the input is empty, the list of all mobile phones must be returned.
model:
from django.db import models
class Brand(models.Model):
name = models.CharField(max_length=32)
nationality = models.CharField(max_length=32)
def __str__(self):
return self.name
class Mobile(models.Model):
brand = models.ForeignKey(Brand, on_delete=models.CASCADE)
model = models.CharField(max_length=32, default='9T Pro', unique=True)
price = models.PositiveIntegerField(default=2097152)
color = models.CharField(max_length=16, default='Black')
display_size = models.SmallIntegerField(default=4)
is_available = models.BooleanField(default=True)
made_in = models.CharField(max_length=20, default='China')
def __str__(self):
return '{} {}'.format(self.brand.name, self.model)
query:
from django.db.models import F, Q
def some_brand_mobiles(*brand_names):
query = Mobile.objects.filter(Q(brand__name__in=brand_names) | ~Q(brand__name=[]))
return query
If the input is empty, the list of all mobile phones will be returned, but i cant use *brand_names to return the list.
for example
query = Mobile.objects.filter(Q(brand_name_in=['Apple', 'Xiaomi']))
return query
and
query = Mobile.objects.filter(~Q(brand__name=[]))
return query
Both of these conditions work by example alone, but it does not check both conditions with the function I wrote.
how to fix it ?
It is simpler to just check the list of brand_names and filter if it contains at least one element:
def some_brand_mobiles(*brand_names):
if brand_names:
return Mobile.objects.filter(brand__name__in=brand_names)
else:
return Mobile.objects.all()
Try this solution:
def some_brand_mobiles(*brand_names):
queryset = Mobile.objects.all()
if brand_names:
queryset = queryset.filter(brand__name__in=brand_names)
return queryset
In that way you can add more filters based on any other condition over the queryset.
Here is my models code:
class Quote(models.Model):
"""Quote model."""
quote_text = models.TextField(unique=True)
author = models.ForeignKey(Author)
topic = models.ForeignKey(Topic)
tags = models.ManyToManyField(Tag)
language = models.ForeignKey(Language)
hit = models.IntegerField(default=0)
published = models.BooleanField(default=False)
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
I want filter all Quote based on characters length, and this is my query in django admin.
class QuoteCountFilter(admin.SimpleListFilter):
"""Filter based on quote_text characters count."""
title = _('Quote Text Char Count')
parameter_name = 'quotelength'
def lookups(self, request, model_admin):
return (
('lessthan50', _('Less than 50')),
('morethan50', _('More than 50')),
)
def queryset(self, request, queryset):
if self.value() == 'lessthan50':
return queryset.extra(select={"val": "SELECT id FROM web_quote WHERE character_length(quote_text) < 50"})
However, it returns Programming error more than one row returned by a subquery used as an expression
Any ideas how to fix?
What I am trying is to find all Quotes where quote_text length is less than 50 characters
Say goodbye to extra and say hello to Length
from django.db.models.functions import Length
queryset.annotate(len=Length('quote_text').filter(len__lt=50)
much neater, safer and shorter
I'm currently trying to find a way to do something with Django's (v1.10) ORM that I feel should be possible but I'm struggling to understand how to apply the documented methods to solve my problem.
Edit: So here's the sql that I've hacked together to return the data that I'd like from the dbshell, with a postgresql database now, after I realised that my original sqlite3 backed sql query was incorrect:
select
voting_bill.*,vv.vote
from
voting_bill
left join
(select
voting_votes.vote,voting_votes.bill_id
from
voting_bill
left join
voting_votes
on
voting_bill.id=voting_votes.bill_id
where
voting_votes.voter_id = (select id from auth_user where username='richard' or username is Null)
)
as
vv
on
voting_bill.id=vv.bill_id;
Here's the 'models.py' for my voting app:
from django.db import models
from django.contrib.auth.models import User
class Bill(models.Model):
name = models.CharField(max_length=255)
description = models.TextField()
result = models.BooleanField()
status = models.BooleanField(default=False)
def __str__(self):
return self.name
class Votes(models.Model):
vote = models.NullBooleanField()
bill = models.ForeignKey(Bill, related_name='bill',
on_delete=models.CASCADE,)
voter = models.ForeignKey(User, on_delete=models.CASCADE,)
def __str__(self):
return '{0} {1}'.format(self.bill, self.voter)
I can see that my sql works as I expect with the vote tacked onto the end, or a null if the user hasn't voted yet.
I was working to have the queryset in this format so that I can iterate over it in the template to produce a table and if the result is null I can instead provide a link which takes the user to another view.
I've read about select_related and prefetch_related, but as I said, I'm struggling to work out how I translate this to how I can do this in SQL.
Hope I correctly understood your problem. Try this:
votes = Votes.objects.filter(voter__username='django').select_related('bill')
You can use this. But I think you do not need select_related in this case.
bills_for_user = Bill.objects.filter(votes__voter__username='django').select_related('votes').distinct()
Now you can iterate your bills_for_user
for bill in bills_for_user:
bill_name = bill.name
bill_description = bill.description
bill_result = bill.result
bill_status = bill.status
# and there are several variants what you can with votes
bill_votes = bill.votes_set.all() # will return you all votes for this bill
bill_first_vote1 = bill.votes_set.first() # will return first element in this query or None if its empty
bill_first_vote2 = bill.votes_set.all()[0] # will return first element in this query or Error if its empty
bill_last_vote = bill.votes_set.last()[0] # will return last element in this query or None if its empty
# you can also filter it for example by voting
bill_positive_votes = bill.votes_set.filter(vote=True) # will return you all votes for this bill with 'vote' = True
bill_negative_votes = bill.votes_set.filter(vote=False) # will return you all votes for this bill with 'vote' = False
bill_neutral_votes = bill.votes_set.filter(vote=None) # will return you all votes for this bill with 'vote' = None
My model
class Article(models.Model) :
title = models.CharField(max_length = 100)
category = models.CharField(max_length = 50, blank = True)
date_time = models.DateTimeField(auto_now_add = True)
content = models.TextField(blank = True, null = True)
def __unicode__(self) :
return self.title
class Meta:
ordering = ['-date_time']
How to make a list contain all category and without repeat?
using the syntax just like:
post_list = Article.objects.filter(category__iexact = tag)
You can use values_list to extract all values of a particular field.
category_list = Article.objects.values_list('category', flat=True)
To remove duplicates from the list:
categories = list(set(category_list))
or as #Iain pointed out, you can use .distinct()
category_list = Article.objects.values_list('category', flat=True).distinct()
The feature you are looking for is distinct. Since it filter in the database layer, it should be faster than filter in Python code
post_list = Article.objects.filter(category__iexact = tag).distinct()
For all categories for which at least one article exists, you can do:
Category.objects.filter(article_set__isnull=False).distinct()
This will also give you a QuerySet which you can use for further queries unlike a list.
I have a problem about filter in django. Please help me. I want to display the objects of the product which has different categories when I click on l.category_name
my html (CategoryList.html):
{% for l in forms %}
<h2>{{ l.category_name }}</h2>
{% endfor %}
CategoryView.html
{{get_product.product_name}}
my model:
class Category(models.Model):
category_id = models.AutoField(primary_key = True)
category_name = models.CharField(max_length = 20)
def __unicode__(self):
return self.category_name
class Product(models.Model):
product_id = models.AutoField(primary_key = True)
product_name = models.CharField(max_length = 50)
product_category = models.ForeignKey(Category)
product_color = models.CharField(max_length = 30)
def __unicode__(self):
return self.product_name
my view:
def category_list(request):
list = Category.objects.all()
context = {'forms':list}
return render(request,'webpage/CategoryList.html',context)
def category_view(request,category_id):
all = Product.objects.all()
if request.POST:
get_id = Category.objects.get(category_id = request.POST['category_id'])
get_category = Product.objects.get(product_category =
request.POST['product_category'])
get_category.product_category = get_id
get_category.save()
if get_category:
get_product = Product.objects.filter(product_category__category_name =
request.POST['category_name'])
context = {'get_product':get_product}
return render(request,'webpage/CategoryView.html',context)
I read document in https://docs.djangoproject.com/en/1.6/topics/db/queries/ but i don't understand .I know i was wrong category_view
There seem to be a lot of problems with your code.
First, you don't have to declare ids in your code. Django does that automatically for you. So, categor_id and product_id are unnecessary.
Second,
Remove the .POST check. You aren't posting anything.
Third,
get_id = Category.objects.get(category_id = request.POST['category_id']) # returns a category, not an id
get_category = Product.objects.get(product_category =
request.POST['product_category']) # returns the product list, not a category
get_category.product_category = get_id
is the same as
category = Category.objects.get(category_id = request.POST['category_id'])
product_list = Product.objects.get(product_category = category)
Fourth, don't hardcode URLs in your template. Use the {% url %} tag instead.
Finally,
You can then pass this product_list to the template
context = {'product_list':product_list}
return render(request,'webpage/CategoryView.html',context)
The way foreign keys are stored is through automatic fields(IDs). Since 'Category' is a foreign field of 'Product', when you make a record entry, the id of category is stored in 'product_category' field in products table.
I think your code is a little confusing since you are trying to do somethings django does automatically for you. Like, once you define a foreign key, the id of the foreign key table record is stored automatically, you don't have to get the id of 'category' entry and store it in products table entry.
What you are trying to achieve is simple, lets say you have the category_name and nothing else, get the id of the category table entry,
category_object = Category.objects.get(category_name = category_name)
category_id = category_object .id
If you already have the ID of category, then you can skip the above step, and simply use the ID to query the products table to get the needed records
Product.objects.filter(product_category = category_id)
In your templates, you can iterate through these product records and display whatever is needed.
BTW, use the .update() method to update any fields instead of save() method.
Something like this:
Entry.objects.all().update(blog=b)
It will be well worth your time reading through the queries help.
Django queries