I've been following the tutorial here, except as I'm not creating a code snippet web-tool, I'm creating a RPG character manager, I've been swapping out 'snippet
' with 'mage
'. The other major difference is that my Mage only has a hold of users via their superclass NWODCharacter
(this is so I can later on add other character types, like Werewolves and Vampires!)
On accessing http://localhost:8000/users/
I get this error:
AttributeError at /users/
'User' object has no attribute 'mages'
Environment:
Request Method: GET
Request URL: http://localhost:8000/users/
Django Version: 1.7.1
Python Version: 3.4.2
Installed Applications:
('autocomplete_light',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'characters')
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware')
Traceback:
File "C:\Python34\lib\site-packages\django\core\handlers\base.py" in get_response
111. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Python34\lib\site-packages\django\views\decorators\csrf.py" in wrapped_view
57. return view_func(*args, **kwargs)
File "C:\Python34\lib\site-packages\django\views\generic\base.py" in view
69. return self.dispatch(request, *args, **kwargs)
File "C:\Python34\lib\site-packages\rest_framework\views.py" in dispatch
407. response = self.handle_exception(exc)
File "C:\Python34\lib\site-packages\rest_framework\views.py" in dispatch
404. response = handler(request, *args, **kwargs)
File "C:\Python34\lib\site-packages\rest_framework\generics.py" in get
269. return self.list(request, *args, **kwargs)
File "C:\Python34\lib\site-packages\rest_framework\mixins.py" in list
46. return Response(serializer.data)
File "C:\Python34\lib\site-packages\rest_framework\serializers.py" in data
615. ret = super(ListSerializer, self).data
File "C:\Python34\lib\site-packages\rest_framework\serializers.py" in data
212. self._data = self.to_representation(self.instance)
File "C:\Python34\lib\site-packages\rest_framework\serializers.py" in to_representation
565. self.child.to_representation(item) for item in iterable
File "C:\Python34\lib\site-packages\rest_framework\serializers.py" in <listcomp>
565. self.child.to_representation(item) for item in iterable
File "C:\Python34\lib\site-packages\rest_framework\serializers.py" in to_representation
423. attribute = field.get_attribute(instance)
File "C:\Python34\lib\site-packages\rest_framework\relations.py" in get_attribute
350. relationship = get_attribute(instance, self.source_attrs)
File "C:\Python34\lib\site-packages\rest_framework\fields.py" in get_attribute
69. instance = getattr(instance, attr)
Exception Type: AttributeError at /users/
Exception Value: 'User' object has no attribute 'mages'
It looks like it hinges on the fact that, my Mage
model holds a FK to the django defined User
, and django-rest-frameworks needs to do some magic to connect the two up. But the fact that I'm using inheritance is somehow blocking django-rest-frameworks mojo.
So my model looks like:
class NWODCharacter(models.Model):
class Meta:
abstract = True
SUB_RACE_CHOICES = ()
FACTION_CHOICES = ()
name = models.CharField(max_length=200)
player = models.ForeignKey('auth.User')
created_date = models.DateTimeField(auto_now_add=True, auto_now=False)
updated_date = models.DateTimeField(auto_now_add=False, auto_now=True)
published_date = models.DateTimeField(blank=True, null=True)
sub_race = models.CharField(choices=SUB_RACE_CHOICES, max_length=50)
faction = models.CharField(
choices=FACTION_CHOICES, max_length=50, null=True)
class Characteristics(models.Model):
class Meta:
abstract = True
VIRTUE_CHOICES = (('prudence', 'Prudence'), ('justice', 'Justice'),
('temperance', 'Temperance'), ('fortitude',
'Fortitude'), ('faith', 'Faith'),
('hope', 'Hope'), ('charity', 'Charity'))
VICE_CHOICES = (('lust', 'Lust'), ('gluttony', 'Gluttony'), ('greed', 'Greed'),
('sloth', 'Sloth'), ('wrath', 'Wrath'), ('envy', 'Envy'), ('pride', 'Pride'))
power_level = IntegerRangeField(min_value=1, max_value=10, default=1)
energy_trait = IntegerRangeField(min_value=1, max_value=10, default=7)
virtue = models.CharField(choices=VIRTUE_CHOICES, max_length=50)
vice = models.CharField(choices=VICE_CHOICES, max_length=50)
morality = IntegerRangeField(min_value=0, max_value=10, default=7)
size = IntegerRangeField(min_value=1, max_value=10, default=5)
class Mage(NWODCharacter, Characteristics):
def __str__(self):
return self.name
And my serializers appear like so:
class MageSerializer(serializers.ModelSerializer):
player = serializers.ReadOnlyField(source='player.username')
class Meta:
model = Mage
fields = ('id', 'player', 'name', 'created_date', 'updated_date', 'published_date',
'sub_race', 'faction', 'power_level', 'energy_trait', 'virtue', 'vice', 'morality', 'size',)
class UserSerializer(serializers.ModelSerializer):
mages = serializers.PrimaryKeyRelatedField(
many=True, queryset=Mage.objects.all())
class Meta:
model = User
fields = ('id', 'username', 'mages')
And these are my simple views
class MageList(generics.ListCreateAPIView):
queryset = Mage.objects.all()
serializer_class = MageSerializer
permission_classes = (permissions.IsAuthenticatedOrReadOnly,
IsOwnerOrReadOnly,)
def perform_create(self, serializer):
serializer.save(player=self.request.user)
class MageDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Mage.objects.all()
serializer_class = MageSerializer
permission_classes = (permissions.IsAuthenticatedOrReadOnly,
IsOwnerOrReadOnly,)
class UserList(generics.ListAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
class UserDetail(generics.RetrieveAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
How do I work round this difference?