2013-11-04 7 views
17

Django aleminde yeniyim ama orada bir sürü "sihir" var. Django REST Framework'ü kullanıyorum ve ücretsiz kullanıcı kaydına izin verecek bir uygulama oluşturuyorum. Kullanıcımın Django kullanıcısı olmayan bazı ek alanlara ihtiyacı var. Bu yüzden Kullanıcıyı genişletmek için çalıştım. Bu buDjango REST Framework Özel kullanıcı oluşturma

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

Bu iyi ama ben

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

Yani bu serileştirici var gibi bir şey oluşturarak yapılmalıdır yönünde bir görüş var olduğunu, sorun bu serileştirici burada bazı "sihirli" yapmasıdır . Modelin hangi alana sahip olduğunu bulmaya çalışıyor ... Burada listelenen alanlara sahip olmak istiyorum ve bunlar alanlar Kullanıcıda ve 'şehir' yeni özel alan. Seri hale getirici, Kullanıcı modeline bakması gerekmiyor.

Burada nelerin eksik? Bu seri hale getiriciye, Kullanıcı'nın içinde bazı alanlar olmasını istiyorum. Ben de kullanıcıyı mahvedebilmem lazım.

+6

Sen UserModel ilişkisi değil, 'ForeignKey' için' OneToOneField' kullanmalıdır. –

+0

'OneToOneField' işlevini kullanın ve bu cevabı takip edip şunları yapabilirsiniz: [link] (http://stackoverflow.com/a/28733782/3294412) – musicformellons

cevap

1

Eğer django 1.5 veya daha büyük kullanıyorsanız, bunun yerine custom user model kullanın, bu şekilde kullanıcı modelinin kendine ait bir tabloya sahip olacak ve serializer alanlarını doğru bir şekilde alacaktır.

+0

Gerçekten bir seçenek olmadığını düşünüyorum, muhtemelen 1.4 kullanıyorum . Gerçekten anlamıyorum, bu gerçekten zor mu? Neden? Yapmam gereken standart şey gibi dikiliyor, neden bu kadar karmaşık? – bradojevic

1

Django Rest Framework'ü kullanırken dikkatli olmalısınız. Herhangi bir özel kullanıcı modeli yerleşik belirteç kimlik doğrulamasını kullanamaz. Bunu yapana kadar, özel modelinizde kullanıcıyla OneToOneField kullanmanızı öneririm. Özel modeliniz tutmak istediğiniz ekstra alanları içerecektir. Bire Bir, kullanıcıya özel kullanıcıdan ve kullanıcıdan gelen özel kullanıcıya erişmenizi sağlar.

+5

Bunu yayınladığınızdan neredeyse bir yıl geçti - DRF, Django'nun Özel Kullanıcı Modellerini desteklemiyor mu yoksa bu cevap hala doğru ve kullanıcılarla OneToOneFields hala en iyi fikir mi? – ArtOfWarfare

12

Tamam, birkaç şey. Kullanıcı modeli uzantınız için OneToOneField oluşturmak istiyorsunuz.

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

Şimdi Django istirahat Framework güç, siz, seri hale inşa edebilirsiniz seri hale Bu modellerin her ikisi veri almaktır.

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

Son olarak, sizin özel alanlar kullanıyorsanız beri, giriş verisinden hem modeller oluşturur kendi restore_object() uygulamak gerekir, kullanıcı oluşturuyorsanız.

Ayrıca, Django'daki Kullanıcılar'ı oluşturmak biraz farklıdır, create_user() numaralı telefonu aramanız ve karma olan bir parola sağlamanız gerekir; bu nedenle, bir serileştiriciden alanları depolamak kadar basit değildir.

+0

Yanıtınızı "restore_object()" ve "create_user()') örnek uygulamasına dahil etmek için genişletebilir misiniz? Parolayı şifrelemeye nasıl başlayacağımı bilmiyorum ... (aklıma kırmızı bayraklar çıkarmamız gerektiğini bile söylemelisiniz - Django veya DRF bu türden kutu?) – ArtOfWarfare

+0

Bu cevap için teşekkürler! Buna ek olarak, "user_profile = serializers.CharField (source = 'userprofile.id')') özniteliğine de başvurabilirsiniz. – pasql

16

Görünüşe göre, bir yanıt altında yorum göndermek için yeterli saygınlığım yok. Eğer modeli gibi bir şey Ama eğer Kevin Taş deyimiyle üzerinde durmak için aşağıdaki:

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

Geri yükleme_object() öğesinin DRF 3.x ile uyumlu olmadığını, bunun yerine create() ve update() yöntemlerini kullanmanız gerektiğini unutmayın. Örnek burada: http://www.django-rest-framework.org/topics/3.0-announcement/#serializers. – jarmod

0

Olurdu:

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

Böyle bir şey yapabiliriz özel kullanıcı ve django kullanıcı oluşturmak, hem de Bu kullanım dokümanı dokümanlar bulmak daha kolay olsaydı. @jamod belirttiği gibi, DRF 3'te, bunu here bulabilirsiniz:

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

sana diyelim olacak bir şey olduğunda uygulamasına sinyalleri gönderir django signals modülü, kullanmayı tercih ve diğer şeylerin yanı sıra diğer işlevlerden önce/sonra kendi bir işlevi.Cevabım Stuart'ın cevabına benziyor ama yeni uzantı sınıfınızla ilgili tüm kodları tek bir yerde saklıyor (daha sonra profili silmek veya ismini değiştirmek istiyorsanız başka bir yere bakmak zorunda kalmazsınız).

Aşağıdaki kod, genişletilmiş sınıf modelinizi ortaya koyar, bu durumda bir kullanıcı profili oluşturur, ardından bir kullanıcı modeli oluşturulduğunda boş bir örnek oluşturur, ardından örneği kaydederek yeni bilgileri (kendiniz eklemeniz gerekir) kaydeder. ebeveyn kullanıcı örneği yani - 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() 

bir ProfileSerializer yoksa: serializers.py

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

Kullanıcınızı oluşturduktan ve kullanıcınızı kaydettikten sonra, bilgi eklemek için boş bir user.profile olacaktır. Örneğin, python manage.py shell deneyin çalıştırdıktan sonra: onların her `User` örneği için tek` MyUser` olabilir çünkü

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