Reputation: 596
Im trying to customise my admin. I have a model with a foreign key to an another model. I currently have a dropdown that display a list of possible keys to chose from, but the list only shows the title.
model.py
class Equipment(models.Model):
noequipment = models.IntegerField('Equipment #' ,db_column='Noequipment', primary_key=True) # Field name made lowercase.
nom = models.CharField('Name',db_column='Nom', max_length=50, blank=True) # Field name made lowercase.
...
nooffice = models.ForeignKey('Office', db_column='NoOffice', blank=True, null=True, verbose_name='Office') # Field name made lowercase.
...
class Meta:
db_table = 'equipment'
ordering = ('nom',)
def __str__(self):
return self.nom
class Office(models.Model):
nooffice = models.IntegerField(db_column='NoOffice', primary_key=True) # Field name made lowercase.
officename = models.CharField(db_column='OfficeName', max_length=50, blank=True) # Field name made lowercase.
adresse = models.CharField(db_column='Adresse', max_length=50, blank=True) # Field name made lowercase.
ville = models.CharField(db_column='Ville', max_length=50, blank=True) # Field name made lowercase.
codepostal = models.CharField(db_column='CodePostal', max_length=50, blank=True) # Field name made lowercase.
class Meta:
db_table = 'office'
def __str__(self):
return self.officename
All I need is that the admin would show a table with the attribute values on top of the drop down.
also here admin.py (Need special ModelAdmin because im using multiple DB as per https://docs.djangoproject.com/en/1.8/topics/db/multi-db/ )
from django.contrib import admin
from .models import Equipment, Manufacturier, Office, Devicetype, Backdoor, Passage, Systadmin, Applicationadmin, Application, Os
from django import forms
from forms import EquipmentAdminForm, ManufacturierAdminForm, OfficeAdminForm, DevicetypeAdminForm, BackdoorAdminForm, PassageAdminForm, SystadminAdminForm, ApplicationadminAdminForm, ApplicationAdminForm, OsAdminForm
class VCOEModelAdmin(admin.ModelAdmin):
# A handy constant for the name of the alternate database.
using = 'vcoe'
def save_model(self, request, obj, form, change):
# Tell Django to save objects to the 'other' database.
obj.save(using=self.using)
def delete_model(self, request, obj):
# Tell Django to delete objects from the 'other' database
obj.delete(using=self.using)
def get_queryset(self, request):
# Tell Django to look for objects on the 'other' database.
return super(VCOEModelAdmin, self).get_queryset(request).using(self.using)
def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
# Tell Django to populate ForeignKey widgets using a query
# on the 'other' database.
return super(VCOEModelAdmin, self).formfield_for_foreignkey(db_field, request=request, using=self.using, **kwargs)
def formfield_for_manytomany(self, db_field, request=None, **kwargs):
# Tell Django to populate ManyToMany widgets using a query
# on the 'other' database.
return super(VCOEModelAdmin, self).formfield_for_manytomany(db_field, request=request, using=self.using, **kwargs)
class VCOETabularInline(admin.TabularInline):
using = 'vcoe'
def get_queryset(self, request):
# Tell Django to look for inline objects on the 'other' database.
return super(VCOEMTabularInline, self).get_queryset(request).using(self.using)
def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
# Tell Django to populate ForeignKey widgets using a query
# on the 'other' database.
return super(VCOEMTabularInline, self).formfield_for_foreignkey(db_field, request=request, using=self.using, **kwargs)
def formfield_for_manytomany(self, db_field, request=None, **kwargs):
# Tell Django to populate ManyToMany widgets using a query
# on the 'other' database.
return super(VCOEMTabularInline, self).formfield_for_manytomany(db_field, request=request, using=self.using, **kwargs)
class OfficeAdmin(VCOEModelAdmin):
form = OfficeAdminForm
class EquipmentAdmin(VCOEModelAdmin):
form = EquipmentAdminForm
...
admin.site.register(Equipment, EquipmentAdmin)
...
admin.site.register(Office, OfficeAdmin)
...
and forms.py
from django import forms
from .models import Equipment, Manufacturier, Office, Devicetype, Backdoor, Passage, Systadmin, Applicationadmin, Application, Os
class EquipmentAdminForm(forms.ModelForm):
class Meta:
model = Equipment
exclude = ['noequipment']
...
class OfficeAdminForm(forms.ModelForm):
class Meta:
model = Office
exclude = ['nooffice']
Upvotes: 2
Views: 803
Reputation: 11471
I see two possible approaches:
The simplest approach is to make __str__
(or __unicode__
, depending on Python version) on your model to include extra information you want to see. E.g.:
class Office(models.Model):
...
def __unicode__(self):
return u"{0.officename} ({0.ville}, {0.addresse})".format(self)
The most flexible but most complicated is to create a custom widget. There are some readily available libraries that may or may not suit your needs and tastes. For example, you may consider taking a look at django-autocomplete-light
's ModelChoiceField
and it`s autocomplete styling options.
The process isn't trivial, but the overall outline is:
Create a ModelForm
that uses this widget. Some libraries provide a custom fields that are pre-configured to use the widget, if you have a self-implemented one, you can consider writing a field or using Django's built-in ModelChoiceField
with widget
argument. Some libraries have their own conventions, if you have own implementation, then you can go with something like:
class EquipmentForm(forms.ModelForm):
class Meta:
model = Equipment
widgets = {
"office": OfficeSelectWidget(...)
}
In your ModelAdmin
class refer to your form, so Django would use it instead of automatically-generated one.
If you're just experimenting or learning - and have enough time to spare, I suggest go the complicated route and write everything on your own, so you'd know how things work under the hood. Then never do this again, but use batteries from PyPI. If you just want things quick, take a look at abovementioned django-autocomplete-light
library, which should be quite simple to get started. Just follow their tutorials and examples, starting from the basic autocomplete field then extending it with custom styling.
Upvotes: 2