2017-06-29 7 views
1

バックストーリーは3つのフィールドを含むモデルです。 1つはデフォルトで塗りつぶされ、もう1つはAPIリクエストで渡され、最後はビューで計算されます。私はrequest.dataと計算された値の両方をシリアライザに取り込む方法を理解できません。ここに私のモデルである:コンテキストとSerializerMethodFieldでシリアライザのフィールドを設定できません

import re 
from django.core.exceptions import ValidationError 
from django.core.validators import URLValidator 
from django.db import models 
from django.utils import timezone 

URL_MAX_SHORT_ID_LEN = 12 
# Maximum length for IE and several other search engines and protocols is 
# 2047/2048. 
URL_MAX_URL_LEN = 2047 

class URL(models.Model): 
    short_id = models.CharField(max_length=URL_MAX_SHORT_ID_LEN, primary_key=True) 
    url = models.URLField(max_length=URL_MAX_URL_LEN) 
    added_date = models.DateTimeField('date added', 
             default=timezone.now) 

    def clean(self): 
     # TODO: make max length and possible chars a setting or global variable 
     if re.match('^[a-zA-Z0-9]{1,' + str(URL_MAX_SHORT_ID_LEN) + '}$', self.short_id) is None: 
      raise ValidationError({'short_id': 
       'only a-zA-Z0-9 valid chars and max length of ' + 
            str(URL_MAX_SHORT_ID_LEN) 
      }) 

    def save(self, *args, **kwargs): 
     self.full_clean() 
     super(URL, self).save(*args, **kwargs) 

    def __str__(self): 
     return str(self.__class__) + ': ' + str(self.__dict__) 

ここのは私のシリアライザです:

from rest_framework import serializers 
from url_shortener.models import URL 

class URLSerializer(serializers.ModelSerializer): 
    short_id = serializers.SerializerMethodField() 

    class Meta: 
     model = URL 
     fields = ('short_id', 'url', 'added_date') 
     read_only_fields = ('added_date',) 

    def get_short_id(self, obj): 
     return self.context.get('short_id') 

シェルでのテストは、そのshort_idが空であるというエラーがスローされます。

>>> from url_shortener.serializers import * 
>>> from django.utils.six import BytesIO 
>>> from rest_framework.renderers import JSONRenderer 
>>> from rest_framework.parsers import JSONParser 
>>> 
>>> j = b'{"url":"https://gobin.io"}' 
>>> stream = BytesIO(j) 
>>> data = JSONParser().parse(stream) 
>>> s = URLSerializer(data=data, context={'short_id': 'asd123'}) 
>>> s.is_valid() 
True 
>>> s.validated_data 
OrderedDict([('url', 'https://gobin.io')]) 
>>> s.save() 
Traceback (most recent call last): 
    File "<console>", line 1, in <module> 
    File "/Users/jolly/git/lurl/myenv/lib/python3.5/site-packages/rest_framework/serializers.py", line 215, in save 
    self.instance = self.create(validated_data) 
    File "/Users/jolly/git/lurl/myenv/lib/python3.5/site-packages/rest_framework/serializers.py", line 916, in create 
    instance = ModelClass.objects.create(**validated_data) 
    File "/Users/jolly/git/lurl/myenv/lib/python3.5/site-packages/django/db/models/manager.py", line 85, in manager_method 
    return getattr(self.get_queryset(), name)(*args, **kwargs) 
    File "/Users/jolly/git/lurl/myenv/lib/python3.5/site-packages/django/db/models/query.py", line 394, in create 
    obj.save(force_insert=True, using=self.db) 
    File "/Users/jolly/git/lurl/lurl/url_shortener/models.py", line 27, in save 
    self.full_clean() 
    File "/Users/jolly/git/lurl/myenv/lib/python3.5/site-packages/django/db/models/base.py", line 1248, in full_clean 
    raise ValidationError(errors) 
django.core.exceptions.ValidationError: {'short_id': ['This field cannot be blank.', 'only a-zA-Z0-9 valid chars and max length of 12']} 

get_short_idが得ることはありませんようですと呼ばれる。私はそれに盛り上がりを入れた。それは決して投げられなかった。私は何が間違っているのか、これが私がやっていることをする正しい方法であるかどうかはわかりません。

答えて

0

SerializerMethodFieldはread onlyです。あなたは、通常のCharFieldですを使用して、代わりにビューでメソッドを保存することがシリアライザに値です渡すことができますビューで

class URLSerializer(serializers.ModelSerializer): 
    short_id = serializers.CharField() 

を:

s = URLSerializer(data=data) 
s.is_valid() 
s.save(short_id='asd123') 
+0

。 s.is_valid()を実行すると、falseになり、s.save()エラーが発生します。これはあなたの提案を使ったシリアライザですhttps://gobin.io/ECcE –

+0

@LukeJollyオプションのshort_idを作成しようとしています: 'serializers.CharField(必須= False)' – neverwalkaloner

0

私は最終的に右の検索語を発見し、similar stackoverflowを発見しました。私はそれが常に正しいかどうかはわかりませんが、私の場合、short_idは実際にはread_onlyです。だから私はextra_kwargsと私の私のシリアライザ製:

from rest_framework import serializers 
from url_shortener.models import URL, URL_MAX_SHORT_ID_LEN 

class URLSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = URL 
     fields = ('short_id', 'url', 'added_date') 
     read_only_fields = ('added_date',) 
     extra_kwargs = { 
      'short_id' : {'read_only' : True} 
     } 

をしてから検証し、このようにそれを保存した:私はかなりそれをやって始まった

s = URLSerializer(data=data) 
s.is_valid() 
s.save(short_id='asd123') 
関連する問題