2016-06-01 5 views
0

Я расширил пользовательскую модель таблицы django auth и реализую api отдыха для этого же.Как реализовать вложенный сериализатор в рамки django rest?

Я не получаю, как реализовать запрос GET/POST для этого же.

Мой models.py код:

class UserProfile(models.Model): 
    """User profile model for information about user.""" 

    users = models.OneToOneField(User) 
    phone_regex = RegexValidator(regex=r'^\+?1?\d{9,15}$', message="Phone number must be entered in the format: '+999999999'") 
    phone_number = models.CharField(max_length=100, validators=[phone_regex], blank=True) 
    created_timestamp = models.DateTimeField(auto_now_add=True, null=True) 
    updated_timestamp = models.DateTimeField(auto_now=True, null=True) 

Мой serializers.py код:

class UserSerializer(serializers.ModelSerializer): 
    """Serializer for users.""" 

    class Meta: 
     model = User 


class UserProfileSerializer(serializers.ModelSerializer): 
    """Serializer for user profiles.""" 

    users = UserSerializer(many=True) 

    class Meta: 
     model = UserProfile 

    def create(self, validated_data): 
     users_data = validated_data.pop('users') 
     print 'yes' 
     print users_data 
     user_profile = UserProfile.objects.create(**validated_data) 
     for user_data in users_data: 
      user_data, created = User.objects.get_or_create(first_name=user_data['first_name'], last_name=user_data['last_name'], 
     username=user_data['username'], password=user_data['password'], email=user_data['email'], is_active=['is_active']) 
     user_profile.users.add(user_data) 
    return user_profile 

Мой v1.py код:

class UserProfileList(APIView): 
    """Get and post user profiles data.""" 

    def get(self, request, format=None): 
     """Get users.""" 
     user_profiles = UserProfile.objects.all() 
     serialized_user_profiles = UserProfileSerializer(user_profiles, many=True) 
     return Response(serialized_user_profiles.data) 

    def post(self, request, format=None): 
     """Post users.""" 
     serializer = UserSerializer(data=request.data) 
     if serializer.is_valid(): 
      serializer.save() 
     return Response(serializer.data, status=status.HTTP_201_CREATED) 
    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) 

Я думаю, что проблема находится в файле v1.py. Я хочу сделать запрос GET и POST, для запроса POST я хочу отправить данные JSON. Может кто-то помочь мне в его реализации. Фактически, я хочу, чтобы одна конечная точка выполняла запрос POST и сохраняла данные в модели User model и UserProfile.

ответ

1

Изменение приведенный выше код

models.py

class UserProfile(models.Model): 
    user = models.OneToOneField(User) 
    phone_number = models.CharField(max_length=100, validators=[ 
    RegexValidator(regex=r'^\+?1?\d{9,15}$', message="Phone number must be entered in the format: '+999999999'") 
    ], blank=True, null=True) 
    created_timestamp = models.DateTimeField(auto_now_add=True, null=True) 
    updated_timestamp = models.DateTimeField(auto_now=True, null=True) 

Serializers.py
class UserSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = User 

class UserProfileSerializer(serializers.ModelSerializer): 
    user = UserSerializer(required=True) 
    class Meta: 
     model = UserProfile 

    def create(self, validated_data): 
     user_data = validated_data.pop('user', None) 
     user = User.objects.create_user(**user_data) 
     return UserProfile.objects.create(user=user, **validated_data) 

    def update(self, instance, validated_data): 
     user_dict = validated_data.pop('user', None) 
     if user_dict: 
      user_obj = instance.user 
      for key, value in user_dict.iteritems(): 
       setattr(user_obj, key, value) 
      user_obj.save() 
      validated_data["user"] = user_obj 
     for key, value in validated_data.iteritems(): 
      setattr(instance, key, value) 
     instance.save() 
     return instance 

viewsets.ру

from rest_framework import mixins 
from rest_framework import viewsets 

class MyUserViewSet(mixins.UpdateModelMixin, 
        mixins.CreateModelMixin, 
        mixins.ListModelMixin, 
        viewsets.GenericViewSet): 

    authentication_classes = (TokenAuthentication, SessionAuthentication) 
    permission_classes = (AllowAny,) 
    serializer_class = UserProfileSerializer 
    queryset = UserProfile.objects.all() 

Следуйте по этой ссылке routers

routers.py

from rest_framework import routers 
router = routers.SimpleRouter() 
router.register('users', MyUserViewSet) 

urls.py

from .routers import router 
urlpatterns = patterns(
    url(r'^api/v1/', include(router.urls)), 
) 
+0

Я использую 'URL (г '^ v1/пользователей/$ ', csrf_exempt (userregistration.v1.MyUserViewSet.as_view ({' get ':' queryset '}))), 'в моем файле urls.py, но при получении ошибки' 'Объект QuerySet не вызываем'. – Ankit

+0

вы указываете 'queryset' там в параметре get, вам нужно mapp {" get ":" list "}. Следуйте по этой ссылке http://www.django-rest-framework.org/api-guide/routers/#example –

+0

Я пробовал, но получаю ошибку '' MyUserViewSet 'объект не имеет атрибута' list'' – Ankit

0

Я предлагаю вам расширить модель User путем подклассификации AbstractBaseUser, которая требует также подкласса BaseUserManager. Таким образом, вы сможете упростить свой сериализатор, имея для этого только один класс. Он также требует подклассов BaseUserManager.

Пользовательские пользователи могут иметь столько настраиваемых полей, сколько захотите. Как правило, проще расширить модель пользователя таким образом, чтобы создать отношение «один к одному» к модели пользователя по умолчанию. Это экономит вам некоторую логику и некоторое время.

Вы можете прочитать здесь: https://docs.djangoproject.com/ja/1.9/topics/auth/customizing/#specifying-a-custom-user-model

Вот пример того, как вы могли бы сделать подкласс BaseUserManager:

class MyUserManager(BaseUserManager): 
    def create_user(self, email=None, password=None, dateofbirth=None, username=None): 
     user = self.model(
      email=MyUserManager.normalize_email(email),  
      dateofbirth=dateofbirth, 
      username=username 
     ) 

     user.set_password(password) 
     user.save(using=self._db) 
     return user 

    def create_superuser(self, username, dateofbirth, email, password): 
     user = self.create_user(email=email, 
        password=password, 
        username=username, 
        dateofbirth=dateofbirth, 
       ) 
     user.is_superuser = True 
     user.save(using=self._db) 
     return user 

Вот пример подклассов AbstractBaseUser:

class MyUser(AbstractBaseUser): 

    email = models.EmailField(
     verbose_name='email address', 
     max_length=255, 
     unique=True 
    ) 

    dateofbirth = models.CharField(max_length=30, blank=True) 

    is_active = models.BooleanField(default=True) 
    is_superuser = models.BooleanField(default=False) 

    USERNAME_FIELD = 'email' 

    objects = MyUserManager() 

    def get_full_name(self): 
     return self.email 

    def get_short_name(self): 
     return self.email 

    def __unicode__(self): 
     return self.email 

    def has_perm(self, perm, obj=None): 
     return True 

    def has_module_perms(self, app_label): 
     return True 

    @property 
    def is_staff(self): 
     return self.is_superuser 

Для этого для работы вам нужно будет установить модель пользователя auth в ваших settings.py, чтобы ваше приложение django знало, что вы нам ИНГ пользовательскую модель пользователя:

AUTH_USER_MODEL = 'myapp.MyUser' 

Вот простая часть - сериализатор:

class MyUserSerializer(serializers.ModelSerializer): 
    password = serializers.CharField(write_only=True, required=True) 

    class Meta: 
     model = MyUser 
     fields = (
      'email', 
      'password', 
      'dateofbirth', 
      'username', 
     ) 

    def create(self, validated_data): 
     password = validated_data.pop("password", None) 
     email = validated_data.pop("email", None) 
     username = validated_data.pop("username", None) 
     user = MyUser.objects.create_user(email=email, password=password, username=username, gender=gender, dateofbirth=dateofbirth) 
     MyUser.objects.filter(id=user.id).update(**validated_data) 
     return user 

Пока вы на него, забыть о APIView и использовать гораздо проще Viewset:

class MyUserViewSet(viewsets.ModelViewSet): 
    authentication_classes = (TokenAuthentication, SessionAuthentication) 
    permission_classes = (AllowAny,) 
    serializer_class = MyUserSerializer 

И только при этом у вас есть GET, POST, PUT, DELETE запросы обрабатываются.

Смежные вопросы