Issue
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
Solution
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
Answered By - Tonio
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.