2013-08-26 27 views
10

Tôi có một chú thích mô hình rằng khi được tạo có thể hoặc không thể tạo người dùng mới. Vì lý do này, API của tôi yêu cầu trường mật khẩu khi tạo nhận xét mới. Đây là mô hình luận của tôi:Thêm trường không có trong mô hình vào bộ nối tiếp trong khung công tác REST của Django

class Comment(models.Model): 
    commenter = models.ManyToManyField(Commenter) 
    email = models.EmailField(max_length=100) 
    author = models.CharField(max_length=100) 
    url = models.URLField(max_length=200) 
    content = models.TextField(blank=True, null=True) 
    ip = models.IPAddressField(max_length=45) 
    date = models.DateTimeField(default=datetime.now) 
    post_title = models.CharField(max_length=200) 
    post_url = models.URLField(max_length=200) 
    rating = models.IntegerField(max_length=10, default=0) 

Đây là quan điểm API của tôi:

class CommentNewView(CreateAPIView): 
    model = Comment 
    serializer_class = CommentCreateSerializer 

đây là serializer tôi:

class CommentCreateSerializer(serializers.ModelSerializer): 
    commenter_pw = serializers.CharField(max_length=32, required=False) 

    class Meta: 
     model = Comment 
     fields = ('email', 'author', 'url', 'content', 'ip', 'post_title', 'post_url', 'commenter_pw') 

đây là lỗi Tôi nhận:

Environment: 


Request Method: POST 
Request URL: http://127.0.0.1:8000/api/comment/create/ 

Django Version: 1.5.2 
Python Version: 2.7.2 
Installed Applications: 
('commentflow.apps.dashboard', 
'commentflow.apps.commenter', 
'commentflow.apps.comment', 
'rest_framework', 
'rest_framework.authtoken', 
'django.contrib.auth', 
'django.contrib.contenttypes', 
'django.contrib.sessions', 
'django.contrib.sites', 
'django.contrib.messages', 
'django.contrib.staticfiles', 
'django.contrib.admin', 
'django.contrib.admindocs') 
Installed Middleware: 
('django.middleware.common.CommonMiddleware', 
'django.contrib.sessions.middleware.SessionMiddleware', 
'django.middleware.locale.LocaleMiddleware', 
'django.middleware.csrf.CsrfViewMiddleware', 
'django.contrib.auth.middleware.AuthenticationMiddleware', 
'django.contrib.messages.middleware.MessageMiddleware') 


Traceback: 
File "/Users/tlovett1/.virtualenvs/commentflow/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response 
    115.       response = callback(request, *callback_args, **callback_kwargs) 
File "/Users/tlovett1/.virtualenvs/commentflow/lib/python2.7/site-packages/django/views/generic/base.py" in view 
    68.    return self.dispatch(request, *args, **kwargs) 
File "/Users/tlovett1/.virtualenvs/commentflow/lib/python2.7/site-packages/django/views/decorators/csrf.py" in wrapped_view 
    77.   return view_func(*args, **kwargs) 
File "/Users/tlovett1/.virtualenvs/commentflow/lib/python2.7/site-packages/rest_framework/views.py" in dispatch 
    327.    response = self.handle_exception(exc) 
File "/Users/tlovett1/.virtualenvs/commentflow/lib/python2.7/site-packages/rest_framework/views.py" in dispatch 
    324.    response = handler(request, *args, **kwargs) 
File "/Users/tlovett1/.virtualenvs/commentflow/lib/python2.7/site-packages/rest_framework/generics.py" in post 
    372.   return self.create(request, *args, **kwargs) 
File "/Users/tlovett1/.virtualenvs/commentflow/lib/python2.7/site-packages/rest_framework/mixins.py" in create 
    50.   if serializer.is_valid(): 
File "/Users/tlovett1/.virtualenvs/commentflow/lib/python2.7/site-packages/rest_framework/serializers.py" in is_valid 
    479.   return not self.errors 
File "/Users/tlovett1/.virtualenvs/commentflow/lib/python2.7/site-packages/rest_framework/serializers.py" in errors 
    471.     ret = self.from_native(data, files) 
File "/Users/tlovett1/.virtualenvs/commentflow/lib/python2.7/site-packages/rest_framework/serializers.py" in from_native 
    867.   instance = super(ModelSerializer, self).from_native(data, files) 
File "/Users/tlovett1/.virtualenvs/commentflow/lib/python2.7/site-packages/rest_framework/serializers.py" in from_native 
    324.    return self.restore_object(attrs, instance=getattr(self, 'object', None)) 
File "/Users/tlovett1/.virtualenvs/commentflow/lib/python2.7/site-packages/rest_framework/serializers.py" in restore_object 
    852.    instance = self.opts.model(**attrs) 
File "/Users/tlovett1/.virtualenvs/commentflow/lib/python2.7/site-packages/django/db/models/base.py" in __init__ 
    415.     raise TypeError("'%s' is an invalid keyword argument for this function" % list(kwargs)[0]) 

Exception Type: TypeError at /api/comment/create/ 
Exception Value: 'commenter_pw' is an invalid keyword argument for this function 

Trả lời

9

Nếu ai là tò mò, giải pháp là để ghi đè lên các phương pháp restore_object và thêm các biến dụ bổ sung cho các đối tượng bình luận sau khi nó đã được khởi tạo:

def restore_object(self, attrs, instance=None): 
     if instance is not None: 
      instance.email = attrs.get('email', instance.email) 
      instance.author = attrs.get('author', instance.author) 
      instance.url = attrs.get('url', instance.url) 
      instance.content = attrs.get('content', instance.content) 
      instance.ip = attrs.get('ip', instance.ip) 
      instance.post_title = attrs.get('post_title', instance.post_title) 
      instance.post_url = attrs.get('post_url', instance.post_url) 
      return instance 

     commenter_pw = attrs.get('commenter_pw') 
     del attrs['commenter_pw'] 

     comment = Comment(**attrs) 
     comment.commenter_password = commenter_pw 

     return comment 
+0

Ồ! Nó đã giúp tôi, rất hữu ích! thx – brunozrk

+0

Điều này không hiệu quả đối với tôi. Tôi nhận được: đối tượng 'Nhận xét' không có thuộc tính 'commenter_pw' –

+0

OK. Tôi phải đặt write_only = True –

0

Điều bạn có thể làm là ghi đè pre_save hoặc create chức năng và đưa ra các commenter_pw từ các trường dữ liệu được gửi (không chắc chắn, nhưng bạn có thể mang nó ra dạng request.POST hoặc sau khi bạn đã tuần tự hóa nó), do đó, khuôn khổ không nên tăng lỗi.

Ngoài ra, nếu bạn có logic bổ sung, bạn có thể triển khai ở đó trước khi lưu (chẳng hạn như để kiểm tra xem người dùng có được tạo hay không).

+0

Tôi đã thử điều đó và dường như nó không hoạt động. – tlovett1

2

Cám ơn câu trả lời của riêng bạn, nó giúp cho tôi một rất nhiều :)

Nhưng tôi nghĩ rằng đây là chung chung hơn một chút, vì tôi vẫn muốn gọi phương thức trên lớp serializer siêu

def restore_object(self, attrs, instance=None): 
    ''' 
    we have to ensure that the temporary_password is attached to the model 
    even though it is no field 
    ''' 
    commenter_pw = attrs.pop('comment_pw', None) 
    obj = super(
     CommentCreateSerializer, self 
    ).restore_object(attrs, instance=instance) 
    if commenter_pw: 
     obj.commenter_pw = commenter_pw 
    return obj 
6

answ trước ers không hoạt động trên DRF3.0, phương thức restore_object() hiện không còn được dùng nữa.

Giải pháp tôi đã sử dụng là khủng khiếp nhưng tôi chưa tìm thấy giải pháp tốt hơn. Tôi đã đặt một bộ khởi động giả/setter cho trường này trên mô hình, điều này cho phép sử dụng trường này như bất kỳ trường nào khác trên mô hình.

Hãy nhớ đặt trường là write_only trên định nghĩa bộ nối tiếp.

class Comment(models.Model): 
    @property 
    def commenter_pw(): 
     return None 

    @commenter_pw.setter 
    def commenter_pw(self, value): 
     pass 

class CommentCreateSerializer(serializers.ModelSerializer): 
    commenter_pw = serializers.CharField(max_length=32, write_only=True, required=False) 

    class Meta: 
     model = Comment 
     fields = ('email', 'author', 'url', 'content', 'ip', 'post_title', 'post_url', 'commenter_pw') 
Các vấn đề liên quan