Django help - how to get data from foreign keys - python

Given the following model setup (stripped down):
class Object(models.Model):
name = models.CharField(max_length=255)
class ObjectVersion(models.Model):
Cabinet = models.ForeignKey(Object)
Say I had a bunch of ObjectVersion entries that I'd filtered called "filteredObjects". How would I get the names of those objects into a vector?

You can use either values_list or values. The docs are available on the Django QuerySet API reference here.
>>> ObjectVersion.objects.filter(...).values('Cabinet__name')
[{'Cabinet__name':'foo'}, {'Cabinet__name':'foo2'}, ...]
or
>>> ObjectVersion.objects.filter(...).values_list('Cabinet__name')
[('foo',), ('foo2',), ...]

so you are saying that you have a list called filteredObjects?
objNames = [fo.name for fo in filteredObjects]

result = ObjectVersion.objects.filter(your filters here).values_list('Cabinet__name', flat=True)
Output:
result = ['ver_1', 'ver_2'..]

Related

Filtering objects and and their instances using filter and exclude

I am trying to filter like this:
#models.py
class A(models:Model):
all_letters = models.ManyToManyField(Letters, related_name="all_letters")
selected_letters = models.ManyToManyField(Letters, related_name="selected_letters")
#views.py
a = A.objects.get(pk=pk)
array_one = a.all_letters.all().exclude(a.selected_letters.all())
I know you can't filter based on instances but is the only equivalent way of doing this using some sort of manual python searching?
You can filter out the items where the relation in reverse (which you also named selected_letters) do not point to a, so:
array_one = a.all_letters.exclude(selected_letters=a)

How can I paginate EmbeddedDocumentListField objects in Mongoengine?

Here are my classes. What is a good way to query the User for the embedded Review objects and paginate it somehow?
class Review(EmbeddedDocument):
review_body = StringField(required=True)
review_stars = FloatField(required=True, default=0)
reviewer = LazyReferenceField('User')
review_date = DateTimeField()
class User(Document):
userreviews = EmbeddedDocumentListField(Review)
I'm sure I can get the total easily with .count() but I'm not sure how to skip and query for only a portion of the objects.
The answer, it seems, lies in the way I was querying the database. I was doing it incorrectly for what I was trying to accomplish.
What wasn't working:
userprofile: user.User = user.User.objects(
username=request.form["username"]).get()
all_reviews = userprofile.userreviews # work with objects here
What should work:
Using .filter() and .slice() I can get the embedded Review objects like so:
reviews = user.User.objects.filter(username=request.form["username"]).fields(
slice__userreviews=[0, 2])
for r in reviews:
print(r.userreviews)
This will return 2 review objects starting at the index of 0. Then I just need to use .count() to get the total amount and I should have the 3 elements I need for pagination.

How to do a JOIN over multiple Django models

The following models are given:
class Copy(CommonLibraryBaseModel):
lecture = models.ForeignKey('Lecture', ...)
signature = models.CharField(max_length=100, ...)
class Lecture(CommonLibraryBaseModel):
category = models.ForeignKey('LectureCategory', ...)
class LectureCategory(CommonLibraryBaseModel):
parent = models.ForeignKey('self', ...)
display_name = models.CharField(max_length=100, ...)
I basically want to do the following query:
SELECT signature, display_name FROM lecturecategory as lc, lecture as l, copy as c WHERE lc.id = l.category_id AND c.lecture_id = l.id AND lc.parent_id=2;
How would I do that in Django? I could not figure out how to combine the different models.
Thanks for the help!
SELECT signature, display_name
FROM lecturecategory as lc, lecture as l, copy as c
WHERE lc.id = l.category_id AND c.lecture_id = l.id AND lc.parent_id=2;
will be :
Copy.objects.filter(lecture__category__parent_id=2).values_list('signature', 'lecture__category__display_name')
If you want a QuerSet of dictionnary in result, use values instead of values_list. Values_list return a tuple.
Documentation about lookup relationship
You could get a queryset of Copy instances with the following filter
copies = Copy.objects.filter(lecture__category_parent_id=2)
See the docs on lookups that span relationships for more info.
You can then loop through the queryset, and access the related lecture and lecture category using the foreign key.
for copy in copies:
print(copy.signature, copy.lecture.category.display_name)
Finally, you can change the initial query to use select_related, so that Django uses an inner join to fetch the lecture and category rather than separate queries:
copies = Copy.objects.filter(lecture__category_parent_id=2).select_related('lecture', lecture__category')

Ordering filtered queryset according to a order of list

I have a list described below.
I want a queryset which will be ordered according to the order of list
list
id_list = [3,1,2]
queryset
queryset = Variant.objects.filter(pk__in=id_list)
the queryset gives objects in the order below:
obj1
obj2
obj3
but i want the objects according to order in the given list:
obj3
obj1
obj2
how??
Don't define ordering in code - add ordering column to your table and order by it. That's it.
class Variant(models.Model):
order = models.IntegerField()
...
Variant(ordering=3).save() # id == 1
Variant(ordering=1).save() # id == 2
Variant(ordering=2).save() # id == 3
queryset = Variant.objects.filter(pk__in=id_list).order_by('order')
So you will have queryset according to desirable order.
Otherwise google: django convert list to queryset and use Sayse answer as base for your code.
One example: django - convert a list back to a queryset
I don't think you could do this with a queryset (nor do I understand why you want to...)
You could do it with a map, but be warned, this will resolve the query and be potentially inefficient.
variants = list(map(lambda id: Variant.objects.get(pk=id), id_list))

Django - select model linked to itself

Jello!
I'm working with django right now and I have a problem which I suspect has a simple solution, but I've had a lot of difficulty trying to find it (most of the relevant keywords tend to point google to the wrong places).
I'm looking to filter a query based on the criteria that: A model has a field that points to itself.
I'll give an example:
class Person(models.Model):
name = models.CharField(max_length=20)
parent = models.ForeignKey('app.Person', null=True)
gramps = Person.objects.create(name='Tod', parent=None)
pops = Person.objects.create(name='Hank', parent=gramps)
sonny_boy = Person.objects.create(name='Tim', parent=pops)
temporal_paradox_dude = Person.objects.create(name='Emmett')
temporal_paradox_dude.parent = temporal_paradox_dude
temporal_paradox_dude.save()
temporal_paradox_dude_2 = Person.objects.create(name='Arnold')
temporal_paradox_dude_2.parent = temporal_paradox_dude_2
temporal_paradox_dude_2.save()
So the question is, in this case, how can I query the Person table for only people who are temporally paradoxical?
>>> Person.objects.filter(parent=SOME_WAY_OF_DECLARING_ITSELF)
[ 'Emmett', 'Arnold' ]
What do I need to replace SOME_WAY_OF_DECLARING_ITSELF with in order to get models that link to themselves?
Thanks!
I think you looking for something like this;
from django.db.models import F
Person.objects.filter(parent_id=F('id'))
You could do a simple query and then filter by iterating through that query:
results = [x for x in Person.objects.all() if x.parent == x]

Categories

Resources