Django model query all fields including the ManyToManyField in a single command - python

While playing around with the ManyToManyField, I wondered is there a way you can query a ManyToManyField automatically the same way you'd do a ForeignKey using select_related()?
Tables:
class Author(models.Model):
fullname = models.CharField(max_length=100)
class Foo(models.Model):
bar = models.CharField(max_length=100)
class Book(models.Model):
title = models.CharField(max_length=100)
foo = models.ForeignKey(Foo)
author = models.ManyToManyField(Author)
In order to get the data I need from Book I usually do:
book = Book.objects.select_related('foo').get(pk=1)
authors = book.author.all()
which makes 2 trips. Is there a way to combine them the way select_related() does?

You can use prefetch_related for M2M field
Book.objects.select_related('foo').prefetch_related('author').values('author', 'title').get(pk=1)

Related

Is it possible to get all authors by single query in django

class Author(models.Model):
name = models.CharField(max_length=50)
class Chapter(models.Model):
book = models.ForeignKey(Album, on_delete=models.CASCADE)
author = models.ManyToManyField("Author")
class Book(models.Model):
author = models.ManyToManyField("Author")
I am trying to show all related authors when I visit one author detail. To do that currently I do this to achieve this:
authors = []
for chapter in Author.objects.get(id=id).chapter_set.all():
authors.append(chapter.artists.all())
Is there any other way to do this by djangoORM
You can follow ManyToManyField relationships backwards in filters, in the case of the Author model you should be able to use chapter__ to access the Chapter.author relationship
authors = Author.objects.filter(chapter__author_id=id).distinct()

Storing list of objects in Django model

Is there a way in Django to have multiple objects stored and manageable (in Django admin) inside another object?
Example, I have two models: Items and RMA. The RMA may have multiple Items inside of it. Each Item is unique in the sense that it is an inventoried part, so I can't just reference the same item multiple times with foreignKey (though maybe I'm misunderstanding its use/implementation).
So for now, I have an Item model:
class Item(models.Model):
serial_number = models.CharField(max_length=200)
name = models.CharField(max_length=200)
part_number = models.CharField(max_length=200)
location = models.CharField(max_length=200)
def __unicode__(self):
return self.name
And an RMA model:
class RMA(models.Model):
number = models.AutoField(primary_key=True)
items = ?????
Ultimately I'd like to be able to maintain use of the Django admin functionality to add/remove items from an RMA if necessary, so I've been staying away from serializing a list and then deserializing on display. Any help would be much appreciated.
You're modeling a has-many relationship.
This would be modeled with a Foreign Key on Item to RMA:
class Item(models.Model):
serial_number = models.CharField(max_length=200)
name = models.CharField(max_length=200)
part_number = models.CharField(max_length=200)
location = models.CharField(max_length=200)
rma = models.ForeignKey(RMA)
def __unicode__(self):
return self.name
To make it accessible in the admin of RMA you need djangos InlineAdmin functionality.
You can find examples in the django tutorial part2.
You are effectively describing a Many-To-One relation and to do this you are going to have to add the ForeignKey reference to the Item model, not to the RMA model.
You can also add a related_name to give the RMA model an attribute that you can call.
For example:
class Item(models.Model):
rma = models.ForeignKey(RMA,related_name="items")
serial_number = models.CharField(max_length=200)
# etc...
To manage the creation of these, you'll need an InlineModelAdmin form, so your admin.py file will need to look like this:
from django.contrib import admin
class ItemInline(admin.TabularInline):
model = Item
class RMAAdmin(admin.ModelAdmin):
inlines = [
ItemInline,
]

django form with select fields

I have the following models
class Group(models.Model):
name = models.CharField(max_length=32, unique=True)
class Subgroup(models.Model):
name = models.CharField(max_length=32, unique=True)
group = models.ForeignKey(Group)
class Keywords(models.Model):
name = models.CharField(max_length=32, unique=True)
subgroup = models.ForeignKey(Subgroup)
For each Subgroup I need to manage a list of keywords.
I'm trying to use django forms to automatically display a list (select box) where if I add or remove values to that list and then issue a form.save that it automatically updates the models and data.
How exactly can I do this? Are my models designed properly to allow this?
I think you can create form with MultipleChoiceField:
class MyForm(forms.Form):
to_select = forms.MultipleChoiceField(widget=forms.CheckboxInput, choices=[])
In this case you have to override form`s save method.
Did you try to create model form for subgroup class?
class MyForm(forms.ModelForm):
class Meta():
model=Subgroup

Filter across three tables using Django

I have 3 django models, where the first has a foreign key to the second, and the second has a foreign key to the third. Like this:
class Book(models.Model):
year_published = models.IntField()
author = models.ForeignKey(Author)
class Author(models.Model):
author_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=50)
agent = models.ForeignKey(LitAgent)
class LitAgent(models.Model):
agent_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=50)
I want to ask for all the literary agents whose authors had books published in 2006, for example. How can I do this in Django? I have looked at the documentation about filters and QuerySets, and don't see an obvious way. Thanks.
LitAgent.objects.filter(author__book__year_published=2006)

How do I use the Django ORM to query this many-to-many example?

I have the following models:
class Author(models.Model):
author_name = models.CharField()
class Book(models.Model):
book_name = models.CharField()
class AuthorBook(models.Model):
author_id = models.ForeignKeyField(Author)
book_id = models.ForeignKeyField(Book)
With that being said, I'm trying to emulate this query using the Django ORM (select all of the books written by a specific author, noting that Authors can have many books and Books can have many Authors):
SELECT book_name
FROM authorbook, book
WHERE authorbook.author_id = 1
AND authorbook.book_id = book.id
I've read this FAQ page on the Django website, but before I modify my model structure and remove AuthorBook, I was curious if I could emulate that query using the current structure.
You should be able to do:
books = Book.objects.filter(authorbook__author_id=1)
to get a QuerySet of Book objects matching your author_id restriction.
The nice thing about Django is you can cook this up and play around with it in the shell. You may also find
http://docs.djangoproject.com/en/dev/topics/db/queries/#spanning-multi-valued-relationships
to be useful.
"AuthorBook" seems not correctly modeled.
You should use a ManyToManyField:
class Book(models.Model):
name = models.CharField()
authors = models.ManyToManyField(Author)
Then you can do:
books = Book.objects.filter(authors__id=1)

Categories

Resources