2013-11-04 10 views
17

私はDjangoレルムでは新しいですが、そこには多くの "魔法"があります。私はDjango REST Frameworkを使用しており、無料のユーザー登録を可能にするアプリケーションを作成しています。私のユーザは、Djangoユーザでは利用できない追加フィールドが必要です。だから、私はユーザーを拡張するためのグーグル。これはこれで結構ですが、私はそう、このシリアライザにDjango RESTフレームワークカスタムユーザの作成

class UserSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = MyUser 
     fields = ('id', 'username', 'password', 'first_name', 'last_name', 'email', 'city') 

を持っている、問題はこのシリアライザは、ここでいくつかの「魔法」をしていることである。この

class MyUser(models.Model): 
    user = models.ForeignKey(User, unique=True) 
    city = models.CharField(max_length=50, blank=True, default='') 

のようなものを作成することによって行われるべきであるという考えがあります。モデル化すべきフィールドを把握しようとしています... ここにリストされているフィールドを持つユーザーがいて、フィールドがUserで、 'city'が新しいカスタムフィールドです。シリアライザは、Userモデル内を見なければならないということはありません。

私はここで何が欠けていますか?このシリアライザに、ユーザの中にいくつかのフィールドが必要だと伝えるには?私もクレテユーザーにできる必要があります。

+6

あなたのUserModel関係なく、 'ForeignKey'ため' OneToOneField'を使用する必要があります。 –

+0

使用 'OneToOneField'とこの答えに従うと、あなたは行ってもいいです:[リンク](http://stackoverflow.com/a/28733782/3294412) – musicformellons

答えて

1

django 1.5以上を使用している場合は、代わりにcustom user modelを使用してください。この方法では、ユーザーモデルに独自の専用テーブルがあり、シリアライザはフィールドを正しくピックアップします。

+0

おそらく私は1.4を使用してすることがあります、それは本当にオプションではありませんだと思います。私は本当にこれは本当に難しいとは分かりませんか?何故ですか?私は縫い目が標準的なもののように、なぜこれはとても複雑ですか?あなたがこの投稿以来 – bradojevic

1

Django Rest Frameworkを使用する場合、注意が必要です。カスタム・ユーザー・モデルでは、組み込みのトークン認証を使用できません。あなたがそれを行うまで、カスタムモデルでOneToOneFieldを使用することをお勧めします。カスタムモデルには、保存する余分なフィールドが含まれます。 One to Oneでは、カスタムユーザーからのユーザーと、ユーザーからのカスタムユーザーにアクセスできます。

+5

は、それはほとんど年をされている - DRFは、Djangoのカスタム・ユーザー・モデルをサポートし、まだかまだユーザーと最高のアイデアこの答えが正しいですOneToOneFieldsのでしょうか? – ArtOfWarfare

12

よろしくお願いします。ユーザーモデル拡張用にOneToOneFieldを作成したいとします。

class MyUser(models.Model): 
    user = models.OneToOneField(User) 
    city = models.CharField(max_length=50, blank=True, default='') 

さて、Djangoの残りフレームワークのパワーは、あなたが、あなたのシリアライザを構築することができますシリアライズする際に、これらのモデルの両方からデータを取ることです。

class UserSerializer(serializers.ModelSerializer): 
    city = serializers.CharField(source='myuser.city') 
    class Meta: 
     model = User 
     fields = ('id', 'username', 'password', 'first_name', 'last_name', 'email', 'city') 

最後に、私たちはあなたでは、カスタムフィールドを使用していることから、あなたが入力されたデータから、両方のモデルを構築し、独自のrestore_object()を実装する必要があり、ユーザーを作成しています。

また、Djangoでのユーザー作成は少し異なります。create_user()に電話をかけ、ハッシュされたパスワードを提供する必要があります。シリアライザのフィールドを保存するほど簡単ではありません。

+0

あなたは 'restore_object()'と 'CREATE_USER()'の実装例を含めるようにあなたの答えを拡張できますか?私はパスワードをハッシュすることについてどうすればいいのか分かりません...(あなたが私たちの心の中で赤旗を立てる必要があることを示唆しているという事実 - DjangoやDRFはこの種のセキュリティを提供してはいけません箱?) – ArtOfWarfare

+0

この返答をありがとう!それまで追加することで、id属性 'user_profile = serializers.CharField(source =' userprofile.id ') 'に行くこともできました。あなたの代わりに()とupdate()メソッドを作成し使用する必要があると思いますので、()restore_object – pasql

16

明らかに私は答えの下にコメントを投稿するのに十分な評判はありません。

class AppUser(models.Model): 
    user = models.OneToOneField(User) 
    ban_status = models.BooleanField(default=False) 

あなたはカスタムユーザーとDjangoのユーザの両方を作成するには、このような何かを行うことができます:

class AppUserSerializer(serializers.ModelSerializer): 
    username = serializers.CharField(source='user.username') 
    email = serializers.CharField(source='user.email') 
    password = serializers.CharField(source='user.password') 
    ban_status = serializers.Field(source='ban_status') 

    class Meta: 
     model = AppUser 
     fields = ('id', 'username', 'email', 'password', 'ban_status') 

    def restore_object(self, attrs, instance=None): 
     """ 
     Given a dictionary of deserialized field values, either update 
     an existing model instance, or create a new model instance. 
     """ 
     if instance is not None: 
      instance.user.email = attrs.get('user.email', instance.user.email) 
      instance.ban_status = attrs.get('ban_status', instance.ban_status) 
      instance.user.password = attrs.get('user.password', instance.user.password) 
      return instance 

     user = User.objects.create_user(username=attrs.get('user.username'), email= attrs.get('user.email'), password=attrs.get('user.password')) 
     return AppUser(user=user) 
+4

注意DRF 3.xのと互換性がありません。ここの例:http://www.django-rest-framework.org/topics/3.0-announcement/#serializers。 – jarmod

0

それはだろうが、あなたのモデルは、次のようなものである場合にはケビン・ストーンは、説明したものに詳しく説明しますこのユースケースがドキュメント内で見つけやすい方がいいですか? @jamodが指摘したように、DRF 3に、あなたはそれをhereを見つけることができます。

class UserSerializer(serializers.ModelSerializer): 
    profile = ProfileSerializer() 

    class Meta: 
     model = User 
     fields = ('username', 'email', 'profile') 

    def create(self, validated_data): 
     profile_data = validated_data.pop('profile') 
     user = User.objects.create(**validated_data) 
     Profile.objects.create(user=user, **profile_data) 
     return user 
1

を、私はあなたが呼ぶようになる何かが起こる時にアプリに信号を送り、ジャンゴsignalsモジュールを、使用することを好む、そしてとりわけ他の機能の前後に自分自身の機能。私の答えはスチュアートの回答に似ていますが、(後でプロファイルを削除するか、名前を変更したい場合は、どこにも見てする必要はありません)一箇所に新しい拡張クラスに関連するすべてのコードを保持します。

次のコードでは、拡張クラスモデル(この場合はユーザープロファイル)をレイアウトし、ユーザーモデルの作成時に空のインスタンスを作成し、そのインスタンスに新しい情報を保存します親ユーザーインスタンスすなわち - user.save()

models.py

from django.db.models.signals import post_save 
from django.db import models 
from django.contrib.auth.models import User 

class Profile(models.Model): #This extends the user class to add profile information 
    user = models.OneToOneField(User, on_delete=models.CASCADE) 
    #add your extra traits here: is_nice, is_shwifty, address, etc. 
    is_nice = models.BooleanField(default=True, blank=True) 

# a user model was just created! This now creates your extended user (a profile): 
@receiver(post_save, sender=User) 
def create_user_profile(sender, instance, created, **kwargs): 
    if created: 
     # instance is the user model being saved. 
     Profile.objects.create(user=instance) 

# a user model was just saved! This now saves your extended user (a profile): 
@receiver(post_save, sender=User) 
def save_user_profile(sender, instance, **kwargs): 
     instance.profile.save() 

あなたはProfileSerializer持っていない場合:serializers.py

を0
#use hyperlinkedmodelserializer for easy api browsing + clicking 
class ProfileSerializer(serializers.HyperlinkedModelSerializer): 
    user = UserSerializer() 
    class Meta: 
     model = Profile 
     fields = ('url', 'user', 'is_nice') 

あなたのユーザーを作成し、ユーザーが保存した後、あなたがに情報を追加するための空のuser.profileを持っています。例えば、python manage.py shell 試みを実行した後:彼らはすべての `User`インスタンス1つだけ` myUser`にすることができるので

from backend.models import User, Profile 
#create your user 
user=User(username="GravyBoat") 
user.save() 
#now update your user's profile 
user.profile.is_nice=False 
#that's one mean gravy boat 
user.save() 
user.profile.is_nice 
#False 
関連する問題