django - class based view store post data

267 views
Skip to first unread message

Shekar Tippur

unread,
May 31, 2015, 2:15:49 AM5/31/15
to django...@googlegroups.com
Hello,

I am trying to use class based view to post data.
I have come across a weird issue. It is not saving data in the backend. I get an error:
Expected view AddToUserProfile to be called with a URL keyword argument named "pk". Fix your URL conf, or set the `.lookup_field` attribute on the view correctly. 

I have searched on google to see explanation on this error but could not understand the explanation. Appreciate if someone can shed some light on this.

Here is my model:

class UserPrefs(models.Model):
Preferences = (
(1,'Likes'),
(1,'Dislikes'),
(1,'Shared'),
(1,'Rejected')
)
user = models.ForeignKey('auth.User', related_name='Hello')
name = models.ForeignKey(Stock)
value = models.CharField(max_length=20,choices=Preferences)

class Meta:
#managed = False
db_table = 'user_pref'

def save(self, *args, **kwargs):
super(Hello, self).save(*args, **kwargs)

class AddToUserProfile(generics.GenericAPIView):
permission_classes = (permissions.IsAuthenticatedOrReadOnly,IsOwnerOrReadOnly)
queryset = UserPrefs.objects.all()
serializer_class = UserPrefSerializer
lookup_fields = ('id')
def get(self, request, *args, **kwargs):
return HttpResponse('Hello there!')

def post(self, request, *args, **kwargs):
self.object = self.get_object()
context = self.get_context_data(object=self.object)
#eturn self.render_to_response(context)
def create(self, serializer):
serializer.save(owner=self.request.user)

Serializer code:

class UserPrefSerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username')
class Meta:
model = UserPrefs
fields = ( 'owner', 'name', 'value')
depth = 1

Url.py entry:
url(r'^Hello/setPrefs', views.AddToUserProfile.as_view()),

James Schneider

unread,
May 31, 2015, 3:10:15 AM5/31/15
to django...@googlegroups.com

A few things to consider:

In your view, it looks like you have 'lookup_fields' instead of 'lookup_field'.

http://www.django-rest-framework.org/api-guide/generic-views/#genericapiview

From a quick read through the DRF docs, it also looks like it only requires a single str value, and you are have it surrounded by (), which may lead to confusion later.

You have overridden post() but it doesn't return anything because all of the code is commented out. That'll also throw misleading errors, if it even runs. I'm assuming that may be from you testing things though.

You may also want to look at one of the other views to inherit from, such as the CreateAPIView, which may be more appropriate and efficient for what you are trying to do, rather than just inheriting from the base view class (unless you are trying to do something crazy). It's equivalent to just inheriting from View when using CBV's, which isn't the norm.

It is also possible that you should be POSTing to a URL that contains the 'pk' of the object that you are trying to modify. If you are trying to create an object, I would suggest looking into the CreateAPIView, since the base view probably expects an object pk to work with.

I've only used DRF briefly, so there may be other issues that I haven't spotted.

-James

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/6dbb2532-3bc3-4108-b1c9-9d48337fb02c%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Shekar Tippur

unread,
May 31, 2015, 1:03:42 PM5/31/15
to django...@googlegroups.com
James,

Thanks for responding. 

I have changed the view to:

class AddToUserProfile(generics.CreateAPIView):

permission_classes = (permissions.IsAuthenticatedOrReadOnly,IsOwnerOrReadOnly)
queryset = UserPrefs.objects.all()
serializer_class = UserPrefSerializer
    lookup_field = 'pk'
    def get(self, request, *args, **kwargs):
        return HttpResponse('Hello world')


def post(self, request, *args, **kwargs):
        #return self.get(request, *args, **kwargs)
        self.object = self.get_object()
context = self.get_context_data(object=self.object)
        return self.render_to_response(context)
def create(self, serializer):
serializer.save(owner=self.request.user)

James Schneider

unread,
May 31, 2015, 7:29:59 PM5/31/15
to django...@googlegroups.com
I would remove the code entirely for the post() and get(). As it stands, your create() method is never being called via post() since it is normally called by CreateAPIView. From a brief look at the DRF source, the reason you are getting the error that you are is because you are calling self.get_object() within the post() method. Since you are trying to create an object, and create() has not yet been called, there is no object to retrieve. The get_object() used by the *APIView's expects the object to be identified via a URL kwarg (referenced by self.lookup_field), not via attributes that have been posted.

TL;DR; Remove all of the code that you're using to override the methods, with the exception of the create() method (see below). Unless you are doing something outside of the norm (if you don't know what that means, you probably aren't), there shouldn't be a need to override them.

I just found this site, which is like Classy CBV's, except for the DRF, which is amazing: http://www.cdrf.co/3.1/rest_framework.generics/CreateAPIView.html

My guess would be to override create() in your view and add the owner to request.data, something along these lines, (Full disclosure: I've never done this, so YMMV):

def create(self, request, *args, **kwargs):
    request.data['owner'] = request.user
    return super(ViewName, self).create(request, *args, **kwargs)

You may need to play with request.data to figure out the structure and how to modify it. 

If the serializer throws an error complaining about 'owner' being a read-only field, you'll probably need to change the type of field. Just make sure to override update() in a similar as well to keep the user from changing that field.

I don't have a working setup with DRF to test, so YMMV.

For better help, though, you should post your question on the DRF mailing list, rather than here in the Django user list: https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework

-James

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users.

Shekar Tippur

unread,
Jun 1, 2015, 2:47:27 AM6/1/15
to django...@googlegroups.com
James,

Thanks for the response. I followed your instructions and took out the overriding of post and get methods.
However, as I am testing the app using curl, I ended up with CSRF verification failed. Request aborted.

- Shekar 

James Schneider

unread,
Jun 1, 2015, 3:17:18 AM6/1/15
to django...@googlegroups.com

Make sure to read the documentation on CSRF protection: http://www.django-rest-framework.org/topics/ajax-csrf-cors/#csrf-protection

-James

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users.
Reply all
Reply to author
Forward
0 new messages