I have the following model and admin defined in djando 1.5. This is a many-to-many relationship between subnet and vlan. I use the related_name option in the ManyToMany field to be able to get the collection of vlan from the related subnet object. Adding subnet to vlans from the admin works well. However when I try to add an horizontal_filer to the subnet admin in order to add van to its vlan set I get an error saying that the vlans attribute doesn't exist. I'm using subnet object in some view and I can access the vlans attribute just right.
What am I doing wrong here ? I've seen similar post but I couldn't adapt any of the proposed solution with success.
Thanks for your help
model.py
from django.db import models
class Subnet(models.Model):
networkAddress = models.CharField(max_length=15)
size = models.IntegerField()
def __unicode__(self):
return "%s/%s" % (self.networkAddress, self.size)
class IpAddress(models.Model):
ipAddress = models.CharField(max_length=15)
subnet = models.ForeignKey(Subnet)
def __unicode__(self):
return "%s" % (self.ipAddress)
class Vlan(models.Model):
number = models.IntegerField()
description = models.CharField(max_length=150)
subnets = models.ManyToManyField(Subnet, related_name='vlans', blank=True)
def __unicode__(self):
return "VLAN %s (%s)" % (self.number, self.description)
admin.py
from network.models import Subnet, IpAddress, Vlan
from django.contrib import admin
class SubnetAdmin(admin.ModelAdmin):
filter_horizontal = ('vlans',)
admin.site.register(Subnet, SubnetAdmin)
admin.site.register(IpAddress)
admin.site.register(Vlan)
and the error I get
Request Method: GET
Request URL: http://127.0.0.1:8000/admin/
Django Version: 1.5.2
Exception Type: ImproperlyConfigured
Exception Value:
'SubnetAdmin.filter_horizontal' refers to field 'vlans' that is missing from model 'network.Subnet'.
ManyToMany. A ManyToMany field is used when a model needs to reference multiple instances of another model. Use cases include: In this case, the user needs to be able to add multiple members to a meal. If the choices were fixed and the same for every user, then we could use django-multiple-select-field.
A ManyToMany field is used when a model needs to reference multiple instances of another model. Use cases include: In this case, the user needs to be able to add multiple members to a meal. If the choices were fixed and the same for every user, then we could use django-multiple-select-field.
Many-to-many relationships can be queried using lookups across relationships: Reverse m2m queries are supported : Relation sets can be cleared: Relation sets can be set: Django will automatically generate a table to manage many-to-many relationships. You might need a custom “through” model.
related_name – Django Built-in Field Validation. Last Updated : 01 Nov, 2020. The related_name attribute specifies the name of the reverse relation from the User model back to your model. If you don’t specify a related_name, Django automatically creates one using the name of your model with the suffix _set.
Apparently this is an 8 year old feature request. There is django-admin-extend. Or you could just throw something like this in there:
from django.contrib import admin as admin_module
class SiteForm(ModelForm):
user_profiles = forms.ModelMultipleChoiceField(
label='Users granted access',
queryset=UserProfile.objects.all(),
required=False,
help_text='Admin users (who can access everything) not listed separately',
widget=admin_module.widgets.FilteredSelectMultiple('user profiles', False))
class SiteAdmin(admin_module.ModelAdmin):
fields = ('user_profiles',)
def save_model(self, request, obj, form, change):
# save without m2m field (can't save them until obj has id)
super(SiteAdmin, self).save_model(request, obj, form, change)
# if that worked, deal with m2m field
obj.user_profiles.clear()
for user_profile in form.cleaned_data['user_profiles']:
obj.user_profiles.add(user_profile)
def get_form(self, request, obj=None, **kwargs):
if obj:
self.form.base_fields['user_profiles'].initial = [ o.pk for o in obj.userprofile_set.all() ]
else:
self.form.base_fields['user_profiles'].initial = []
return super(SiteAdmin, self).get_form(request, obj, **kwargs)
It should give you a filter_horizontal
when you specify it in the fields
tuple.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With