Show field many to many in django admin panel - django

I use this functions (cedi) but dont work.I want to show field nombre of Cedi model in panel admin of Campania model. The name of the column appear but the info or every instance doesn´t.
#admin.register(Campania)
class CampaniaAdmin(ImportExportMixin, admin.ModelAdmin):
# conecta con CampaniaResource
resource_class = CampaniaResource
list_display = ('nombre', 'descripcion', 'cedi')
list_filter = ('nombre', )
readonly_fields = ('fecha_creacion', 'fecha_modificacion')
search_fields = ['nombre',]
def cedi(self, obj):
return ", ".join([i.nombre for i in obj.cedis.all()])
models
class Campania(models.Model):
nombre = models.CharField(verbose_name='campaña', max_length=200, primary_key=True)
fecha_creacion = models.DateTimeField(auto_now_add=True)
fecha_modificacion = models.DateTimeField(auto_now=True)
descripcion = models.TextField()
# campo manytomany
cedis = models.ManyToManyField(Cedi)
def __str__(self):
return self.nombre
class Cedi(models.Model):
nombre = models.CharField(max_length=200, primary_key=True)
fecha_creacion = models.DateTimeField(auto_now_add=True)
fecha_modificacion = models.DateTimeField(auto_now=True)
# campo ForeignKey
pais = models.ForeignKey(Pais, on_delete=models.CASCADE)
def __str__(self):
return self.nombre

I did the same using your code and got this result:
shown M2M field in django admin
Here's what code looks like on my end:
models.py
class Pais(models.Model):
name = models.CharField(max_length=200, primary_key=True)
class Cedi(models.Model):
nombre = models.CharField(max_length=200, primary_key=True)
fecha_creacion = models.DateTimeField(auto_now_add=True)
fecha_modificacion = models.DateTimeField(auto_now=True)
# campo ForeignKey
pais = models.ForeignKey(Pais, on_delete=models.CASCADE)
def __str__(self):
return self.nombre
class Campania(models.Model):
nombre = models.CharField(verbose_name='campaña', max_length=200, primary_key=True)
fecha_creacion = models.DateTimeField(auto_now_add=True)
fecha_modificacion = models.DateTimeField(auto_now=True)
descripcion = models.TextField()
# campo manytomany
cedis = models.ManyToManyField(Cedi)
def __str__(self):
return self.nombre
admin.py
class PaisAdmin(admin.ModelAdmin):
list_display = [f.name for f in Pais._meta.fields]
admin.site.register(Pais, PaisAdmin)
class CediAdmin(admin.ModelAdmin):
list_display = [f.name for f in Cedi._meta.fields]
admin.site.register(Cedi, CediAdmin)
#admin.register(Campania)
class CampaniaAdmin(ImportExportMixin, admin.ModelAdmin):
# conecta con CampaniaResource
resource_class = Campania
list_display = ('nombre', 'descripcion', 'cedi')
list_filter = ('nombre', )
readonly_fields = ('fecha_creacion', 'fecha_modificacion')
search_fields = ['nombre',]
def cedi(self, obj):
return ", ".join([i.nombre for i in obj.cedis.all()])

Related

KeyError Post DjangoRestFramework

I'm new on Django Rest Framework and when I want to POST data I get a error: KeyError: 'id_area' I do not know what I'm doing wrong. Here's my code:
in my models.py
class Area(models.Model):
id_area = models.AutoField(primary_key=True)
APM = 'apm'
BUSINESS = 'business'
DESARROLLO = 'desarrollo'
SISTEMAS = 'sistemas'
ATENTUSIANOS_CHOICES = (
(APM, 'Apm'),
(BUSINESS, 'Business'),
(DESARROLLO, 'Desarrollo'),
(SISTEMAS, 'Sistemas'),
)
nombre = models.CharField(max_length=255, choices=ATENTUSIANOS_CHOICES)
class Meta:
verbose_name = 'Área'
verbose_name_plural = 'Áreas'
def __str__(self):
return self.nombre
class Atentusiano(models.Model):
id_atentusiano = models.AutoField(primary_key=True)
nombre = models.CharField(max_length=255, blank=False, null=False)
apellido = models.CharField(max_length=255, blank=False, null=False)
correo = models.CharField(max_length=255, blank=False, null=False, unique=True)
anexo = models.CharField(max_length=255, blank=True, null=True)
area = models.ForeignKey(Area, related_name='areas', on_delete=models.CASCADE)
class Meta:
verbose_name = 'Atentusiano'
verbose_name_plural = 'Atentusianos'
ordering = ['nombre']
def __str__(self):
return self.nombre + ' ' + self.apellido
in my serializers.py
class AreaSerializer(serializers.ModelSerializer):
areas = serializers.CharField(read_only=True)
class Meta:
model = Area
fields = ('id_area', 'nombre', 'areas')
class AtentusianoSerializer(serializers.ModelSerializer):
atentusianos = serializers.CharField(read_only=True)
area = serializers.CharField(source='area.nombre', read_only=True)
id_area = serializers.CharField(source='area.id_area')
class Meta:
model = Atentusiano
fields = ['id_atentusiano', 'nombre', 'apellido', 'correo', 'anexo', 'id_area', 'area', 'atentusianos']
def create(self, validated_data):
area_data = validated_data.pop('id_area')
area = models.Area.objects.create(**area_data)
atentusiano = models.Atentusiano.objects.create(area=area, **validated_data)
return atentusiano
And in my views.py
class AtentusianoView(viewsets.ModelViewSet):
queryset = Atentusiano.objects.all()
serializer_class = AtentusianoSerializer
class AreaView(viewsets.ModelViewSet):
queryset = Area.objects.all()
serializer_class = AreaSerializer
The problem is that when I want to Post data, for example:
{
"nombre": "name",
"apellido": "lastname",
"correo": "email#gmail.com",
"anexo": "1364",
"id_area": "1"
}
i got this error area_data = validated_data.pop('id_area')
KeyError: 'id_area'
I need help please
you should pop like this,
class AtentusianoSerializer(serializers.ModelSerializer):
.....
.....
class Meta:
model = Atentusiano
fields = ['id_atentusiano', 'nombre', 'apellido', 'correo', 'anexo', 'id_area', 'area', 'atentusianos']
def create(self, validated_data):
id_area = validated_data.pop('area')['id_area'] # here the correction
area = Area.objects.create(id_area=id_area) # an additional correction
atentusiano = Atentusiano.objects.create(area=area, **validated_data)
return atentusiano
EDIT: As id_area value, you are passing a string instead of an integer which will through another error. Also not,
area = models.Area.objects.create(**area_data)
it should be,
area = Area.objects.create(id_area=id_area)

Django / Customized ModelChoiceField: how label_from_instance works?

I use ModelChoiceField with initial value just for display (readonly field).
But value displayed is model id and I want to display customized value that will be a concatenation of 3 fields. I've override ____str____ method but it is not applyed.
I try to make customize ModelChoiceFiedl to define label_from_instance that seems to be the way to do what I want but it is not applyed...
models.py
class Utilisateur(SafeDeleteModel):
_safedelete_policy = SOFT_DELETE_CASCADE
uti_ide = models.AutoField(primary_key = True)
# pro_ide = models.ForeignKey(Projet, on_delete = models.CASCADE) # related project
projets = models.ManyToManyField(Projet, through='UtilisateurProjet')
uti_nom = models.CharField("Nom", max_length=20)
uti_pre = models.CharField("Prénom", max_length=20)
uti_mai = models.CharField("Email", max_length=40)
uti_sit = models.CharField("Equipe", max_length=20, null=True, blank=True)
uti_pro = models.CharField("Fonction/profil", max_length=200, null=True, blank=True)
uti_log = models.CharField("Log utilisateur", max_length=20, null=True, blank=True)
uti_dat = models.DateTimeField("Date log",auto_now_add=True, null=True, blank=True)
log = HistoricalRecords()
#classmethod
def options_list(cls,pro_ide):
# projet = Projet.objects.get(pro_ide=pro_ide)
# utilisateurs = Utilisateur.objects.filter(pro_ide=projet.pro_ide)
utilisateurs = Utilisateur.objects.filter(projets__pro_ide=pro_ide)
the_opts_list = [(utilisateur.uti_ide, utilisateur.uti_nom+', '+utilisateur.uti_pre) for utilisateur in utilisateurs]
the_opts_list.insert(0, (None, ''))
return the_opts_list
class Meta:
db_table = 'tbl_uti'
verbose_name_plural = 'Utilisateurs'
ordering = ['uti_ide']
def __str__(self):
return f"{self.uti_nom}, {self.uti_pre} ({self.uti_mai})"
forms.py
class UtilisateurModelChoiceField(ModelChoiceField):
def label_from_instance(self, obj):
print('label')
return obj.uti_nom+', '+obj.uti_pre+' ('+obj.uti_mai+')'
class UtilisateurProjetUpdateForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.request = kwargs.pop("request")
super(UtilisateurProjetUpdateForm, self).__init__(*args, **kwargs)
# print('kwargs',self.request)
# print('projet',self.request['projet'])
# print('utilisateur',self.request['utilisateur'])
PROJETS = Projet.objects.all()
UTILISATEURS = Utilisateur.objects.all()
self.fields["pro_ide"] = forms.ModelChoiceField(queryset = PROJETS, label = "Nom projet", widget = forms.HiddenInput(), initial = Projet.objects.get(pro_ide=self.request['projet']))
self.fields["uti_ide"] = UtilisateurModelChoiceField(queryset = UTILISATEURS, label = "Nom, prénom de l'utilisateur", widget = forms.TextInput(attrs={'readonly':'readonly'}), initial = Utilisateur.objects.get(uti_ide=self.request['utilisateur']),) #,to_field_name="uti_nom"
class Meta:
model = UtilisateurProjet
fields = ('pro_ide','uti_ide',)
in forms.py under that last class Meta: you need to add:
field_classes = {
'pro_ide': UtilisateurModelChoiceField,
'uti_ide': UtilisateurModelChoiceField,
}

How to group list items by user

I have an object with foreign key Edp. A user can have several RespostaEdp as per the design. However, when printing the list I want to group them by user. Any ideas on how to get this done? I tried the solution below but I cannot access user values.
#teacher_required
def listarRespostasEDA(request):
edpsTodas = Edp.objects.all()
title = 'Estruturas Digitais Pedagogicas'
template = 'edp/listarEDArespondida.html'
edps = list()
for edp in edpsTodas:
if edp.respostas.all().count() != 0:
# if not edp.respostas.none:
edps.append(edp)
return render(request, template, {'title': title, 'edps': edps})
def listaAlunosResponderamEdp(request, slug):
edp = get_object_or_404(Edp, slug=slug)
# respostas = RespostaEdp.objects.filter(edp=edp)
lista = list()
respostas = RespostaEdp.objects.filter(edp=edp).values('aprendiz').distinct().order_by('aprendiz')
for r in respostas:
for k,v in r.items():
aluno = User.objects.filter(pk=v)
lista.append(aluno)
print (lista)
return render(request, 'edp/teste.html', {'lista':lista})
class RespostaEdp(models.Model):
edp = models.ForeignKey(Edp, verbose_name='Edp', related_name='respostas', on_delete=models.CASCADE)
video_embedded = EmbedVideoField(blank=True, null=True)
texto = models.TextField('Texto', blank=True)
video = models.FileField(upload_to='video/', storage=upload_storage, default="media/none.mp4")
aprendiz = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name='aluno', related_name='respostaAluno', on_delete=models.CASCADE)
# aprendiz = models.ForeignKey(Student, verbose_name='aprendiz ', related_name='respostaAprendiz', on_delete=models.CASCADE)
created_at = models.DateTimeField('Criado em', auto_now_add=True)
updated_at = models.DateTimeField('Atualizado em', auto_now=True)
def __str__(self):
return self.edp.titulo + " - " + self.aprendiz.username
def iniciar(self):
self.save()
#models.permalink
def get_absolute_url(self):
return ('edp:detalhe_edp_resposta', (), {'slug': self.slug})
class Meta:
verbose_name = 'Resposta Estrutura Digital de Aprendizagem'
verbose_name_plural = 'Resposta Estrutura Digital de Aprendizagem'
ordering = ['-created_at']
class User(AbstractUser):
eh_aluno = models.BooleanField(default=False)
eh_professor = models.BooleanField(default=False)
And here is the models of the users:
class User(AbstractUser):
eh_aluno = models.BooleanField(default=False)
eh_professor = models.BooleanField(default=False)
class Student(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
def __str__(self):
return self.user.username

Populate combos in Django and initialize them with a foreign key

I need to populate two combos in a ModelForm, and I would like to initialize them with the current value of each foreign key.
My models are:
class Alumno(models.Model):
idalumno = models.AutoField(primary_key=True)
padre_idpadre = models.ForeignKey('Padre', models.DO_NOTHING, db_column='padre_idpadre', blank=True, null=True)
curso_idcurso = models.ForeignKey('Curso', models.DO_NOTHING, db_column='curso_idcurso')
nombre = models.CharField(max_length=45, blank=True, null=True)
class Meta:
db_table = 'alumno'
class Curso(models.Model):
idcurso = models.IntegerField(primary_key=True)
nombrecurso = models.CharField(max_length=45, blank=True, null=True)
class Meta:
db_table = 'curso'
class Padre(models.Model):
idpadre = models.AutoField(primary_key=True)
socio = models.NullBooleanField(blank=True, null=True)
nombre = models.CharField(max_length=45, blank=True, null=True)
primerapellido = models.CharField(max_length=45, blank=True, null=True)
segundoapellido = models.CharField(max_length=45, blank=True, null=True)
class Meta:
db_table = 'padre'
This is my Form in forms.py:
class AlumnoForm(forms.ModelForm):
padre = PadreModelChoiceField(queryset=Padre.objects.all(), initial=**XXXXXXXXX**) #I would like to init here with the value of the FK
curso = CursoModelChoiceField(queryset=Curso.objects.all(), initial=**XXXXXXXXXX**) #And here too
class Meta:
model = Alumno
fields = ('nombre','padre','curso',)
labels = {
'nombre': 'Nombre',
'padre': 'Padre',
'curso': 'Curso',
}
In views.py
def alumno_editar(request, pk):
alumno = get_object_or_404(Alumno, pk=pk)
if request.method == "POST":
form = AlumnoForm(request.POST, instance=alumno)
if form.is_valid():
alumno = form.save(commit=False)
alumno.save()
return redirect('alumno_listar')
else:
form = AlumnoForm(instance=alumno)
return render(request, 'administration/alumno_editar.html', {'form': form})
What should I write in the part XXXXXXXXXX of the code.
It could be misconception but I'm think is a common operation, althought I don't find it.

django ManyToManyField show slug as label

i have a "rare" behavior here, i this model:
models.py
class Area(models.Model):
area = models.CharField(max_length=150,unique=True)
slug = models.SlugField(max_length=200)
fecha = models.DateTimeField(default=datetime.date.today,editable=False)
activa = models.BooleanField(default=True)
class Empresa(models.Model):
usuario = models.ForeignKey(User)
nombre = models.CharField(max_length=150)
telefono = models.CharField(max_length=20)
fax = models.CharField(max_length=20,null=True,blank=True)
actividad = models.ManyToManyField(Area)
I dont know why the m2m_field actividad, into the django admin and any forms html is showing the slug field from the model Area as label
i was just returning the slug field and not the area "name"
class Area(models.Model):
area = models.CharField(max_length=150,unique=True)
slug = models.SlugField(max_length=200)
fecha = models.DateTimeField(default=datetime.date.today,editable=False)
activa = models.BooleanField(default=True)
def __unicode__(self):
return self.area # was self.slug
def get_absolute_url(self):
return '/areas/%s' % self.slug