through relations one manytoonerel many python django django-admin

python - relations - one to one django



Interfaz de administración de Django: usando horizontal_filter con el campo en línea ManyToMany (2)

El problema no es tener líneas internas; Es de la forma en que funciona ModelForm , en general. Solo crean campos de formulario para campos reales en el modelo, no atributos de administrador relacionados. Sin embargo, puede agregar esta funcionalidad al formulario:

from django.contrib.admin.widgets import FilteredSelectMultiple class ProjectAdminForm(forms.ModelForm): class Meta: model = Project 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 ...

Un pequeño recorrido está probablemente en orden. Primero, definimos un campo de formulario de userprofiles . Utilizará un ModelMultipleChoiceField , que de manera predeterminada dará como resultado un cuadro de selección múltiple. Dado que este no es un campo real en el modelo, no podemos simplemente agregarlo a filter_horizontal , así que en su lugar le decimos que simplemente use el mismo widget, FilteredSelectMultiple , que usaría si estuviera listado en filter_horizontal .

Inicialmente, establecimos el conjunto de consultas como el conjunto completo de perfiles de usuario, no puede filtrarlo aquí, sin embargo, porque en esta etapa de la definición de la clase, el formulario no ha sido instanciado y, por lo tanto, aún no tiene el conjunto de instance . Como resultado, reemplazamos __init__ para que podamos establecer el conjunto de consultas filtradas como el valor inicial del campo.

Finalmente, anulamos el método de save , de modo que podamos establecer el contenido del administrador relacionado en la misma forma que lo que estaba en los datos POST del formulario, y listo.

Tengo un campo de modelo de Django que me gustaría alinear. El campo es una relación de muchos a muchos. Así que hay "Proyectos" y "Perfiles de usuario". Cada perfil de usuario puede seleccionar cualquier número de proyectos.

Actualmente, tengo la vista en línea "tabular" funcionando. ¿Hay alguna forma de tener un "filtro horizontal" para poder agregar y eliminar proyectos fácilmente de un perfil de usuario?

Por favor, vea la imagen adjunta para un ejemplo.

Aquí está el código de modelo para el perfil de usuario:

class UserProfile(models.Model): user = models.OneToOneField(User, unique=True) projects = models.ManyToManyField(Project, blank=True, help_text="Select the projects that this user is currently working on.")

Y el código modelo para un proyecto:

class Project(models.Model): name = models.CharField(max_length=100, unique=True) application_identifier = models.CharField(max_length=100) type = models.IntegerField(choices=ProjectType) account = models.ForeignKey(Account) principle_investigator = models.ForeignKey(User) active = models.BooleanField()

Y el código de administrador para la vista:

class UserProfileInline(admin.TabularInline): model = UserProfile.projects.through extra = 0 verbose_name = ''user'' verbose_name_plural = ''users'' class ProjectAdmin(admin.ModelAdmin): list_display = (''name'', ''application_identifier'', ''type'', ''account'', ''active'') search_fields = (''name'', ''application_identifier'', ''account__name'') list_filter = (''type'', ''active'') inlines = [UserProfileInline,] admin.site.register(Project, ProjectAdmin)


Una adición menor cuando se trata de una relación de muchos a muchos consigo mismo. Uno podría querer excluirse de las opciones:

if self.instance.pk: self.fields[''field_being_added''].queryset = self.fields[''field_being_added''].queryset.exclude(pk=self.instance.pk) self.fields[''field_being_added''].initial = """Corresponding result queryset"""