2016-05-15 41 views
11

Tôi đang gặp sự cố khi cập nhật đối tượng lồng nhau.Django-Rest-Framework. Cập nhật đối tượng lồng nhau

Vì vậy, tôi có một mô hình mà cấu trúc tương tự như thế này:

class Invoice(models.Model): 
    nr = models.CharField(max_length=100) 
    title = models.CharField(max_length=100) 

class InvoiceItem(models.Model): 
    name = models.CharField(max_length=100) 
    price = models.FloatField() 
    invoice = models.ForeignKey(Invoice, related_name='items') 

tôi cần phải tạo đối tượng trẻ em từ cha mẹ, và những gì tôi có ý nghĩa bởi đó, là tạo ra InvoiceItems trực tiếp khi tạo một đối tượng Invoice . Với mục đích này, tôi đã viết serializers sau:

class InvoiceItemSerializer(serializers.ModelSerializer): 
    invoice = serializers.PrimaryKeyRelatedField(queryset=Invoice.objects.all(), required=False) 
    class Meta: 
     model = InvoiceItem 


class InvoiceSerializer(serializers.ModelSerializer): 
    items = InvoiceItemSerializer(many=True) 

    class Meta: 
     model = Invoice 

    def create(self, validated_data): 
     items = validated_data.pop('items', None) 
     invoice = Invoice(**validated_data) 
     invoice.save() 
     for item in items: 
      InvoiceItem.objects.create(invoice=invoice, **item) 
     return invoice 

Cho đến nay, tạo/đọc/xóa các phương pháp hoạt động hoàn hảo, ngoại trừ update. Tôi nghĩ rằng logic dưới đây nên chính xác, nhưng nó bỏ sót điều gì đó.

def update(self, instance, validated_data): 
    instance.nr = validated_data.get('nr', instance.nr) 
    instance.title = validated_data.get('title', instance.title) 
    instance.save() 

    # up till here everything is updating, however the problem appears here. 
    # I don't know how to get the right InvoiceItem object, because in the validated 
    # data I get the items queryset, but without an id. 

    items = validated_data.get('items') 
    for item in items: 
     inv_item = InvoiceItem.objects.get(id=?????, invoice=instance) 
     inv_item.name = item.get('name', inv_item.name) 
     inv_item.price = item.get('price', inv_item.price) 
     inv_item.save() 

    return instance 

Mọi trợ giúp sẽ thực sự được đánh giá cao.

+1

Có thể bạn sẽ phải chuyển pk như một phần của tải trọng. – dkarchmer

+0

Tôi đang chuyển, nhưng nó không có trong 'validated_data' – dimmg

+0

Bạn có thể hiển thị tải trọng của mình không? – dkarchmer

Trả lời

11

Đây là cách tôi đã hoàn thành tác vụ:

Tôi đã thêm trường id vào InvoiceItemSerializer

class InvoiceItemSerializer(serializers.ModelSerializer): 
    ... 
    id = serializers.IntegerField(required=False) 
    ... 

Và phương pháp cập nhật cho InvoiceSerializer

def update(self, instance, validated_data): 
    instance.nr = validated_data.get('nr', instance.nr) 
    instance.title = validated_data.get('title', instance.title) 
    instance.save() 

    items = validated_data.get('items') 

    if items: 
     for item in items: 
      item_id = item.get('id', None) 
      if item_id: 
       inv_item = InvoiceItem.objects.get(id=item_id, invoice=instance) 
       inv_item.name = item.get('name', inv_item.name) 
       inv_item.price = item.get('price', inv_item.price) 
       inv_item.save() 
      else: 
       InvoiceItem.objects.create(account=instance, **item) 

    return instance 

Cũng trong phương pháp create Tôi popping các id nếu nó được thông qua.

+0

Cảm ơn bạn đã lấy mẫu. Nhưng người dùng vui lòng không quên bắt ngoại lệ 'DoesNotExist' mà' inv_item = InvoiceItem.objects.get (id = item_id, invoice = instance) 'có thể tăng lên. – Merka

2

Gần đây, tôi đã gặp phải vấn đề tương tự. Con đường tôi giải quyết nó là để buộc các id là trường bắt buộc:

class MySerializer(serializers.ModelSerializer): 

    class Meta: 
     model = MyModel 
     fields = ('id', 'name', 'url',) 
     extra_kwargs = {'id': {'read_only': False, 'required': True}} 

Bằng cách này tôi đã có thể lấy ví dụ chính xác và cập nhật nó

+2

và điều gì sẽ xảy ra trong trường hợp phương thức 'create' trong đó' id' là thừa? – dimmg

0

Hãy thử

def update(self, instance, validated_data): 
    instance.nr = validated_data.get('nr', instance.nr) 
    instance.title = validated_data.get('title', instance.title) 
    instance.save() 


    items = validated_data.get('items') 
    for item in items: 
     inv_item = InvoiceItem.objects.get(invoice=instance, pk=item.pk) 
     inv_item.name = item.get('name', inv_item.name) 
     inv_item.price = item.get('price', inv_item.price) 
     inv_item.invoice = instance 
     inv_item.save() 

    instance.save() 
    return instance 
Các vấn đề liên quan