2013-11-04 9 views
17

मैं Django दायरे में नया हूं लेकिन वहां बहुत सारे "जादू" हैं। मैं Django रीस्ट फ्रेमवर्क का उपयोग कर रहा हूं और ऐप बना रहा हूं जो मुफ्त उपयोगकर्ता पंजीकरण की अनुमति देगा। मेरे उपयोगकर्ता को कुछ अतिरिक्त फ़ील्ड चाहिए जो Django उपयोगकर्ता में उपलब्ध नहीं हैं। तो मैं उपयोगकर्ता को विस्तारित करने के लिए googled। वहाँ एक विचार है कि यह इसDjango REST Framework कस्टम उपयोगकर्ता बनाना

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

यह ठीक है, लेकिन मैं इस serializer

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

तो है की तरह कुछ बनाने के द्वारा किया जाना चाहिए है, समस्या यह है कि इस serializer कुछ "जादू" यहाँ करता है । यह पता लगाने की कोशिश करता है कि मॉडल के पास कौन सा क्षेत्र होना चाहिए ... मैं यहां सूचीबद्ध फ़ील्ड वाले उपयोगकर्ता को रखना चाहता हूं, और ये फ़ील्ड उपयोगकर्ता में हैं और 'शहर' नया कस्टम फ़ील्ड है। Serializer नहीं मिलता है कि यह उपयोगकर्ता मॉडल के अंदर देखना चाहिए।

मुझे यहां क्या याद आ रही है? इस धारावाहिक को कैसे बताना है कि मैं उपयोगकर्ता के अंदर कुछ फ़ील्ड चाहता हूं? मुझे उपयोगकर्ता को क्रेते भी करने में सक्षम होना चाहिए।

+6

आप OneToOneField' अपने UserModel संबंध, नहीं 'ForeignKey' के लिए उनके केवल एक ही' हर 'User' उदाहरण के लिए MyUser' हो सकता है के बाद से इस्तेमाल करना चाहिए'। –

+0

'OneToOneField' का उपयोग करें और इस उत्तर का पालन करें और आप जाने के लिए अच्छे हैं: [link] (http://stackoverflow.com/a/28733782/3294412) – musicformellons

उत्तर

1

यदि आप django 1.5 या इससे अधिक का उपयोग कर रहे हैं तो इसके बजाय custom user model का उपयोग करें, इस तरह उपयोगकर्ता मॉडल की अपनी समर्पित तालिका होगी और सीरिएलाइज़र तब फ़ील्ड को सही तरीके से उठाएगा।

+0

सोचें कि यह वास्तव में एक विकल्प नहीं है, शायद मैं 1.4 का उपयोग करूँगा । मैं वास्तव में समझ में नहीं आता कि यह वास्तव में करना मुश्किल है? ऐसा क्यों है? मैं मानक चीज की तरह सीम करता हूं, यह इतना जटिल क्यों है? – bradojevic

1

Django Rest Framework का उपयोग करते समय आपको सावधान रहना होगा। कोई भी कस्टम उपयोगकर्ता मॉडल निर्मित टोकन प्रमाणीकरण का उपयोग नहीं कर सकता है। जब तक आप ऐसा नहीं कर सकते, मैं आपके कस्टम मॉडल में उपयोगकर्ता के साथ OneToOneField का उपयोग करने का सुझाव दूंगा। आपके कस्टम मॉडल में वे अतिरिक्त फ़ील्ड होंगे जिन्हें आप रखना चाहते हैं। एक से एक आपको कस्टम उपयोगकर्ता से उपयोगकर्ता तक पहुंचता है, और उपयोगकर्ता से कस्टम उपयोगकर्ता देता है।

+5

यह पोस्ट करने के लगभग एक साल हो गया है - क्या डीआरएफ अभी तक Django के कस्टम उपयोगकर्ता मॉडल का समर्थन करता है या क्या यह उत्तर अभी भी सही है और उपयोगकर्ताओं के साथ OneToOneFields अभी भी सबसे अच्छा विचार है? – ArtOfWarfare

12

ठीक है, कुछ चीजें। आप अपने उपयोगकर्ता मॉडल एक्सटेंशन के लिए OneToOneField बनाना चाहते हैं।

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

अब, Django बाकी फ्रेमवर्क की शक्ति, आप अपने serializer निर्माण कर सकते हैं जब serializing इन मॉडलों के दोनों से डेटा लेने के लिए है।

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() 'के उदाहरण कार्यान्वयन को शामिल करने के लिए अपने उत्तर पर विस्तार कर सकते हैं? मुझे यकीन नहीं है कि मुझे पासवर्ड को हश करने के बारे में कैसे जाना चाहिए ... (तथ्य यह है कि आप यह भी सुझाव देते हैं कि हमें ऐसा करने की ज़रूरत है जो मेरे दिमाग में लाल झंडे उठाए - क्या डैंजो या डीआरएफ इस तरह की सुरक्षा प्रदान नहीं कर सकता बॉक्स?) – ArtOfWarfare

+0

इस उत्तर के लिए धन्यवाद! इसमें शामिल होने पर, आप आईडी-एट्रिब्यूट 'user_profile = serializers.harfield (source =' userprofile.id ') के लिए भी जा सकते हैं। – pasql

16

तो जाहिर है कि मेरे पास उत्तर के तहत कोई टिप्पणी पोस्ट करने के लिए पर्याप्त प्रतिष्ठा नहीं है। लेकिन क्या केविन स्टोन वर्णित पर विस्तृत करने, अगर आप मॉडल की तरह कुछ है निम्नलिखित:

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

ध्यान दें कि restore_object() DRF 3.x के साथ संगत नहीं है, इसलिए आपको इसके बजाय create() और अद्यतन() विधियों का उपयोग करना होगा। यहां उदाहरण: http://www.django-rest-framework.org/topics/3.0-announcement/#serializers। – jarmod

0

यह होगा:

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

आप कुछ इस तरह कर सकते हैं दोनों कस्टम उपयोगकर्ता और Django उपयोगकर्ता बनाने के लिए अच्छा है अगर दस्तावेज़ों में यह उपयोग केस ढूंढना आसान था। के रूप में @jamod ने कहा, डीआरएफ 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

मैं आपसे संपर्क कर सकें जाएगा Django 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

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

अपने उपयोगकर्ता को बनाने और अपने उपयोगकर्ता को सहेजने के बाद, आपके पास जानकारी जोड़ने के लिए एक खाली उपयोगकर्ता होगा। प्रोफाइल। उदाहरण के लिए, चल python manage.py shell कोशिश के बाद:

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