如何将来自第三方API的响应存储为Django模型中的示例

ioekq8ef  于 2023-10-21  发布在  Go
关注(0)|答案(1)|浏览(125)

编辑:我已经编辑了我的问题,包括我的代码:
我正在DRF中构建一个Web API。还有第三方API,其响应返回ip_addresslatitudelongitude等字段。我有一个用户模型(它基本上是从AbstractBaseUser继承的),它包含像emailusernamefirst_namelast_name这样的字段。创建这个用户模型的示例是可行的。
但是我想做的是保存来自这个第三方API的响应,作为一个名为Artist的模型的示例,每当这个用户模型的示例被保存时,它都有一个带有用户模型的OneToOneField。我该怎么做?
注意:我让Djoser,一个处理身份验证的第三方库,负责我的用户模型上的身份验证端点。因此,到目前为止,这个项目还没有涉及到任何意见。
以下是我目前为止的代码:

import uuid
import requests

from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
from django.db import models
from django.utils import timezone
from django.utils.translation import gettext_lazy as _

from .managers import CustomUserManager


class UserGeoData(models.Model):
    ip_address = models.GenericIPAddressField(default="0.0.0.0")
    city = models.CharField(max_length=50)
    region_iso_code = models.CharField(max_length=5)
    country_code = models.CharField(max_length=5)
    longitude = models.DecimalField(max_digits=9, decimal_places=6)
    latitude = models.DecimalField(max_digits=9, decimal_places=6)

class User(AbstractBaseUser, PermissionsMixin):
    pkid = models.BigAutoField(primary_key=True, editable=False)
    id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
    username = models.CharField(verbose_name=_("Username"), max_length=255, unique=True)
    first_name = models.CharField(verbose_name=_("First Name"), max_length=50)
    last_name = models.CharField(verbose_name=_("Last Name"), max_length=50)
    email = models.EmailField(verbose_name=_("Email Address"), unique=True)
    usergeo = models.OneToOneField(UserGeoData, on_delete=models.CASCADE, null=False)
    is_staff = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    date_joined = models.DateTimeField(default=timezone.now)

    USERNAME_FIELD = "email"
    REQUIRED_FIELDS = ["username", "first_name", "last_name"]

    objects = CustomUserManager()

    class Meta:
        verbose_name = _("User")
        verbose_name_plural = _("Users")

    def __str__(self):
        return self.username

    @property
    def get_full_name(self):
        return f"{self.first_name} {self.last_name}"

    def get_short_name(self):
        return self.username
    
    def save(self, *args, **kwargs):
        url = "https://ipgeolocation.abstractapi.com/v1/?api_key=d77f75a5593e4073a6eb1bef9c35e929"
        response = requests.get(url)
        data = response.json()
        obj, created = UserGeoData.objects.get_or_create(
            ip_address=data["ip_address"],
            defaults={
                "city": data["city"],
                "region_iso_code": data["region_iso_code"],
                "country_code": data["country_code"],
                "longitude": data["longitude"],
                "latitude": data["latitude"],
            },
        )
        self.ship = obj
        return super().save()

# class Holiday(models.Model):
#     user = models.OneToOneField(User, on_delete=models.CASCADE)
#     holiday_name = models.CharField(max_length=120)
#     holiday_type = models.CharField(max_length=120)
#     date = models.DateTimeField(auto_now=True)
    
# class Security(models.Model):
#     usergeodata = models.OneToOneField(UserGeoData, on_delete=models.CASCADE)
#     is_vpn = models.BooleanField(default=False)

这是我的用户管理器:

from django.contrib.auth.base_user import BaseUserManager
from django.core.exceptions import ValidationError
from django.core.validators import validate_email
from django.utils.translation import gettext_lazy as _

class CustomUserManager(BaseUserManager):
    def email_validator(self, email):
        try:
            validate_email(email)
        except ValidationError:
            raise ValueError(_("You must provide a valid email address"))

    def create_user(
        self, username, first_name, last_name, email, password, **extra_fields
    ):
        if not username:
            raise ValueError(_("Users must submit a username"))

        if not first_name:
            raise ValueError(_("Users must submit a first name"))

        if not last_name:
            raise ValueError(_("Users must submit a last name"))

        if email:
            email = self.normalize_email(email)
            self.email_validator(email)
        else:
            raise ValueError(_("Base User Account: An email address is required"))

        user = self.model(
            username=username,
            first_name=first_name,
            last_name=last_name,
            email=email,
            **extra_fields
        )

        user.set_password(password)
        extra_fields.setdefault("is_staff", False)
        extra_fields.setdefault("is_superuser", False)
        user.save(using=self._db)
        return user

    def create_superuser(
        self, username, first_name, last_name, email, password, **extra_fields
    ):
        extra_fields.setdefault("is_staff", True)
        extra_fields.setdefault("is_superuser", True)
        extra_fields.setdefault("is_active", True)

        if extra_fields.get("is_staff") is not True:
            raise ValueError(_("Superusers must have is_staff=True"))

        if extra_fields.get("is_superuser") is not True:
            raise ValueError(_("Superusers must have is_superuser=True"))

        if not password:
            raise ValueError(_("Superusers must have a password"))

        if email:
            email = self.normalize_email(email)
            self.email_validator(email)
        else:
            raise ValueError(_("Admin Account: An email address is required"))

        user = self.create_user(
            username, first_name, last_name, email, password, **extra_fields
        )
        user.save(using=self._db)
        return user
iyzzxitl

iyzzxitl1#

基本上,通过覆盖您的自定义用户save方法。下面是一个使用SWAPI为用户分配Ship的简单示例:
models.py

import requests as req

class Ship(models.Model):
    name = models.CharField(max_length=100)
    model = models.CharField(max_length=255)
    manufacturer = models.CharField(max_length=255)
    hyperdrive_rating = models.FloatField()
    starship_class = models.CharField(max_length=255)

class User(AbstractUser):
    # supposedly you want to maintain the ship in this case.
    # but may want to get rid of your actual values with models.CASCADE
    ship = models.OneToOneField(Ship, on_delete=models.DO_NOTHING)

    def save(self, *args, **kwargs):
        res = req.get("https://swapi.dev/api/starships/10")
        data = res.json()
        obj, created = Ship.objects.get_or_create(
            name=data["name"],
            defaults={
                "model": data["model"],
                "manufacturer": data["manufacturer"],
                "hyperdrive_rating": data["hyperdrive_rating"],
                "starship_class": data["starship_class"],
            },
        )
        self.ship = obj
        return super().save()

为了简单起见,使用了AbstractUser
P.S.你想要Python requests

相关问题