Cách thay đổi tên trường trong Django REST Framework


98

Tôi đang cố gắng thay đổi tên trường Model trong DRF Serializer giống như bí danh trong SQL. Tôi đã thử các phương pháp khác nhau nhưng không thể thành công.

models.py

class Park(models.Model):
    name = models.CharField(max_length=256)
    alternate_name = models.CharField(max_length=256, blank=True)
    objects = models.GeoManager()

    class Meta:
        db_table = u'p_park'

    def __unicode__(self):
        return '%s' % self.name

    def alias_alternate_name(self):
        return self.alternate_name

serializers.py

class ParkSerializer(serializers.ModelSerializer):

    location = serializers.Field(source='alias_alternate_name')
    #location = serializers.SerializerMethodField(source='alias_alternate_name')

    #alternate_name as location


    class Meta:
        model = Park
        fields = ('id', 'name', 'location')

Tôi cũng đã thử thêm bí danh trong Django Queryset nhưng không thể thay đổi.

Đã cập nhật

Đây là ngoại lệ mà tôi đang phải đối mặt

Đối tượng AttributeError tại / ViewName / 'module' không có thuộc tính 'Field'

Tôi có thể làm cái này như thế nào?


1
Bạn có đang sử dụng cách triển khai đúng serializers.SerializerMethodFieldcách không? Ý tôi là thế này: serializers.SerializerMethodField('get_location')def get_location(self, obj): ...
erthalion

Chúng ta có thể xem nhập khẩu của serializers.py?
joerick

sẽ downvote câu hỏi vì OP chấp nhận một câu trả lời một phần sai lầm và khó hiểu thay vì những cái tốt hơn dưới đây ...
NeuronQ

Câu trả lời:


58

Bạn có thể sử dụng serializers.SerializerMethodField:

Đây là mô hình Park, có các trường name và alternate_name.

class Park(models.Model):
    name = models.CharField(max_length=256)
    alternate_name = models.CharField(max_length=256, blank=True)
    objects = models.GeoManager()

    class Meta:
        db_table = u'p_park'

    def __unicode__(self):
        return '%s' % self.name

Đây là Serializer cho Park Model, ParkSerializer. Điều này thay đổi tên của alternate_name thành vị trí.

class ParkSerializer(serializers.ModelSerializer):
    location = serializers.SerializerMethodField('get_alternate_name')

    class Meta:
        model = Park
        fields = ('other_fields', 'location')

    def get_alternate_name(self, obj):
        return obj.alternate_name

Ngoài ra, bạn có thể sử dụng serializers.CharFieldvới sourcethuộc tính:

class ParkSerializer(serializers.ModelSerializer):
    location = serializers.CharField(source='other_fields')

    class Meta:
        model = Park
        fields = ('other_fields', 'location')

__Ký hiệu của Django để duyệt khóa ngoại cũng hoạt động:

location = serializers.CharField(source='OtherModel__other_fields')

Nguyên tắc tương tự cũng áp dụng nếu bạn muốn thay đổi kiểu trả về trên API, vì vậy bạn có thể thực hiện serializers.DecimalField(source=...)và cả các kiểu trường khác.

Tuy nhiên, điều này sẽ chỉ hoạt động cho các trường chỉ đọc.


Bây giờ ngoại lệ này đang ném AttributeError vào đối tượng / ViewName / 'module' không có thuộc tính 'SerializerMethodField'
Shoaib Ijaz

1
Làm thế nào để tập luyện này với các yêu cầu tạo và chỉnh sửa?
iankit

1
Dòng số 13 của 'Zen of Python': "Nên có một - và tốt nhất là chỉ có một - cách dễ dàng để làm điều đó."
iankit

14
Đây không phải là câu trả lời được chấp nhận. Hãy xem hình dưới đây, có gần gấp 5 lần số phiếu ủng hộ tại thời điểm tôi viết bài này.
cderwin

6
Đây là một giải pháp tồi. Sử dụng sourcekwarg thay thế như mô tả bên dưới.
Patrick

215

Có một tính năng rất hay trong các trường serializer và serializers nói chung được gọi là 'nguồn', nơi bạn có thể chỉ định nguồn dữ liệu từ trường mô hình.

class ParkSerializer(serializers.ModelSerializer):
    location = serializers.SomeSerializerField(source='alternate_name')

    class Meta:
        model = Park
        fields = ('other_fields', 'location')

Nơi serializers.SomeSerializerField có thể là serializers.CharField như mô hình của bạn đề xuất nhưng cũng có thể bởi bất kỳ trường nào khác. Ngoài ra, bạn có thể đặt các trường quan hệ và các trình tuần tự khác để thay thế và điều này vẫn hoạt động như một sự quyến rũ. tức là ngay cả khi alternate_name là một trường khóa ngoại đối với một mô hình khác.

class ParkSerializer(serializers.ModelSerializer):
    locations = AlternateNameSerializer(source='alternate_name', many=true)

    class Meta:
        model = Park
        fields = ('other_fields', 'locations')

class AlternateNameSerializer(serializers.ModelSerialzer):
    class Meta:
        model = SomeModel

Điều này cũng hoạt động với việc tạo, xóa và sửa đổi loại yêu cầu. Nó tạo một cách hiệu quả ánh xạ tên trường trong bộ tuần tự và tên trường trong các mô hình.


Tôi đồng ý, đó sourcelà cách tiếp cận tổng quát hơn. Nhưng bạn có thể thấy một vài nỗ lực sử dụng nó trong câu hỏi, vì vậy nếu bạn muốn trả lời theo cách đó, bạn cũng nên nói rõ tại sao mã gốc không hoạt động, phải không?
erthalion

Mã của bạn sẽ hoạt động tốt .. miễn là yêu cầu là cho danh sách và lấy
iankit

Cả hai câu trả lời đều không đầy đủ. Trong trường hợp khóa ngoại, phương thức này ngụ ý rằng khi tạo một Park mới, bạn phải cung cấp toàn bộ đối tượng cha (tên_trách_hóa) làm chính tả trong yêu cầu POST của bạn, điều này rất điên rồ vì đối tượng cha đã tồn tại. Người ta có thể đề cập đến phiên bản nước ngoài thông qua id của nó.
stelios

Trong trường hợp của tôi (khóa ngoại), tôi đã giải quyết vấn đề này với locations = serializers.PrimaryKeyRelatedField(source='alternate_name', queryset=AlternateName.objects.all()). Rõ ràng RelatedFieldcũng có thể được sử dụng.
stelios

@chefarov source = 'new_name' là một đối số chung chung mà bạn có thể đưa ra cho các trường serializer, các quan hệ và các serializers liên quan khác, v.v. Không chắc tại sao bạn nói câu trả lời là không đầy đủ.
iankit

15

Điều này cũng sẽ hoạt động cho các hoạt động ghi

class ParkSerializer(serializers.ModelSerializer):
    location = serializers.CharField(source='alternate_name')

    class Meta:
        model = Park
        fields = ('id', 'name', 'location')
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.