Django Admin - How can I select new data created using ForeignKey? - python

For example, I have this models
# models.py
from django.db import models
class Category(models.Model):
title = models.CharField(max_length=60)
class CategoryDescription(models.Model)
category = models.ForeignKey(Category)
description = models.CharField(max_length=120)
class Image(models.Model):
category = models.ForeignKey(Category)
description = models.ForeignKey(CategoryDescription)
image = models.ImageField()
And I have this admin init file
# admin.py
from django.contrib import admin
from .models import Category, CategoryDescription, Image
class CategoryDescriptionInline(admin.TabularInline):
model = CategoryDescription
class CategoryAdmin(admin.ModelAdmin):
inlines = (CategoryDescriptionInline,)
class ImageAdmin(admin.ModelAdmin):
pass
admin.site.register(Category, CategoryAdmin)
admin.site.register(Image, ImageAdmin)
I want create new Image in Admin, i create new category, using plus placed right from select input and next, i want choose Image Description, but i cant do it, because it isn't loaded.
What you may recommend for me in this situation? Thanks

Register a ModelAdmin for CategoryDescription, e.g.:
admin.site.register(CategoryDescription)

Related

How do I delete a field from my Django ModelForm?

I'm trying to hide and delete two fields from showing in a form I created in the Django administration page using ModelForm.
I looked at answers that said I should use the "exclude" meta field, but I don't know why it's not working in my case.
Here is my code:
models.py:
class Activity(models.Model):
type = models.CharField(max_length=50, default="")
title = models.CharField(max_length=200, default="")
description = models.CharField(max_length=500)
owner = models.ForeignKey(User, related_name="owner")
college = models.CharField(max_length=200)
location = models.CharField(max_length=200)
room = models.CharField(max_length=200)
startDate = models.DateTimeField(null=True, blank=True)
endDate = models.DateTimeField(null=True, blank=True)
attendee = models.ManyToManyField(Attendee, related_name="attendees",null=True, blank=True)
volunteer = models.ManyToManyField(Volunteer, related_name="volunteers",null=True, blank=True)
I'm trying to exclude the "attendee & volunteer" fields from displaying in the Django administration form.
In admin.py I have:
from django.contrib import admin
from django import forms
from KSUvity.models import Activity
class ActivityForm(forms.ModelForm):
class Meta:
model = Activity
exclude = ['attendee', 'volunteer',]
class ActivityAdmin(admin.ModelAdmin):
exclude = ['attendee', 'volunteer',]
form = ActivityForm
admin.site.register(Activity, ActivityAdmin)
You have to create an admin.py file in your app and register your models
Follow the instuctions
See the example below
from django import forms
from django.contrib import admin
from myapp.models import Person
class PersonForm(forms.ModelForm):
class Meta:
model = Person
exclude = ['name']
class PersonAdmin(admin.ModelAdmin):
exclude = ['age']
form = PersonForm
admin.site.register(Person, PersonAdmin)
You can use either fields or exclude in one class.
In your app admin field add this code.
app_name/admin.py
from django.contrib import admin
class ActivityAdmin(admin.ModelAdmin):
exclude = ('attendee', 'volunteer',)
You have to use ModelAdmin option to exclude fields from form in Django administration, either ModelAdmin.exclude or ModelAdmin.fields. Below is an example:
class ActivityAdmin(admin.ModelAdmin):
exclude = ('attendee', 'volunteer', )
To make it work, you register model like this:
admin.site.register(Activity, ActivityAdmin)
You add this code to admin.py file.

How to use filter_horizontal on a ForeignKey between two apps using ContentTypes in Django admin?

Say I have this app named Pantry that is to connect to any other app I may come along. To keep the app decoupled, generic relations are used through the model LinkedItem which connects the Ingredients model to apps outside Pantry.
I would like the content on the other end of the generic relation, say an app named Bakery, to be able to do a filter_horizontal with Ingredients.
Pantry
models.py
from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import fields
class Ingredient(models.Model):
'''
Model containing all the ingredients, their slugs, and their descriptions
'''
name = models.CharField(unique=True, max_length=100)
slug = models.SlugField(unique=True, max_length=100)
description = models.CharField(max_length=300)
# method to return the name of the db entry
def __str__(self):
return self.name
class LinkedItem(models.Model):
'''
Model that links ingredients to various other content models
'''
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = fields.GenericForeignKey('content_type', 'object_id')
ingredient = models.ForeignKey(Ingredient)
# method to return the name of the db entry
def __str__(self):
return self.ingredient.name
# defines options for the model itself
class Meta:
unique_together = (('content_type','object_id')) # prevents duplicates
Bakery
admin.py
from django.contrib import admin
from bakery.models import Cake
class CakeAdmin(admin.ModelAdmin):
filter_horizontal = ('') # what to put here so ingredients show up?
Any ideas?
I think this is what the GenericRelation is for, so you need to add one to your Cake model and use it's name in your CakeAdmin.
But you need to use Inlines if you don't want to do a lot of workaround as M2M fields are not supported for relations with intermediary models.

How to access a ManyToManyField between two apps using ContentTypes for Django admin?

Say I have this app named Pantry that is to connect to any other app I may come along. To keep the app decoupled, generic relations are used through the model LinkedItem which connects the Ingredients model to apps outside Pantry.
I can make a filter_horizontal show up for the LinkedItem's admin in Django. Now I would like the content on the other end of the generic relation, say an app named Bakery, to be able to do a filter_horizontal with ingredients.
Pantry
models.py
from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import fields
class Ingredient(models.Model):
'''
Model containing all the ingredients, their slugs, and their descriptions
'''
name = models.CharField(unique=True, max_length=100)
slug = models.SlugField(unique=True, max_length=100)
description = models.CharField(max_length=300)
# method to return the name of the db entry
def __str__(self):
return self.name
class LinkedItem(models.Model):
'''
Model that links ingredients to various other content models
'''
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = fields.GenericForeignKey('content_type', 'object_id')
ingredient = models.ManyToManyField(Ingredient)
# method to return the name of the db entry
def __str__(self):
return self.ingredient.name
# defines options for the model itself
class Meta:
unique_together = (('content_type','object_id')) # prevents duplicates
Bakery
admin.py
from django.contrib import admin
from bakery.models import Cake
class CakeAdmin(admin.ModelAdmin):
filter_horizontal = ('') # what to put here so ingredients show up?
Any ideas?
A solution is to create a GenericTabularInline for LinkedItem and putting some restrictions on the display to avoid duplicates like below:
from django.contrib.contenttypes.admin import GenericTabularInline
class LinkedItemAdmin(GenericTabularInline):
model = LinkedItem
# choosing the field and display
field = ['ingredient']
filter_horizontal = ['ingredient']
# These help with removing some potential issues in the admin
extra = 0
min_num = 1
max_num = 1
can_delete = False
Then in the CakeAdmin I can do this to make the ingredients show up.
class CakeAdmin(admin.ModelAdmin):
inlines = [LinkedItemAdmin]

How do I get the checkboxselectmultiple formfield_overrides to show on both of my models in a manytomany relationship?

So here is the code that I am working with right now
models.py
from django.db import models
class Building(models.Model):
name = models.TextField(max_length=60)
def __str__(self):
return self.name
class Charge(models.Model):
item = models.CharField(max_length=60)
cost = models.CharField(max_length=15)
last_updated = models.DateField(default='',auto_now=True)
buildings = models.ManyToManyField(Building)
def __str__(self):
return self.item
admin.py
from django.contrib import admin
from rlscharges.models import Charge, Building
from django.db import models
from django.forms import CheckboxSelectMultiple
class MyModelAdmin(admin.ModelAdmin):
formfield_overrides = {
models.ManyToManyField: {'widget': CheckboxSelectMultiple},
}
class BuildingInline(admin.TabularInline):
model = Charges.building.through
class BuildingAdmin(MyModelAdmin):
fields = ['name']
inlines = [BuildingInline]
admin.site.register(Charge, MyModelAdmin)
admin.site.register(Building, BuildingAdmin)
I basically just want the checkboxselectmultiple to show up on the Charge and Building models admin pages. Right now the checkbox only shows up on the Charge model and the TabularInline shows up on the Building model. Is there a way to get formfield_overrides to apply to the BuildingInline so it shows the checkboxes and not the TabularInline? Or do I need to do something to the relationship of the models? I apologize ahead of time if this is a stupid question, I am just getting started with django.

django-mptt nested dropdown in standard ModelAdmin?

I'm using django-mptt for a Category model, which is a foreign key to a Project model:
from django.db import models
from mptt.models import MPTTModel, TreeForeignKey
class Category(MPTTModel):
name = models.CharField(max_length=255)
parent = TreeForeignKeyY('self',
null=True,
blank=True,
related_name='children'
)
class Project(models.Model):
name = models.CharField(max_length=255)
category = models.ForeignKey('Category')
It's easy to set up the Category admin using MPTTModelAdmin, complete with a nice nested dropdown for picking parent category:
from django.contrib import admin
from mptt.admin import MPTTModelAdmin
from myapp.models import Category, Project
admin.site.register(Category, MPTTModelAdmin)
Now I'd like to include a nice nested Category dropdown in my Project admin, but the standard admin.ModelAdmin does not include this functionality and subclassing MPTTModelAdmin doesn't seem to work:
Project has no field named 'parent'
Is it possible to mimic the nested dropdown in a non-MPTT admin tool?
You can still use TreeForeignKey on a non-MPTTModel, assuming that the linked model is an MPTTModel, i.e.:
class Project(models.Model):
name = models.CharField(max_length=255)
category = TreeForeignKey('Category')
Alternatively, you can make the field an instance of mptt.forms.TreeNodeChoiceField or mptt.forms.TreeNodeMultipleChoiceField on your form.

Categories