Alexandre Maneta
Alexandre Maneta

Reputation: 99

How transform a many to many relationship into a queryset?

I have a model in Django related to another model with a ManyToManyField. I'd like to retrieve all elements of ManyToManyField.

Here are the models :

class Personnel(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
    adresse = models.CharField(max_length=150, verbose_name=_("Adresse"))
    telephone = models.CharField(max_length=15, verbose_name=_("Téléphone"))
    dossiermedical = models.ManyToManyField("DossierMedical",  related_name=_("travaille_sur"))

class DossierMedical(models.Model):
    patient = models.OneToOneField("Patient", on_delete=models.CASCADE)

In the Django shell, I did the following:

p = Personnel.objects.get(pk=User.objects.get(pk=1))
d = p.dossiermedical.all()
<QuerySet []>

However, when I'm Django admin for this Personnel, you have : enter image description here

Response

Basically, the display in the image has nothing to do with the linked DossierMedical objects. To add objects, you should modify the admin page like this :

class PersonnelAdmin(admin.ModelAdmin):
     model= Personnel
     filter_horizontal = ('dossiermedical',)

After that, you just have to register it and go on the autogenerated admin page that django provides.

Upvotes: 1

Views: 107

Answers (2)

Damir Boltachev
Damir Boltachev

Reputation: 101

Don't use ModelName.objects.get(pk=1) anymore, because it raising exceptions. Use ModelName.objects.filter(pk=1).first() or django.shortcuts.get_object_or_404(ModelName, pk=1) instead.

It's a good practice to override __str__ function for your models like so:

class Personnel(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
    adresse = models.CharField(max_length=150, verbose_name=_("Adresse"))
    telephone = models.CharField(max_length=15, verbose_name=_("Téléphone"))
    dossiermedical = models.ManyToManyField("DossierMedical",  related_name=_("travaille_sur"))

    def __str__(self):
        return f'#{self.pk} {self.user.full_name}'

class DossierMedical(models.Model):
    patient = models.OneToOneField("Patient", on_delete=models.CASCADE)

    def __str__(self):
        return f'#{self.pk} {self.patient.full_name}'

Also you can add an inline for DossierMedical model and place it to 'inlines' field of PersonnelAdmin as described here.

Upvotes: 1

Malav Shah
Malav Shah

Reputation: 1

Just try it with filter. p = Personnel.objects.filter(pk=User.objects.get(pk=1))

Upvotes: 0

Related Questions