I have a Book Model and BookImages model. Book is not related to Images directly ,instead BookImages has Book as foreign key and a Book can have many images.
I want to show Book details along with images related to book in admin panel but here Book doesnt have any relation to BookImages. Instead BookImages points to Book Model.
How can i show admin view with Book details and all Book Images.
Below is exact model code.
class Book(models.Model):
name = models.CharField(max_length=100)
description = models.CharField(max_length = 5000)
class BookImage(models.Model):
book = models.ForeignKey('Book', on_delete=models.CASCADE)
image = models.ImageField(upload_to=settings.MEDIA_RELATIVE_ROOT + "/bookimages")
Python version is 3.7.12 and django version is 3.2.14
Use TabularInline or StackedInline admin classes:
Example:
# admin.py
class BookImageInline(admin.TabularInline):
model = BookImage
fields = ['image']
extra = 1
class BookAdmin(admin.ModelAdmin):
inlines = [BookImageInline]
Related
My models.py:
class Author(models.Model):
name = models.CharField(max_length=100)
books = models.ManyToManyField(
"Book", related_name="books", blank=True
)
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.ManyToManyField(Author)
In Django admin I first created an instance of Author, without assigning him any Book:
Then I created a new Book and assigned Leo Tolstoy as theAuthor:
In Django shell, I am able to access the Book's Author:
>>> Book.objects.filter(title="War and Peace").first().author.first()
<Author: Leo Tolstoy>
But I'm unable to access the Author's Books:
>>> Author.objects.filter(name="Leo Tolstoy").first().books.all()
<QuerySet []>
The book isn't assigned in the Admin view either:
I would like to access the Author's Books as well as for the Books
to show in the Author's Admin view.
You only need one ManyToManyField. You should also pass "books" as the related_name on Book.authors as this is the name Django will use for the many-to-many manager attribute it automatically adds to Author instances.
See the example in the Django docs for more info.
When a ManyToManyField is created on both sides of a relation, Django is creating two associative tables between the book and author tables under the hood. Changes to one table don't affect the other.
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(
Author, related_name="books", blank=True
)
I suggest you do this:
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.ManyToManyField(Author, related_name="books",blank=True)
You need one ManyToManyField, then django will create two associative tables between the book and author tables. Changes to one table will not affect the other. You can see in the django documentation about many to many relationships. I have removed your books field in my answer because you have created an instance of your Author but you did not assign his 'book' and you have created a Book instance with giving title and author in your Book model. So so that any of your data won't be deleted. I also added related_name to your author field in your Book model because when you try to get the books related to the author (for example "Loe Tolstoy") you can get by this:
Author.objects.get(name="Leo Tolstoy").books.all()
I've been struggling with dajngo-filter recently. I have 2 models: Book and Author.
class Book(models.Model):
title = models.CharField(max_length=150)
author = models.ForeignKey(Author, on_delete=model.CASCADE)
length = models.PositiveIntegerField()
class Author(models.Model):
first_name = models.CharField(max_length=150)
last_name = models.CharField(max_length=150)
year_of_birth = models.DateFiled()
So, I'd like to make filter page, where you can find book by it's properties (title, author etc) AND information about author. For example book shorter than 300 pages, which author is beetween 20-25 years old.
In filters.py I have:
import django_filters
from .models import Book, Author
class BookFilter(django_filters.FilterSet):
class Meta():
model = Book
fields = ['title', 'author']
And have actually no idea how to also filter by different model, which is related by ForeignKey to Book model.
I have really little experience with Dajngo, I wonder if it's very complex problem or not. :)
Thanks!
Basically there are two important arguments for each filter:
field_name: The name of the model field to filter on. You can traverse “relationship paths” using Django’s __ syntax to filter fields on a related model. ex, author__last_name.
lookup_expr: The field lookup to use when filtering. Django’s __ syntax can again be used in order to support lookup transforms. ex, year__gte. For full list of field lookups you can use see here: https://docs.djangoproject.com/en/2.2/ref/models/querysets/#field-lookups.
Together, the field field_name and lookup_expr represent a complete Django lookup expression. A detailed explanation of lookup expressions is provided in Django’s lookup reference here: https://docs.djangoproject.com/en/2.2/ref/models/lookups/#module-django.db.models.lookups.
With that in mind here is the answer:
import django_filters
from .models import Book, Author
class BookFilter(django_filters.FilterSet):
title = django_filters.CharFilter(field_name='title', lookup_expr='iexact')
author = django_filters.CharFilter(field_name='author__last_name', lookup_expr='iexact')
class Meta():
model = Book
If you want to filter by exact date just add to your BookFilter class:
date_of_birth = django_filters.DateFilter(field_name='author__date_of_birth', lookup_expr='exact')
However it would make more sense to filter by year of birth (for example to get all the books from authors born between 1980 and 1990). To do that here is what you add to BookFilter class:
birth_year__gt = django_filters.NumberFilter(field_name='author__date_of_birth', lookup_expr='year__gt')
birth_year__lt = django_filters.NumberFilter(field_name='author__date_of_birth', lookup_expr='year__lt')
You can take a look at the document of django-filter package.
Items in the fields sequence in the Meta class may include “relationship paths” using Django’s __ syntax to filter on fields on a related model.
Like so:
import django_filters
from .models import Book, Author
class BookFilter(django_filters.FilterSet):
class Meta():
model = Book
fields = ['title', 'author__first_name', 'author__last_name']
I have a model Teacher which has following data:
class Teacher(models.Model):
name = models.CharField(max_length=100)
thumbnail = models.ForeignKey(Thumbnail)
class Thumbnail(models.Model):
thumbnail = models.FileField(upload_to=upload_to)
class TeacherAdmin(admin.ModelAdmin):
list_display = ('name',)
Here I want to relate all the thumbnail in my project to Thumbnail field. In my admin it shows me a dropdown of thumbnail while I want to add the thumbnail from admin.
Is it possible that I can upload from admin too?
Also what can I do in the case like :
class Teacher(models.Model):
name = models.CharField(max_length=100)
thumbnail = models.ManyToManyField(Thumbnail)
If I want to add multiple Images.
The only issue I am having is on admin side. Client side can be handles from regular forms.
Need suggestions and Ideas
models:
class Detail(models.Model):
def __unicode__(self):
return self.title
title = models.CharField(max_length=32)
class Cars(models.Model):
def __unicode__(self):
return self.name
name = models.CharField(max_length=32, unique=True)
details = models.ManyToManyField(Detail)
So, every car has a many details - wheels, engine, etc. How to do this: in Django Admin situated Cars menu, in that menu we have a many lines of details (like in tutorial).
In admin I use:
class DetailInline(admin.TabularInline):
model = Detail
extra = 6
class CarsAdmin(admin.ModelAdmin):
inlines = [DetailInline]
But it has error: Detail has no ForeignKey to Cars. How to fix it?
Django does not natively let you add a reverse inline.
i.e. You can have the Detail page contain an inline admin of all the Cars that contain a ForeignKey to that particular Detail. However, the reverse is not natively possible.
There is a workaround though wherein you have to override the admin template a bit. There is a previous SO question about this here: Inline-like solution for Django Admin where Admin contains ForeignKey to other model
For couple days I am trying to do multiple inline models in django. (inline inside inline)
But I couldnt. Then I decided to define a formset while editing base model (Page in example below), So one can also add new link when adding a new page(in admin page).
Like page->linksection->link. Here is the model.
#model.py
class Page(models.Model):
title = models.CharField(max_length=255)
class LinkSection(models.Model):
page = models.ForeignKey(Page)
title = models.CharField(max_length=255)
class Link(models.Model):
linksection = models.ForeignKey(LinkSection)
text = models.CharField(max_length=255)
url = models.URLField()
#admin.py
class LinkSectionInline(admin.TabularInline):
form = LinkSectionForm + LinkForm
Can you please show me how to define a formset for this model?
Thank you very much.