2013-08-23 33 views
91

Tôi muốn serialize một mô hình, nhưng muốn bao gồm một trường bổ sung mà đòi hỏi phải thực hiện một số tra cứu cơ sở dữ liệu về các trường hợp mô hình để được tuần tự:Django REST của khung: thêm trường bổ sung để ModelSerializer

class FooSerializer(serializers.ModelSerializer): 
    my_field = ... # result of some database queries on the input Foo object 
    class Meta: 
     model = Foo 
     fields = ('id', 'name', 'myfield') 

là gì đúng cách để làm điều này? Tôi thấy rằng you can pass in extra "context" đến serializer, là câu trả lời đúng để vượt qua trong lĩnh vực bổ sung trong một từ điển ngữ cảnh? Với cách tiếp cận đó, logic của việc nhận được trường tôi cần sẽ không được khép kín với định nghĩa serializer, điều này lý tưởng vì mọi trường hợp được tuần tự hóa sẽ cần my_field. Ở những nơi khác trong tài liệu tuần tự DRF tài liệu nó says "trường bổ sung có thể tương ứng với bất kỳ tài sản hoặc có thể gọi trên mô hình". Có phải những lĩnh vực phụ mà tôi đang nói đến không? Tôi có nên định nghĩa một hàm trong định nghĩa mô hình của Foo trả về giá trị my_field và trong bộ nối tiếp tôi kết nối my_field với hàm đó có thể gọi được không? Điều đó giống như thế nào?

Xin cảm ơn trước, vui lòng làm rõ câu hỏi nếu cần.

Trả lời

158

Tôi nghĩ SerializerMethodField là những gì bạn đang tìm kiếm:

class FooSerializer(serializers.ModelSerializer): 
    my_field = serializers.SerializerMethodField('is_named_bar') 

    def is_named_bar(self, foo): 
     return foo.name == "bar" 

    class Meta: 
    model = Foo 
    fields = ('id', 'name', 'my_field') 

http://www.django-rest-framework.org/api-guide/fields/#serializermethodfield

+0

+1, Điều đó cũng có hiệu quả đối với Trình tùy chỉnh không? –

+12

có thể thêm xác thực vào các trường như vậy không? câu hỏi của tôi là: làm thế nào để chấp nhận các giá trị POST tùy chỉnh có thể được xác nhận và xử lý trong trình xử lý post_save()? – Alp

+7

Lưu ý rằng SerializerMethodField là chỉ đọc, do đó, điều này sẽ không hoạt động cho POST/PUT/PATCH. –

29

Bạn có thể thay đổi phương thức mô hình thành thuộc tính và sử dụng nó trong bộ nối tiếp với phương pháp này.

Chỉnh sửa: Với phiên bản mới nhất của khung còn lại (tôi đã thử 3.3.3), bạn không cần phải thay đổi thuộc tính. Phương pháp mô hình sẽ hoạt động tốt.

+0

Cảm ơn @Wasil! Tôi không quen thuộc với việc sử dụng tài sản trong mô hình Django, và không thể tìm thấy lời giải thích tốt về ý nghĩa của nó. Bạn có thể giải thích? Điểm của trang trí @property ở đây là gì? – Neil

+2

có nghĩa là bạn có thể gọi phương thức này như một thuộc tính: tức là 'biến = model_instance.my_field' cho kết quả tương tự như' variable = model_instance.my_field() 'mà không có trình trang trí. cũng: http://stackoverflow.com/a/6618176/2198571 –

+0

Điều này không hoạt động, ít nhất là trong Django 1.5.1/djangorestframework == 2.3.10. Các ModelSerializer không nhận được propery ngay cả khi explictly gọi trong "lĩnh vực" Meta thuộc tính. – ygneo

8

phản ứng của tôi với một câu hỏi tương tự (here) có thể có ích.

Nếu bạn có một phương pháp mô hình được xác định theo cách sau:

class MyModel(models.Model): 
    ... 

    def model_method(self): 
     return "some_calculated_result" 

Bạn có thể thêm kết quả của phương pháp gọi nói với serializer của bạn như vậy:

class MyModelSerializer(serializers.ModelSerializer): 
    model_method_field = serializers.CharField(source='model_method') 

tái bút: Kể từ khi lĩnh vực tùy chỉnh là không thực sự là một lĩnh vực trong mô hình của bạn, bạn sẽ thường muốn làm cho nó read-only, như vậy:

class Meta: 
    model = MyModel 
    read_only_fields = (
     'model_method_field', 
     ) 
7

Với phiên bản cuối cùng của Django Nghỉ ngơi Framework, bạn cần phải tạo ra một trong mô hình của bạn với tên của trường bạn muốn thêm vào. Không cần @propertysource='field' tăng lỗi.

class Foo(models.Model): 
    . . . 
    def foo(self): 
     return 'stuff' 
    . . . 

class FooSerializer(ModelSerializer): 
    foo = serializers.ReadOnlyField() 

    class Meta: 
     model = Foo 
     fields = ('foo',) 
Các vấn đề liên quan