Saya membuat ModelSerializer
dan ingin menambahkan bidang khusus yang bukan bagian dari model saya.
Saya menemukan deskripsi untuk menambahkan bidang ekstra di sini dan saya mencoba yang berikut:
customField = CharField(source='my_field')
Saat saya menambahkan bidang ini dan memanggil validate()
fungsi saya maka bidang ini bukan bagian dari attr
dict. attr
berisi semua bidang model yang ditentukan kecuali bidang ekstra. Jadi saya tidak dapat mengakses bidang ini dalam validasi yang ditimpa, bukan?
Ketika saya menambahkan bidang ini ke daftar bidang seperti ini:
class Meta:
model = Account
fields = ('myfield1', 'myfield2', 'customField')
kemudian saya mendapatkan error karena customField
bukan bagian dari model saya - apa yang benar karena saya ingin menambahkannya hanya untuk serializer ini.
Apakah ada cara untuk menambahkan bidang khusus?
Jawaban:
Anda melakukan hal yang benar, kecuali bahwa
CharField
(dan kolom lain yang diketik) adalah untuk kolom yang bisa ditulis.Dalam hal ini Anda hanya menginginkan bidang hanya baca sederhana, jadi gunakan saja:
customField = Field(source='get_absolute_url')
sumber
.validate()
metode untuk menghapus atribut. Lihat: django-rest-framework.org/api-guide/serializers.html#validation Itu akan melakukan apa yang Anda butuhkan, meskipun saya tidak benar-benar memahami kasus penggunaan, atau mengapa Anda menginginkan bidang yang dapat ditulis yang terkait dengan properti read-onlyget_absolute_url
?get_absolute_url
Saya baru saja menyalin & menempelkannya dari dokumen. Saya hanya ingin bidang yang dapat ditulis normal yang dapat saya akses divalidate()
. Saya hanya menebak bahwa saya membutuhkansource
atribut ...Ternyata ada solusinya tanpa menyentuh sama sekali modelnya. Anda dapat menggunakan
SerializerMethodField
yang memungkinkan Anda untuk menyambungkan metode apa pun ke serializer Anda.class FooSerializer(ModelSerializer): foo = serializers.SerializerMethodField() def get_foo(self, obj): return "Foo id: %i" % obj.pk
sumber
SerializerMethodField
bukan... untuk kejelasan, jika Anda memiliki Metode Model yang ditentukan dengan cara berikut:
class MyModel(models.Model): ... def model_method(self): return "some_calculated_result"
Anda dapat menambahkan hasil dari memanggil metode tersebut ke serializer Anda seperti:
class MyModelSerializer(serializers.ModelSerializer): model_method_field = serializers.CharField(source='model_method')
ps Karena bidang khusus sebenarnya bukan bidang dalam model Anda, Anda biasanya ingin membuatnya menjadi hanya-baca, seperti:
class Meta: model = MyModel read_only_fields = ( 'model_method_field', )
sumber
perform_create(self, serializer)
,perform_update(self, serializer)
,perform_destroy(self, instance)
.di sini menjawab pertanyaan Anda. Anda harus menambahkan ke akun model Anda:
@property def my_field(self): return None
sekarang Anda dapat menggunakan:
customField = CharField(source='my_field')
sumber: https://stackoverflow.com/a/18396622/3220916
sumber
Untuk menunjukkan
self.author.full_name
, saya mendapat kesalahan denganField
. Ini bekerja denganReadOnlyField
:class CommentSerializer(serializers.HyperlinkedModelSerializer): author_name = ReadOnlyField(source="author.full_name") class Meta: model = Comment fields = ('url', 'content', 'author_name', 'author')
sumber
Dengan versi terakhir Django Rest Framework, Anda perlu membuat metode dalam model Anda dengan nama bidang yang ingin Anda tambahkan.
class Foo(models.Model): . . . def foo(self): return 'stuff' . . . class FooSerializer(ModelSerializer): foo = serializers.ReadOnlyField() class Meta: model = Foo fields = ('foo',)
sumber
Saya sedang mencari solusi untuk menambahkan bidang kustom yang dapat ditulis ke serializer model. Saya menemukan yang satu ini, yang belum tercakup dalam jawaban atas pertanyaan ini.
Sepertinya Anda memang perlu membuat Serializer sederhana Anda sendiri.
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
Sekarang Anda dapat menggunakan Serializer ini untuk menambahkan kolom kustom ke ModelSerializer
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
Ini juga berfungsi, jika Model
MyModel
benar-benar memiliki properti yang dipanggilmy_custom_field
tetapi Anda ingin mengabaikan validatornya.sumber
MyModel
instance.Setelah membaca semua jawaban di sini, kesimpulan saya adalah tidak mungkin melakukan ini dengan bersih. Anda harus bermain kotor dan melakukan sesuatu yang hadkish seperti membuat bidang write_only dan kemudian mengganti metode
validate
danto_representation
. Inilah yang berhasil untuk saya: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
sumber