if i have this code
class Father(models.Model):
Description = models.CharField(max_length=50)
Code = models.IntegerField(max_length=2, unique=True)
def __unicode__(self):
return "%s (%s)" % (self.Description, self.Code)
class Son(models.Model):
Father = models.ForeignKey(Father)
Description = models.CharField(max_length=50)
And I want to create a filter by the select box shown to the user.
Assuming that I have a record in Father like:
# | Description | Code
--------------------------
1 | Fred Nichols | 100
In the ForeignKey field should have a HTML content like:
<option value="1">Fred NIchols (100)</option>
if I try to query by the field in the son model:
Son.objects.filter(Father__Contains="Fred")
I get an error. In the documentation of Django the nearest option should be something like:
Son.objects.filter(Father__Description__contains="Fred")
or for any of the columns data
Son.objects.filter(Q(Father__Description__contains="Fred") | Q(Father__Code__Contains="Fred") )
I'd like to make something the most similar to the user info shown.
How could I make a query that could do that?
In single step u could do this :
Son.objects.filter(father__Description__contains="Fred")
you were doing it right the only thing that was wrong is :
the referencing entity Father should be lowercase name of the model
reference
Related
I have models:
class Publisher(Model):
name = TextField()
class Author(Model):
name = TextField()
class Book(Model):
publisher = ForeignKey("Publisher")
author = ForeignKey("Author")
class Magazine(Model):
publisher = ForeignKey("Publisher")
writer = ForeignKey("Author")
I want to know which authors wrote for publishers. My version is this:
from django.db.models import TextField, F, Subquery, OuterRef
from django.contrib.postgres.aggregates import StringAgg # I use postgres
# to lead to the same name
books = Book.objects.annotate(author_name=F("author__name"))
magazines = Magazine.objects.annotate(author_name=F("writer__name"))
books = books.values("publisher_id", "author_name")
magazines = magazines.values("publisher_id", "author_name")
product = books.union(magazines)
# !! here I have a problem with grouping
product = product.group_by(
"publisher_id"
).annonate(
author_names=StringAgg("author_name", ";")
)
publishers = Publisher.objects.all().annotate(
author_names=Subquery(
product.filter(publisher_id=OuterRef("id")).values("author_names")[:1],
output_field=TextField()
)
)
# I was expecting something like
# name | author_names
# ------------------------------------------
# Publisher1 | Author1;Author2;Author3
# Publisher2 | Author2
# Publisher3 | Author2;Author3
The problem is that QuerySet has no .group_by() method, instead the .values() method is suggested (product.values("publisher_id").annonate(...)).
But this is complicated by the fact that I had previously called .values("publisher_id", "author_name") to bring two different models into the same view.
I also tried using .only("publisher_id", "author_name"), but (maybe it's a Django bug) this method can't work together with annotated and normal fields.
Is there any way to fix this problem or some other way to get a list of authors for a publisher?
Perform JOIN on in django fetching related date in reverse relationship.
There are three models.
Following is code for models
class Question(models.Model):
title = models.CharField(max_length=255 )
description = models.TextField(max_length=300)
class Quiz(models.Model):
name = models.CharField(max_length=225,blank=False )
quiz_type =models.IntegerField(choices=QUIZ_TYPE,default=0)
questions = models.ManyToManyField( Question, through='QuestionQuiz', related_name="quiz_question")
categories= models.ManyToManyField(Category,through='CategoryQuiz',related_name='quiz_category')
class QuestionQuiz(models.Model):
quiz = models.ForeignKey(Quiz,on_delete=models.CASCADE)
question = models.ForeignKey(Question,on_delete=models.CASCADE)
correct =models.DecimalField(max_digits=4, decimal_places=3)
incorrect= models.DecimalField(max_digits=4, decimal_places=3)
class Meta:
unique_together = ('quiz','question')
In this the questions are added to the quiz using model Question Quiz.
Here , QuizQuestion has foreign key relationship with the question. I need to fetch all from question JOIN and records from QuestionQuiz with a particular quiz_id.
Suppose quiz_id =3
Then I will fetch all questions with correct and incorrect. if that quiz id is added to the question then it will display correct incorrect else these would be blank.
question_id | title|description|correct|incorrect|quesquizid
1 | Q1 |Q1desc |2 | -2 | 1
2 | Q2 |Q2desc | | |
ques_id =1 added to quiz_id=3 .ques_id=2 not added to quiz_id=3.So, correct incorrect are blank.
I tried following but it fetches all question and related quizes scores irrespective of their occurrence in current quiz :
Question.objects.prefetch_related('questionquiz_set').all()
The result should be similar to following query
Select * from question as qs LEFT JOIN questionquiz as qq on (qq.question_id = qs.id AND qq.id=3)
Please check the result of the query:
I think prefetch_related along with Prefetch may get you the desired result.
q = Question.objects.prefetch_related(
Prefetch('questionquiz_set', queryset=QuestionQuiz.objects.filter(quiz=3))
)
print(q)
This may retrieve all related data along with null if exist.
Here is the db looks like:
id | Post | tag
1 | Post(1) | 'a'
2 | Post(1) | 'b'
3 | Post(2) | 'a'
4 | Post(3) | 'b'
And here is the code of the module
class PostMention(models.Model):
tag = models.CharField(max_length=200)
post = models.ForeignKey(Post,on_delete=models.CASCADE)
Here is the code of search,
def findPostTag(tag):
keywords=tag.split(' ')
keyQs = [Q(tag=x) for x in keywords]
keyQ = keyQs.pop()
for i in keyQs:
keyQ &= i
a = PostMention.objects.filter(keyQ).order_by('-id')
if not a:
a=[]
return a
(this code does not work correctly)
I withdraw the tags and save each as one row in the database. Now I want to make a search function that the user can input more than one keywords at the same time, like 'a b', and it will return 'Post(1)'. I searched for some similar situations, but seems all about searching for multi keywords in one row at the same time, like using Q(tag='a') & Q(tag='b'), it will search for the tag that equals to both 'a' and 'b'(in my view), which is not what I want (and get no result, obviously). So is there any solution to solve this? Thanks.
Is this cases, django provides, ManyToManyField, to work correctly you must to use:
class Tags(models.Model):
tag = models.CharField(unique=True, verbose_name='Tags')
class Post(models.Model): #your model
title = models.CharField(verbosone_name = 'Title')
post_tags = models.ManyToManyField(Tags, verbose_name='Choice your tags')
So you'll choice many tags to your post
this is my model
class pdUser(models.Model):
Name = models.CharField(max_length=200)
Mobile = models.CharField(max_length=200)
PagerDutyID = models.CharField(max_length=200)
PagerDutyPolicyID = models.CharField(max_length=200)
PagerDutyPolicy = models.CharField(max_length=200)
Want i want to be able to do is group by PagerDutyPolicy & PagerDutyPolicyID and return that as an object of its own with unique values only
so for example
Name: bob
PagerDutyPolicyID: 232
PagerDutyPolicy: Team 1
Name: Bill
PagerDutyPolicyID: 232
PagerDutyPolicy: Team 1
Name: Fred
PagerDutyPolicyID: 145
PagerDutyPolicy: Team 2
what i need is an object that has only got
PolicyID: 145
Policy: Team 2
PolicyID: 232
Policy: Team 1
in it, how would i do this?
Thanks
You'll need two models, and a foreign key between them, e.g.:
from django.contrib.auth.models import User
class PagerDutyPolicy(models.Model):
# the model automatically gets an id field
policy_name = models.CharField(max_length=200)
class PagerDuty(models.Model):
# I'm assuming you wanted these to be related to users who can log in..
user = models.ForeignKey(User)
mobile = models.CharField(max_length=200)
policy = models.ForeignKey(PagerDutyPolicy)
To get all policies:
PagerDutyPolicy.objects.all()
To create a new PagerDuty object for bob, butting him in Team 1:
PagerDuty.objects.create(
user=User.objects.get(username='bob'), # or create a new user
mobile='...',
# policy=PagerDutyPolicy.objects.get(policy_name='Team 1') # or..
policy=PagerDutyPolicy.objects.get(id=232)
)
if you're going to look up policies by policy_name that field should also have a db_index=True in the model definition.
something like this:
get all (ID, Team) tuples, make unique
id_teams = pdUser.objects.values_list('id', 'team', flat=True)
id_teams = set(id_teams)
turn into objects
import collections
IDTeam = collections.namedtuple('IDTeam', ['id', 'team'])
output = [IDTeam(id=id, team=team)
for id,team in id_teams]
You can combine values and distinct methods like this:
pdUser.objects.all().values("PagerDutyPolicyID", "PagerDutyPolicy").distinct()
However this will produce fields with PagerDutyPolicyID, PagerDutyPolicy names
In Django, how do I construct a COUNT query for a ManyToManyField?
My models are as follows, and I want to get all the people whose name starts with A and who are the lord or overlord of at least one Place, and order the results by name.
class Manor(models.Model):
lord = models.ManyToManyField(Person, null=True, related_name="lord")
overlord = models.ManyToManyField(Person, null=True, related_name="overlord")
class Person(models.Model):
name = models.CharField(max_length=100)
So my query should look something like this... but how do I construct the third line?
people = Person.objects.filter(
Q(name__istartswith='a'),
Q(lord.count > 0) | Q(overlord.count > 0) # pseudocode
).order_by('name'))
Actually it's not the count you're interested in here, but just whether or not there are any members in that relationship.
Q(lord__isnull=False) | Q(overlord__isnull=False)
In this case, better resort to raw SQL.
for p in Person.objects.raw('SELECT * FROM myapp_person WHERE...'):
print p