জ্যাঙ্গো রেস্ট ফ্রেমওয়ার্ক - মডেলশিরাইজারে কীভাবে কাস্টম ফিল্ড যুক্ত করা যায়


89

আমি একটি তৈরি করেছি ModelSerializerএবং একটি কাস্টম ফিল্ড যুক্ত করতে চাই যা আমার মডেলের অংশ নয়।

আমি এখানে অতিরিক্ত ক্ষেত্র যুক্ত করতে একটি বিবরণ পেয়েছি এবং আমি নিম্নলিখিতটি চেষ্টা করেছি:

customField = CharField(source='my_field')

আমি যখন এই ক্ষেত্রটি যুক্ত করব এবং আমার validate()ফাংশনটি কল করব তখন এই ক্ষেত্রটি attrডিকের অংশ নয় । attrঅতিরিক্ত ক্ষেত্রগুলি বাদে নির্দিষ্ট সমস্ত মডেল ক্ষেত্র রয়েছে। সুতরাং আমি আমার ওভাররাইট বৈধকরণে এই ক্ষেত্রটি অ্যাক্সেস করতে পারি না, আমি কি পারি?

আমি যখন এই ক্ষেত্রটিকে ফিল্ড তালিকায় যুক্ত করব:

class Meta:
    model = Account
    fields = ('myfield1', 'myfield2', 'customField')

তারপরে আমি একটি ত্রুটি পেয়েছি কারণ customFieldএটি আমার মডেলের অংশ নয় - সঠিক কি কারণ আমি এটিকে কেবল এই সিরিয়ালের জন্য যুক্ত করতে চাই।

কাস্টম ক্ষেত্র যুক্ত করার কোনও উপায় আছে?


আপনি কীভাবে প্রসারিত করতে পারেন "তবে যখন আমার ক্ষেত্রটি সিরিয়ালে বর্ণিত মডেল ফিল্ড তালিকায় নেই তবে এটি বৈধতা () অ্যাটর-অভিধানের অংশ নয়" ", আমি নিশ্চিত নই যে এটি খুব পরিষ্কার।
টম ক্রিস্টি

এছাড়াও "এটি অভিযোগ করে - সঠিকভাবে - যে আমার মডেলটিতে আমার কোনও ফিল্ড কাস্টমফিল্ড নেই,", আপনি কী ব্যতিক্রমটি দেখেছেন তা স্পষ্ট করে বলতে পারেন - ধন্যবাদ! :)
টম ক্রিস্টি

আমি আমার পোস্ট আপডেট করেছি এবং আশা করি এটি আরও পরিষ্কার হয়ে গেছে। আমি কেবল জানতে চাই যে আমি কীভাবে এমন একটি ক্ষেত্র যুক্ত করতে পারি যা আমার মডেলের অংশ নয় ...
রন


উত্তর:


63

আপনি সঠিক জিনিসটি করছেন, ব্যতীত CharField(এবং অন্যান্য টাইপ করা ক্ষেত্রগুলি) লিখনযোগ্য ক্ষেত্রগুলির জন্য।

এক্ষেত্রে আপনি কেবল একটি সাধারণ পঠনযোগ্য ক্ষেত্র চান, সুতরাং পরিবর্তে কেবল ব্যবহার করুন:

customField = Field(source='get_absolute_url')

4
ধন্যবাদ, তবে আমি একটি লেখার ক্ষেত্র চাই। আমি একটি নির্দিষ্ট ব্যবহারকারীর টোকেন পাস করি যা আমার ব্যবহারকারীকে সনাক্ত করে। তবে আমার মডেলটিতে আমার ব্যবহারকারী রয়েছে এবং টোকেনটি নেই। সুতরাং আমি টোকনটি পাস করতে এবং এটি একটি প্রশ্নের মাধ্যমে কোনও ব্যবহারকারী সামগ্রীতে "রূপান্তর" করতে চাই।
রন

পরবর্তী জিনিসটি কি সেই উত্সটির একটি মডেল বৈশিষ্ট্যকে লক্ষ্য করা দরকার, তাই না? আমার ক্ষেত্রে আমি উল্লেখ করতে একটি বৈশিষ্ট্য আছে না।
রন

আমি মন্তব্যটির ব্যবহারকারী / টোকেন বিটটি বুঝতে পারি না। আপনি যদি কোনও মডেল উদাহরণে পুনরুদ্ধার করার আগে সিরিয়ালাইজারের কোনও ক্ষেত্রকে ছিনিয়ে নিতে চান তবে আপনি .validate()বৈশিষ্ট্যটি অপসারণ করতে এই পদ্ধতিটি ব্যবহার করতে পারেন । দেখুন: django-rest-framework.org/api-guide/serializers.html# માન્યকরণ এটি আপনার প্রয়োজন অনুসারে করতে হবে, যদিও আমি সত্যিই ব্যবহারের কেসটি বুঝতে পারি না বা আপনি কেন এমন একটি লেখার ক্ষেত্র চান যা একটি সাথে আবদ্ধ কেবল পঠন সম্পত্তি get_absolute_url?
টম ক্রিস্টি

get_absolute_urlআমি ডকস থেকে এটি অনুলিপি করে কাস্ট করে ফেলেছি সম্পর্কে ভুলে যান । আমি কেবলমাত্র একটি সাধারণ লিখনযোগ্য ক্ষেত্র চাই যা আমি প্রবেশ করতে পারি validate()। আমি শুধু খেয়াল হল যে, আমি প্রয়োজন চাই sourceঅ্যাট্রিবিউট ...
রন

এটি আরও অর্থবোধ করে। :) মানটি যাচাইকরণের জন্য দিয়ে যাওয়া উচিত, সুতরাং আপনি কীভাবে সিরিয়ালাইজারটি ইনস্ট্যান্ট করছেন এবং এটির মানটি যদি সত্যিই সরবরাহ করা হচ্ছে তবে আমি দ্বিগুণ পরীক্ষা করে দেখতে চাই।
টম ক্রিস্টি

85

সমস্ত মডেল স্পর্শ না করে আসলে একটি সমাধান আছে। আপনি ব্যবহার করতে পারেন SerializerMethodFieldযা আপনার সিরিয়ালাইজারে কোনও পদ্ধতি প্লাগ করতে দেয়।

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

    def get_foo(self, obj):
        return "Foo id: %i" % obj.pk

6
ওপি যেমন এই মন্তব্যে উল্লিখিত হয়েছে , তারা একটি লিখনযোগ্য ক্ষেত্র চান, যা SerializerMethodFieldএগুলি নয়
ইসমাইল

14

... স্পষ্টতার জন্য, আপনার যদি নিম্নলিখিত পদ্ধতিতে কোনও মডেল পদ্ধতি সংজ্ঞায়িত করা থাকে:

class MyModel(models.Model):
    ...

    def model_method(self):
        return "some_calculated_result"

আপনি আপনার সিরিয়ালাইজারে বলার পদ্ধতিটি কল করার ফলাফলটি এমনভাবে যুক্ত করতে পারেন:

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

PS যেহেতু কাস্টম ক্ষেত্রটি আপনার মডেলের কোনও ক্ষেত্র নয়, আপনি সাধারণত এটিকে কেবল পঠনযোগ্য করতে চাইবেন:

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

4
আমি যদি এটি লেখার যোগ্য হতে চাই?
সিসাবা টথ

4
@Csaba: আপনি শুধু লেখার কাস্টম সংরক্ষণ এবং অতিরিক্ত বিষয়বস্তুর জন্য মুছে ফেলার আঙ্গুলসমূহ করতে হবে: "পদ্ধতি" এর অধীনে দেখুন "সংরক্ষণ করুন এবং মোছা আঙ্গুলসমূহ" ( এখানে ) আপনি লিখতে কাস্টম করতে হবে perform_create(self, serializer), perform_update(self, serializer), perform_destroy(self, instance)
লিন্ডাউসন

13

আপনার প্রশ্নের উত্তর এখানে। আপনার আপনার মডেল অ্যাকাউন্টে যুক্ত করা উচিত:

@property
def my_field(self):
    return None

এখন আপনি ব্যবহার করতে পারেন:

customField = CharField(source='my_field')

উত্স: https://stackoverflow.com/a/18396622/3220916


6
আমি এই পদ্ধতির ব্যবহারটি করেছি যখন এটি বোধগম্য হয় তবে এমন কিছু মডেলগুলিতে অতিরিক্ত কোড যুক্ত করা ভাল নয় যা কেবলমাত্র নির্দিষ্ট এপিআই কলগুলির জন্য ব্যবহৃত হয়।
অ্যান্ডি বেকার

4
আপনি
আশ

10

দেখাতে self.author.full_name, আমি এর সাথে একটি ত্রুটি পেয়েছি Field। এটি এর সাথে কাজ করেছে ReadOnlyField:

class CommentSerializer(serializers.HyperlinkedModelSerializer):
    author_name = ReadOnlyField(source="author.full_name")
    class Meta:
        model = Comment
        fields = ('url', 'content', 'author_name', 'author')

6

জ্যাঙ্গো রেস্ট ফ্রেমওয়ার্কের শেষ সংস্করণটি সহ, আপনি যে ক্ষেত্রটি যুক্ত করতে চান তার নাম সহ আপনার মডেলটিতে একটি পদ্ধতি তৈরি করতে হবে।

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

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

    class Meta:
        model = Foo
        fields = ('foo',)

4

আমি একটি মডেল সিরিয়ালাইজে লিখনযোগ্য কাস্টম ফিল্ড যুক্ত করার জন্য একটি সমাধান খুঁজছিলাম। আমি এটি পেয়েছি, যা এই প্রশ্নের উত্তরে আওতাভুক্ত হয়নি।

দেখে মনে হচ্ছে আপনার নিজের সাধারণ সিরিয়ালাইজারটি লিখতে হবে।

class PassThroughSerializer(serializers.Field):
    def to_representation(self, instance):
        # This function is for the direction: Instance -> Dict
        # If you only need this, use a ReadOnlyField, or SerializerField
        return None

    def to_internal_value(self, data):
        # This function is for the direction: Dict -> Instance
        # Here you can manipulate the data if you need to.
        return data

এখন আপনি এই সিরিয়ালাইজারটি কোনও মডেলশিরাইজারে কাস্টম ক্ষেত্রগুলি যুক্ত করতে ব্যবহার করতে পারেন

class MyModelSerializer(serializers.ModelSerializer)
    my_custom_field = PassThroughSerializer()

    def create(self, validated_data):
        # now the key 'my_custom_field' is available in validated_data
        ...
        return instance

এটিও কাজ করে, যদি মডেলটির MyModelআসলে কোনও সম্পত্তি বলা হয় my_custom_fieldতবে আপনি এর বৈধতা যাচাইকারীদের উপেক্ষা করতে চান।


সুতরাং আমার_কাস্টম_ফিল্ড মাইমোডেলের সম্পত্তি না হলে এটি কাজ করে না? আমি ত্রুটি পেয়েছি সিরিয়ালাইজার ফিল্ডটি ভুলভাবে নামকরণ করা যেতে পারে এবং MyModelউদাহরণের সাথে কোনও বৈশিষ্ট্য বা কীটির সাথে মেলে না ।
সন্দীপ বালাগোপাল

3

এখানে সমস্ত উত্তর পড়ার পরে আমার উপসংহার এই যে এটি পরিষ্কারভাবে করা অসম্ভব। আপনাকে নোংরা খেলতে হবে এবং লেখার জন্য কেবল ক্ষেত্র তৈরি করার মতো কিছু কাজ করতে হবে এবং তারপরে পদ্ধতিগুলি validateএবং to_representationপদ্ধতিগুলিকে ওভাররাইড করতে হবে । এটিই আমার পক্ষে কাজ করেছে:

class FooSerializer(ModelSerializer):

    foo = CharField(write_only=True)

    class Meta:
        model = Foo
        fields = ["foo", ...]

    def validate(self, data):
        foo = data.pop("foo", None)
        # Do what you want with your value
        return super().validate(data)

    def to_representation(self, instance):
        data = super().to_representation(instance)
        data["foo"] = whatever_you_want
        return data
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.