django: обновить две модели, используя один и тот же вызов API - PullRequest
0 голосов
/ 01 ноября 2019

У меня есть вызов API, который получает и получает данные пользователя. Модель пользователя выглядит примерно так -

У меня есть модель для пользователя -

{
    "id": 23,
    "name": "fname",
    "height": null,
    "weight": "59",
    "blood_pressure": "131",
    "blood_sugar": "320",
    "email": "m@gmail.com",
}

Я хочу сохранить этоданные будут сохранены в UserBody модели -

"height": null,
"weight": "59",
"blood_pressure": "131",
"blood_sugar": "320",

, в то время как я хочу, чтобы остальные данные (идентификатор, имя, адрес электронной почты) были сохранены в BodyModel

My Userмодель выглядит так -

class MyUser(AbstractBaseUser, PermissionMixin):
    name = models.CharField(max_length=63, blank=True)
    height = models.IntegerField(blank=false, null=false)
    weight = models.IntegerField(blank=true, null=false)
    blood_pressure = models.IntegerField(blank=true, null=false)
    blood_sugar = models.IntegerField(blank=true, null=false)
    email = models.CharField(max_length=63, blank=True)

Класс UserBody -

class UserBody(AbstractBaseUser, PermissionMixin):
        user = models.OneToOneField(MyUser, on_delete=models.CASCADE)
        height = models.IntegerField(blank=false, null=false)
        weight = models.IntegerField(blank=true, null=false)
        blood_pressure = models.IntegerField(blank=true, null=false)
        blood_sugar = models.IntegerField(blank=true, null=false)

Я возился с созданием user объекта foreignKey, но просто не могу обернутьсякак это должно было работать. У меня есть MyUser сериализатор, но Я просто не знаю, как написать сериализатор для UserBody модель . Помогите мне с любым направлением, я буду идти вперед оттуда.

1 Ответ

0 голосов
/ 02 ноября 2019

Прежде всего, вы не должны наследовать обе ваши модели от AbstractBaseUser, чтобы предотвратить дублирование ваших данных (в этом случае обе модели будут иметь одинаковые поля, например, «пароль», «группы» и т. Д.). Также вы не должны определять одинаковые поля, такие как «рост», «вес» и т. Д. В обеих моделях по одним и тем же причинам - это не СУХОЙ подход. Вместо этого вам нужно наследовать модель User от AbstractBaseUser и UserBody от models.Model. Примерно так:

class User(AbstractUser):
    name = models.CharField(max_length=63, blank=True)
    email = models.CharField(max_length=63, blank=True)

    def __str__(self):
        return self.username


class UserBody(models.Model):
    user = models.OneToOneField(User, related_name='user_bodies', on_delete=models.CASCADE)
    height = models.IntegerField(blank=False, null=False)
    weight = models.IntegerField(blank=True, null=False)
    blood_pressure = models.IntegerField(blank=True, null=False)
    blood_sugar = models.IntegerField(blank=True, null=False)

Сериализаторы:

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        exclude = ('groups', 'user_permissions', )


class UserBodySerializer(serializers.ModelSerializer):
    user = UserSerializer(required=True)

    def create(self, validated_data):
        user_data = validated_data.pop('user')
        user = UserSerializer.create(UserSerializer(), validated_data=user_data)
        user_body, created = UserBody.objects.update_or_create(user=user, **validated_data)

    class Meta:
        model = UserBody
        fields = '__all__'

Вид:

class UserBodyView(APIView):
    permission_classes = (AllowAny, )

    def get(self):
        user_bodies = UserBody.objects.all()
        serializer = UserBodySerializer(user_bodies, many=True)
        return Response(serializer.data)

    def post(self, request):
        serializer = UserBodySerializer(data=request.data)
        if serializer.is_valid(raise_exception=ValueError):
            serializer.create(validated_data=request.data)
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.error_messages,
                        status=status.HTTP_400_BAD_REQUEST)

Добавить в urlpatterns:

path('api/v1/bodies/', UserBodyView.as_view(), name='user-bodies')

Теперь у вас есть следующая конечная точка: / api / v1 / body /

Если вы разместите следующие данные:

{
        "height": 170,
        "weight": 70,
        "blood_pressure": 120,
        "blood_sugar": 20,
        "user": {
            "username": "dimitrionian",
            "email": "john_doe@gmail.com",
            "password": "qweqwe123"
    }
}

, это создаст экземпляр пользователя и связанный экземпляр user_body,Сериализатор вернет следующее:

{
  "user": {
    "password": "qweqwe123",
    "last_login": null,
    "username": "dimitrionian",
    "email": "john_doe@gmail.com"
  },
  "height": 170,
  "weight": 70,
  "blood_pressure": 120,
  "blood_sugar": 20
} 

Это рабочий и проверенный случай. Вы можете уточнить его в соответствии с вашими потребностями. Например, установите необходимые разрешения вместо примененного AllowAny

...