How to modify values in m2m field in form? (Django)

dsaperov

I have 2 models in my models.py. They are Doctor and Specialty:

class Doctor(models.Model):
    name = CharField(max_length=255)
    specialties = ManyToManyField('Specialty', related_name='doctors')
    mc_id = CharField(max_length=255, unique=True)

class Specialty(models.Model):
    name = CharField(max_length=255)
    mc_id = CharField(max_length=255, unique=True)

    def __str__(self):
        return self.name

When i'm creating new Doctor instance via admin interface (change_form.html template) I see my Doctor model fields, which I should fill with data. Among these fields there is a field specialties ("Cпециальности"), which is m2m field and contains names (as I set __str__(self) method in Specialty model to return self.name) for specialties which were previously added to Specialty model (see a screen).

All I want is to see in this list not only specialty names, but also values of mc_id field of Specialty model, but it is not my case to make it at the expense of something like this:

class Specialty(models.Model):
    name = CharField(max_length=255)
    mc_id = CharField(max_length=255, unique=True)

    def __str__(self):
        return self.name + '(' + self.mc_id + ')'

I thought i could make it through overriding of formfield_for_manytomany() method in my admin model (associated with Doctor model) in admin.py:

@admin.register(Doctor)
class DoctorAdmin(admin.ModelAdmin):
    def formfield_for_manytomany(self, db_field, request, **kwargs):
        if db_field.name == "specialties":
            queryset = Specialty.objects.all()
            for specialty in queryset:
                specialty.name += '(' + {specialty.mc_id} + ')'
        return super().formfield_for_manytomany(db_field, request, **kwargs)

It didn't work. I'd like to know how can i solve my problem. Thank you in advance.

UPDATE: I'd also like to make a content of specialties field in the form user-dependent:

  • if superuser tries to add new doctor he will see in the specialties field of the form values like:
    • Internal Medicine (mc1_id)
    • Neurology (mc1_id)
    • Cardiology (mc2_id)
  • if normal user which name is 'mc1_id' tries to add new doctor he will see in the form values filtered by his name and without '(mc_id)'-part. Like:
    • Internal Medicine
    • Neurology
Tonio

I think that overwrite the label_from_instance method in the form field can work for you.



class SpecialtyModelMultipleChoiceField(forms.ModelMultipleChoiceField):

    def label_from_instance(self, obj):
        obj.name + '(' + obj.mc_id + ')'


class DoctorModelForm(forms.ModelForm):
    specialties = SpecialtyModelMultipleChoiceField(
        Specialty.objecs.all
        # ....
    )
    
    class Meta:
        model = Doctor
        fields = '__all__'


@admin.register(Doctor)
class DoctorAdmin(admin.ModelAdmin):
    form = DoctorModelForm
    # ....

UPDATE:

In order to make the field text user dependent you can return different classes in the get_form method of the Admin Model:


class SpecialtyModelMultipleChoiceField(forms.ModelMultipleChoiceField):

    def label_from_instance(self, obj):
        obj.name + '(' + obj.mc_id + ')'


class DoctorModelForm(forms.ModelForm):
    specialties = SpecialtyModelMultipleChoiceField(
        Specialty.objecs.all
        # ....
    )
    
    class Meta:
        model = Doctor
        fields = '__all__'


class SimpleDoctorModelForm(forms.ModelForm):
    
    class Meta:
        model = Doctor
        fields = '__all__'


@admin.register(Doctor)
class DoctorAdmin(admin.ModelAdmin):
    
    def get_form(self, request, obj=None, **kw):
        if request.user.is_superuser:
            return DoctorModelForm
        return SimpleDoctorModelForm

If you need more, you can set properties in the form and work with its in the constructor:


class DoctorModelForm(forms.ModelForm):
    
    class Meta:
        model = Doctor
        fields = '__all__'

    @classmethod
    def set_user(cls, user):
        cls.__user = user

    def __init__(self, *args, **kw):
        super(DoctorModelForm, self).__init__(*args, **kw)
        if self.__user.condition:
            self.fields['specialties'] = MyCustomField


@admin.register(Doctor)
class DoctorAdmin(admin.ModelAdmin):
    form = DoctorModelForm

    def get_form(self, request, obj=None, **kw):        
        form_class = super(DoctorAdmin, self).get_form(request, obj, **kw)
        form_class.set_user(request.user)

        return form_class

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

Django M2M field in a Model Form?

How to save m2m field on Django with commit=False?

How to .update m2m field in django

How to check the occurrence of a value in a m2m field in Django?

How to Select Multiple data from drop down in django form(Field has M2M relation in database)?

Accessing a m2m field values in django templates using forms

How do I save m2m field session from a form to another?

How to query records from a nested M2M field in Django?

How do create a custom save method for an existing m2m field. (Django)

how we can show users in admin panel in django in m2m field without list comprehension

How to create a django form object for m2m through object

Does Django makes additional query on accessing prefetched M2M field through "values()" or "values_list()"?

Modify objects in an m2m relation in Django

Get all possible values ​of a M2M field in a model

Setting field values for M2M object in djnago

Django m2m field remove method not working

django m2m field return objects instead of keys

Checking if an M2M field is empty or not in Django

Django get field from m2m and foreign key

Filter field M2M in Django ORM

How to display additional fields about the M2M field in Django or override select2-results__option

Django model form saves m2m after instance

Django model form: reverse side of m2m not saving

How to transition from M2M created with 'through' to a M2M managed by Django

Modify django model form field with widget

Django admin select m2m items based on their tags (item's m2m field)

How to dynamically modify a form field based on 2 other fields in Symfony?

How filter latest m2m objects with a QuerySet in Django

Django, how to have an array in model without M2M?