2017-04-25 7 views
0

ユニーク= Trueのフィールドを持つモデルにFKでオブジェクトを作成していないビューでDjangoの残りのフレームワークは、私はこのような二つのモデル持って

を、I

address_serialized = AddressSerializer(data=request.data) 
    if address_serialized.is_valid(): 
     address_serialized.save(client=client) 

これは決してcreateになります。コードはFalseを返すis_valid()この機能を、触れることはありません

class AddressSerializer(serializers.ModelSerializer): 
    city_gps = CitySerializer(required=False) 
    sector = SectorSerializer(required=False) 

    class Meta: 
     model = Address 
     fields = (..., "sector") 

    def create(self, validated_data): 
     ... 
     sector_dict = validated_data.get("sector", None) 
     sector = None 

     if sector_dict and "name" in sector_dict and city_gps: 
      if Sector.objects.filter(name=sector_dict["name"], city=city_gps).exists(): 
       sector = Sector.objects.get(name=sector_dict["name"], city=city_gps) 

     # pdb.set_trace() 
     if "sector" in validated_data: 
      validated_data.pop("sector") 
     if "city_gps" in validated_data: 
      validated_data.pop("city_gps") 

     address = Address.objects.create(sector=sector, city_gps=city_gps, **validated_data) 

     return address 

:私はこのようになります作成機能付きシリアル化されています。私が使用して新しいアドレスを作成できるようにする必要があり

とメッセージが

{}:{「名前」[「この名前の部門がすでに存在している。」]「部門」}です既存のセクターへのFK。それをどうすれば実現できますか?どんな助言も役に立ちます。

EDITは

ビューは次のようになります。

class ClientProfileAddressCreateView(APIView): 
    # throttle_scope = '1persecond' 
    renderer_classes = (JSONRenderer,) 
    permission_classes = (IsAuthenticated,) 

    def post(self, request): 

     try: 
      client = Client.objects.get(user=request.user) 
     except ObjectDoesNotExist: 
      return Response({"error": "A client profile for the logged user does not exit"}, 
          status=status.HTTP_404_NOT_FOUND) 

     address_serialized = AddressSerializer(data=request.data) 
     print("address_serialized.is_valid: %s" % address_serialized.is_valid()) # Returns False when unique=True in models 
     if address_serialized.is_valid(): 
      # print("address_serialized: %s" % address_serialized.data) 
      address_serialized.save(client=client) 
     else: 
      return Response(data=address_serialized.errors, status=status.HTTP_400_BAD_REQUEST) 

     return Response(data=address_serialized.data, status=status.HTTP_201_CREATED) 
+1

無効なデータ –

+0

あなたの意見をお寄せくださいか?また、 '' 'serializer''の' '' required = True'''を変更すると何も変わりませんか? –

+0

また、dbにセクタエントリがないかブランクでチェックしてください。 –

答えて

2

これは、ネストされたシリアライザとユニーク制約の既知の問題です。

本当に素晴らしいことは、実際にはシリアライザを印刷することです - それはあなたに多くの追加情報を与えることができます。

あなたはこのようなJSONを持っている:

{ 
    "Sector": { 
     "name": "Sector XYZ" 
    }, 
    "address_line_one": “Some Random Address” 
} 

DjangoのRESTフレームワークは、このように、それはリクエストごとに検証を強制的に、あなたはセクターのオブジェクトを作成または取得しているかどうか分かりません。あなたがする必要がどのような

は次のとおりです。

class SectorSerializer(serializers.ModelSerializer): 
    # Your fields. 
    class Meta: 
     model = Address 
     fields = ("Your Fields",) 

     extra_kwargs = { 
      'name': { 
       'validators': [], 
      } 
     } 

次にあなたが一意性制約に合わせ、例外/検証エラーを上げるために作成/更新部をやり直す必要があります検証を処理します。

こちらがお役に立てば幸いです。

参考リンク:This SO AnswerDealing with unique constraints in nested serializers

EDIT:セザールの要求を1として

:私はそれは、シリアライザのcreateメソッドをオーバーライドするように見えるかもしれませんどのように追加されます。私はこのコードを試していませんが、ロジックはこのようになります。あなたが `... http://www.django-rest-framework.org/api-guide/serializers/#raising-an-exceptionを診断するために` IS_VALID(RAISE_EXCEPTION = true)をしようとする場合があります

class SectorSerializer(serializers.ModelSerializer): 
    # Your fields. 
    class Meta: 
     model = Address 
     fields = ("Your Fields",) 

     extra_kwargs = { 
      'name': { 
       'validators': [], 
      } 
     } 

    def create(self, validated_data): 
     raise_errors_on_nested_writes('create', self, validated_data) 

     ModelClass = self.Meta.model 

     info = model_meta.get_field_info(ModelClass) 
     many_to_many = {} 
     for field_name, relation_info in info.relations.items(): 
      if relation_info.to_many and (field_name in validated_data): 
       many_to_many[field_name] = validated_data.pop(field_name) 

     # FIELD CHECK 
     your_field = validated_data.get("your_field","") # or validated_data["your_field"] 
     try: 
      YourModel.objects.filter(your_check=your_field).get() 
      raise ValidationError("Your error") 
     except YourModel.DoesNotExist: 
      # if it doesn't exist it means that no model containing that field exists so pass it. You can use YourQuerySet.exists() but then the logic changes 
      pass 

     try: 
      instance = ModelClass.objects.create(**validated_data) 
     except TypeError: 
      tb = traceback.format_exc() 
      msg = (
       'Got a `TypeError` when calling `%s.objects.create()`. ' 
       'This may be because you have a writable field on the ' 
       'serializer class that is not a valid argument to ' 
       '`%s.objects.create()`. You may need to make the field ' 
       'read-only, or override the %s.create() method to handle ' 
       'this correctly.\nOriginal exception was:\n %s' % 
       (
        ModelClass.__name__, 
        ModelClass.__name__, 
        self.__class__.__name__, 
        tb 
       ) 
      ) 
      raise TypeError(msg) 

     # Save many-to-many relationships after the instance is created. 
     if many_to_many: 
      for field_name, value in many_to_many.items(): 
       field = getattr(instance, field_name) 
       field.set(value) 

     return instance 
+0

最終的に、手作業で実装されたユニークな検証の簡単な例を提供できますか? HOWL;) – cezar

+0

これを達成する方法は複数あります。 'create' /' update''''''''''''''''''''''''''''''または '' 'perform_create'' /' 'perform_update''をオーバーライドする' 'ビュー' '自体で行うことができます。あるいは、 'create' /' update'をオーバーライドすることでシリアライザで行うこともできます。シリアライザチェックを含むように私の答えを編集します - とnema na cemu :) @cezar –

+0

@cezarをチェックしてください –

関連する問題