Utworzyłem ModelSerializer
i chcę dodać pole niestandardowe, które nie jest częścią mojego modelu.
Znalazłem opis, aby dodać dodatkowe pola tutaj i starałem się następujące elementy:
customField = CharField(source='my_field')
Kiedy dodam to pole i wywołam moją validate()
funkcję, to pole nie jest częścią attr
dyktatu. attr
zawiera wszystkie określone zmienne modelu z wyjątkiem pól dodatkowych. Więc nie mogę uzyskać dostępu do tego pola w mojej nadpisanej walidacji, prawda?
Kiedy dodam to pole do listy pól w następujący sposób:
class Meta:
model = Account
fields = ('myfield1', 'myfield2', 'customField')
wtedy customField
pojawia się błąd, ponieważ nie jest częścią mojego modelu - co jest poprawne, ponieważ chcę go dodać tylko dla tego serializatora.
Czy istnieje sposób na dodanie niestandardowego pola?
Odpowiedzi:
Robisz dobrze, z wyjątkiem tego, że
CharField
(i inne wpisane pola) są przeznaczone do pól zapisywalnych.W tym przypadku potrzebujesz prostego pola tylko do odczytu, więc zamiast tego użyj:
customField = Field(source='get_absolute_url')
źródło
.validate()
metody, aby usunąć atrybut. Zobacz: django-rest-framework.org/api-guide/serializers.html#validation To zrobi to, czego potrzebujesz, chociaż tak naprawdę nie rozumiem przypadku użycia lub dlaczego chcesz, aby pole do zapisu, które było powiązane z właściwość tylko do odczytuget_absolute_url
?get_absolute_url
skopiowaniu i wklejeniu go z dokumentów. Chcę tylko normalnego pola do zapisu, do którego mam dostęp wvalidate()
. Zgadłem, że będę potrzebowałsource
atrybutu ...W rzeczywistości istnieje rozwiązanie bez dotykania modelu. Możesz użyć
SerializerMethodField
które pozwalają na podłączenie dowolnej metody do twojego serializatora.class FooSerializer(ModelSerializer): foo = serializers.SerializerMethodField() def get_foo(self, obj): return "Foo id: %i" % obj.pk
źródło
SerializerMethodField
nie ma... dla jasności, jeśli masz metodę modelu zdefiniowaną w następujący sposób:
class MyModel(models.Model): ... def model_method(self): return "some_calculated_result"
Możesz dodać wynik wywołania tej metody do swojego serializatora w następujący sposób:
class MyModelSerializer(serializers.ModelSerializer): model_method_field = serializers.CharField(source='model_method')
ps Ponieważ pole niestandardowe nie jest tak naprawdę polem w Twoim modelu, zazwyczaj będziesz chciał ustawić je jako tylko do odczytu, na przykład:
class Meta: model = MyModel read_only_fields = ( 'model_method_field', )
źródło
perform_create(self, serializer)
,perform_update(self, serializer)
,perform_destroy(self, instance)
.tutaj odpowiedź na twoje pytanie. należy dodać do swojego modelu Konto:
@property def my_field(self): return None
teraz możesz użyć:
customField = CharField(source='my_field')
źródło: https://stackoverflow.com/a/18396622/3220916
źródło
Aby pokazać
self.author.full_name
, wystąpił błąd zField
. Działało zReadOnlyField
:class CommentSerializer(serializers.HyperlinkedModelSerializer): author_name = ReadOnlyField(source="author.full_name") class Meta: model = Comment fields = ('url', 'content', 'author_name', 'author')
źródło
W ostatniej wersji Django Rest Framework musisz stworzyć w swoim modelu metodę z nazwą pola, które chcesz dodać.
class Foo(models.Model): . . . def foo(self): return 'stuff' . . . class FooSerializer(ModelSerializer): foo = serializers.ReadOnlyField() class Meta: model = Foo fields = ('foo',)
źródło
Szukałem rozwiązania umożliwiającego dodanie zapisywalnego pola niestandardowego do serializatora modelu. Znalazłem ten, który nie został uwzględniony w odpowiedziach na to pytanie.
Wygląda na to, że naprawdę musisz napisać swój własny prosty Serializer.
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
Teraz możesz użyć tego serializatora, aby dodać niestandardowe pola do 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
Działa to również, jeśli Model
MyModel
faktycznie ma właściwość o nazwie,my_custom_field
ale chcesz zignorować jej walidatory.źródło
MyModel
instancji.Po przeczytaniu wszystkich odpowiedzi tutaj dochodzę do wniosku, że nie można tego zrobić czysto. Musisz grać nieczysto i zrobić coś szalonego, jak utworzenie pola write_only, a następnie nadpisać metody
validate
ito_representation
. Oto, co zadziałało dla mnie: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
źródło