I want to add fields dynamically in Django 1.8.
Here's my models.py
class Book(models.Model):
title = models.CharField(max_length=100)
def __str__(self):
return self.title
class Author(models.Model):
name = models.CharField(max_length=100)
books = models.ManyToManyField(Book)
def __str__(self):
return self.name
Here's my admin.py
class AuthorAdmin(admin.ModelAdmin):
admin.site.register(Author, AuthorAdmin)
class BookAdmin(admin.ModelAdmin):
admin.site.register(Book, BookAdmin)
Here's how it looks now:
I've tried to use Inline, but I can only add a new book also.
I want to be able to add many books to one author dynamically.
Something like this:
How can I do this?
Edit:
I've changed AuthorAdmin to this:
class AuthorAdmin(admin.ModelAdmin):
formfield_overrides = {
models.ManyToManyField: {'widget': CheckboxSelectMultiple},
}
admin.site.register(Author, AuthorAdmin)
But instead of one checkbox with "N" options, I want "N" textboxes to choose the books.
You got your cardinalities the wrong way round. As you wrote it, the relationship is "An author has one book, a book has many authors", while you obviously wanted "A book has one author, an author has many books" - or possibly "a book as one or many authors, an author has one or many books".
In the first case, you have to remove the ForeignKey in Author and add a ForeignKey to Book in Author - and use an AdminInline in Author if you want to be able to add books to an author from the AuthorAdmin.
In the second case, you want a ManyToManyField, which can be in either Book or Author...
You need to use ManyToMany field for books:
books = models.ManyToManyField(Book)
Django doc for ManyToMany.
Related
Say I have Django models like so:
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
authors = models.ManyToManyField(Author)
What's the best way to get the the number of books each author created (preferably ordered) within a query or two?
The Author set might get pretty big, so I'm looking for a way to avoid iterating over all of it.
in your model book add...
...
author = models.ForeignKey(Author)
...
and to get then you use a QuerySet like
...
Author.objects.get(id=some_id).book_set.all() # this line, return all book of these author, if you want get the number just add at end '.count()'
...
I have some models, where Books can have many Authors and vice versa:
class Book(models.Model):
name = models.CharField(max_length=140)
class Author(models.Model):
name = models.CharField(max_length=140)
books = models.ManyToManyField(Book, related_name="authors")
I need to find all Books that have no author from a Book queryset, yet I can't find an appropriate .filter() or .exclude() clause that will do it.
Can I do this from a queryset?
You can simply write
Book.objects.filter(author_set=None)
or, if you have an existing query
book_queryset.filter(author_set=None)
I have the following code:
class Item(models.Model):
name = models.CharField(max_length=100)
keywords = models.CharField(max_length=255)
type = models.ForeignKey(Type)
class Meta:
abstract = True
class Variant(models.Model):
test_field = models.CharField(max_length=255)
class Product(Item):
price = models.DecimalField(decimal_places=2, max_digits=8,null=True, blank=True)
brand = models.ForeignKey(Brand)
variant = models.ForeignKey(Variant)
def get_fields(self):
return [(field.name, field.value_to_string(self)) for field in Product._meta.fields]
def __unicode__(self):
return self.name
Im using Grappelli.
I want my Product to have multiple Variations. Should I use a manytomanyfield?
I want to be able to add Variants to my Product directly in the Admin. Now I get an empty dropwdown with no variants(because they doesnt exists).
I thought Django did this automatically when u specified a Foreign Key?
How can I get the Variant fields to display directly on my Product page in edit?
I've read someting about inline fields in Admin?
Well, it's the other way around :)
1/ Place the foreign key field in your Variant, not in your Product (what you describe is actually a OneToMany relationship).
2/ Link the Variant to your Product in the relative ProductAdmin in admin.py as an inline (i.e VariantInline).
See the docs for further informations : https://docs.djangoproject.com/en/1.6/ref/contrib/admin/#inlinemodeladmin-objects
Hope this helps !
Regards,
I would like to implement a very simple feature with the django admin panel but I couldn't find the right way to achieve this so far:
model.py
class Author(models.Model):
name = models.CharField()
class Books(models.Model):
title = models.CharField()
author = models.ForeignKey(Author)
admin.py
class AuthorAdmin(admin.ModelAdmin):
pass
admin.site.register(Author, AuthorAdmin)
How can I add a hyperlink to every item (Author) in the authors' list overview that links to a view showing all books of the specific author? For Example:
J.K. Rowling (books)
J.R.R. Tolkien (books)
where books is a hyperlink to a site showing all books of the author.
You are looking for a ModelAdmin.list_filter.
Set list_filter to activate filters in the right sidebar of the change list page of the admin. A listfilter can be a field name, where the specified field should be either a BooleanField, CharField, DateField, DateTimeField, IntegerField, ForeignKey or ManyToManyField, for example:
# Add a list filter author to BookAdmin.
# Now you can filter books by author.
class BookAdmin(ModelAdmin):
list_filter = ('author', )
Now you can use #Wolph suggestion to add a link in the Author list_display. This link points to the book list filtered by author:
# Add hyperlinks to AuthorAdmin.
# Now you can jump to the book list filtered by autor.
class AuthorAdmin(admin.ModelAdmin):
def authors(self):
return '%s' % (self.author_id, self.author)
authors.allow_tags = True
ALTERNATIVE. To save a click you can also point to the change view of a book directly:
class Books(models.Model):
title = models.CharField()
author = models.ForeignKey(Author)
def get_admin_url(self):
return "/admin/appname/books/%d/" %self.id
class BookAdmin(admin.ModelAdmin):
def authors(self):
html = ""
for obj in Books.objects.filter(author__id_exact=self.id):
html += '<p>%s</p>' %(obj.get_admin_url(), obj.title)
return html
authors.allow_tags = True
list_display = ['title', authors]
Disclaimer: Not tested, but if you fix the typo's it'll work! :)
Note that these links can also be injected at other points in the admin. When you add it to a widget, you can go from change view to change view.
Look into implementing an InlineModelAdmin object.
# admin.py
class BooksInline(admin.TabularInline):
model = Books
class AuthorAdmin(admin.ModelAdmin):
inlines = [BooksInline]
Edited answer in response to OP's comment:
class AuthorAdmin(admin.ModelAdmin):
list_display = ['name', 'books_published']
def books_published(self, obj):
redirect_url = reverse('admin:books_changelist')
extra = "?author__id__exact=%d" % (obj.id)
return "<a href='%s'>Books by author</a>" % (redirect_url + extra)
books_published.allow_tags = True
It's not as simple as you might think actually, possible but not trivial since there is not that much documentation of this feature :)
What you need is a custom column which is generated by a function which gives you a link to the Django admin with a given filter. Something like this (from the top of my head so not tested) should do the trick:
class AuthorAdmin(admin.ModelAdmin):
def authors(self):
return '%s' % (self.author_id, self.author)
authors.allow_html = True
list_display = ['title', authors]
I have a manytomany relationship between publication and pathology. Each publication can have many pathologies. When a publication appears in the admin template, I need to be able to see the many pathologies associated with that publication. Here is the model statement:
class Pathology(models.Model):
pathology = models.CharField(max_length=100)
def __unicode__(self):
return self.pathology
class Meta:
ordering = ["pathology"]
class Publication(models.Model):
pubtitle = models.TextField()
pathology = models.ManyToManyField(Pathology)
def __unicode__(self):
return self.pubtitle
class Meta:
ordering = ["pubtitle"]
Here is the admin.py. I have tried variations of the following, but always
get an error saying either publication or pathology doesn't have a foreign key
associated.
from myprograms.cpssite.models import Pathology
class PathologyAdmin(admin.ModelAdmin):
# ...
list_display = ('pathology', 'id')
admin.site.register(Pathology, PathologyAdmin)
class PathologyInline(admin.TabularInline):
#...
model = Pathology
extra = 3
class PublicationAdmin(admin.ModelAdmin):
# ...
ordering = ('pubtitle', 'year')
inlines = [PathologyInline]
admin.site.register(Publication,PublicationAdmin)
Thanks for any help.
Unless you are using a intermediate table as documented here http://docs.djangoproject.com/en/dev/ref/contrib/admin/#working-with-many-to-many-intermediary-models, I don't think you need to create an Inline class. Try removing the line includes=[PathologyInline] and see what happens.
I realize now that Django is great for the administration (data entry) of a website, simple searching and template inheritance, but Django and Python are not very good for complex web applications, where data is moved back and forth between a database and an html template. I have decided to combine Django and PHP, hopefully, applying the strengths of both. Thanks for you help!
That looks more like a one-to-many relationship to me, tho I'm somewhat unclear on what exactly Pathologies are. Also, so far as I understand, Inlines don't work on manytomany. That should work if you flip the order of the models, remove the manytomany and add a ForeignKey field to Publication in Pathology.
class Publication(models.Model):
pubtitle = models.TextField()
def __unicode__(self):
return self.pubtitle
class Meta:
ordering = ["pubtitle"]
class Pathology(models.Model):
pathology = models.CharField(max_length=100)
publication = models.ForeignKey(Publication)
def __unicode__(self):
return self.pathology
class Meta:
ordering = ["pathology"]