问题
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?
回答1:
You need to use the related name to access mages from the user.
But in your case, you're using an abstract class.
You need to change your foreign key player
like so :player = models.ForeignKey('auth.User', related_name="%(class)s_by_user")
And then use that related name in your serializer :
class UserSerializer(serializers.ModelSerializer):
mage_by_user = serializers.PrimaryKeyRelatedField(
many=True, queryset=Mage.objects.all())
class Meta:
model = User
fields = ('id', 'username', 'mage_by_user')
Read more about this here :
https://docs.djangoproject.com/en/1.7/topics/db/models/#be-careful-with-related-name
来源:https://stackoverflow.com/questions/28430881/inheritance-blocking-django-rest-frameworks-mojo-user-object-has-no-attribut