Access different fields on 'ManyRelatedManager' using Django Rest Framework?
django, django-rest-framework, json, python, serialization
Solution
As discussed, if you add a related_name="linked_arcana" to the mage field in the CharacterArcanumLink class, you should be able to do something like this:
class MageSerializer(serializers.ModelSerializer):
arcana = serializers.SerializerMethodField()
def get_arcana(self, obj):
if obj:
return {str(x): x.current_value for x in obj.linked_arcana.all()}
Problem
I'm trying to access fields on the through table of my ManyToMany link to serialize into a JSON via Django Rest Frameworks. My models involved in the many to many are: ``` class Mage(models.Model): arcana = models.ManyToManyField('ArcanumAbility', through='CharacterArcanumLink', related_name='mage_by_arcana') class ArcanumAbility(models.Model): class Arcana(AutoNumber): FATE = () MIND = () SPIRIT = () DEATH = () FORCES = () TIME = () SPACE = () LIFE = () MATTER = () PRIME = () arcanum = EnumField(Arcana) class Meta: verbose_name_plural = "Arcana Abilities" def __str__(self): return self.arcanum.label class CharacterArcanumLink(Trait): PRIORITY_CHOICES = ( (0, 'Unassigned'), (1, 'Ruling'), (2, 'Common'), (3, 'Inferior') ) priority = models.PositiveSmallIntegerField( choices=PRIORITY_CHOICES, default=0) mage = models.ForeignKey('Mage') arcana = models.ForeignKey('ArcanumAbility') class Meta: unique_together = ('mage', 'arcana') def __str__(self): return self.arcana.arcanum.label ``` Where the `Trait` mixin provides a `current_value` To serialize the above relation into my JSON, I have tried these two patters on my serializer: ``` class CharacterArcanumLinkSerializer(serializers.ModelSerializer): class Meta: model = CharacterArcanumLink fields = ('current_value', 'arcana') class MageSerializer(serializers.ModelSerializer): arcana = CharacterArcanumLinkSerializer() .... class Meta: model = Mage fields = (...., 'arcana', ....) depth = 1 ``` But that gives me this error: ``` AttributeError at /mages 'ManyRelatedManager' object has no attribute 'arcana' ``` Which is from (ultimately): ``` C:\Python34\lib\site-packages\rest_framework\fields.py in get_attribute if instance is None: # Break out early if we get `None` at any point in a nested lookup. return None try: if isinstance(instance, collections.Mapping): instance = instance[attr] else: instance = getattr(instance, attr) ... except ObjectDoesNotExist: return None if is_simple_callable(instance): instance = instance() return instance ▼ Local vars Variable: Value instance: <django.db.models.fields.related.create_many_related_manager.<locals>.ManyRelatedManager object at 0x0000000004E4D4A8> attr: 'arcana' attrs: ['arcana'] ``` (Question: What trick to I need to go from my ManyRelatedManager to it's fields?) And I've also tried not specifying a special serializer, and just having `'arcana'` in my fields, and pull it from my model. That leads to this error: ``` TypeError at /mages <Arcana.FATE: 1> is not JSON serializable ``` Where the `1` is from the PK on the ArcanumAbility not the value on the through table. The issue here is that the Mage class has a M2M field that points to the `'ArcanumAbility'` model, so all that DRF tries to do is serialize the Enum on it. So what method should I use if I want a JSON dictionary of all the relationships from Mage to ArcanumAbility with data from the through table? Responding to Mark R., I'd like it looks like so: ``` .... "arcanum": { "Fate": 2, "Spirit": 0, "Mind": 3, .... } ``` Hopefully that's a clear enough sample.