Interfaz de administrador de Django: uso de horizontal_filter con campo ManyToMany con tabla intermedia
Estoy tratando de mejorar la interfaz de administración de django de forma similar a lo que se ha hecho en la respuesta aceptada deesta publicación SO. Tengo una relación de muchos a muchos entre unUser
mesa y unProject
mesa. En el administrador de django, me gustaría poder asignar usuarios a un proyecto como en la imagen a continuación:
Funciona bien con un simpleManyToManyField
pero el problema es que mi modelo usa elthrough
parámetro de laManyToManyField
usar una tabla intermedia. No puedo usar elsave_m2m()
yset()
funciono y no tengo idea de cómo adaptar el código a continuación para que funcione.
El modelo:
class UserProfile(models.Model):
user = models.OneToOneField(User, unique=True)
projects = models.ManyToManyField(Project, through='Membership')
class Project(models.Model):
name = models.CharField(max_length=100, unique=True)
application_identifier = models.CharField(max_length=100)
type = models.IntegerField(choices=ProjectType)
...
class Membership(models.Model):
project = models.ForeignKey(Project,on_delete=models.CASCADE)
user = models.ForeignKey(UserProfile,on_delete=models.CASCADE)
# extra fields
rating = models.IntegerField(choices=ProjectType)
...
El código utilizado para el widget enadmin.py
:
from django.contrib.admin.widgets import FilteredSelectMultiple
class ProjectAdminForm(forms.ModelForm):
class Meta:
model = Project
fields = "__all__" # not in original SO post
userprofiles = forms.ModelMultipleChoiceField(
queryset=UserProfile.objects.all(),
required=False,
widget=FilteredSelectMultiple(
verbose_name='User Profiles',
is_stacked=False
)
)
def __init__(self, *args, **kwargs):
super(ProjectAdminForm, self).__init__(*args, **kwargs)
if self.instance.pk:
self.fields['userprofiles'].initial = self.instance.userprofile_set.all()
def save(self, commit=True):
project = super(ProjectAdminForm, self).save(commit=False)
if commit:
project.save()
if project.pk:
project.userprofile_set = self.cleaned_data['userprofiles']
self.save_m2m()
return project
class ProjectAdmin(admin.ModelAdmin):
form = ProjectAdminForm
...
Nota: no es necesario cambiar todos los campos adicionales del modelo intermediario en la vista Administrador de proyectos (se calculan automáticamente) y todos tienen un valor predeterminado.
¡Gracias por tu ayuda!