django 有没有办法优化这段代码?

b09cbbtk  于 8个月前  发布在  Go
关注(0)|答案(2)|浏览(101)

下面是两个模型:models.py文件:

class Profile(models.Model):
    """
    User Profile Model
    
    This model represents a user's profile information, including their avatar,
    location, city, address, and geographical coordinates (latitude and longitude).

    Fields:
    - user (OneToOneField): The associated user instance.
    - avatar (ImageField): An optional user avatar (profile picture).
    - location_picture (ImageField): An optional picture of the user's location.
    - city (CharField): An optional field for the user's city.
    - address (CharField): An optional field for the user's address.
    - latitude (DecimalField): An optional field for the latitude of the user's location.
      Valid range: -90.0 to 90.0.
    - longitude (DecimalField): An optional field for the longitude of the user's location.
      Valid range: -180.0 to 180.0.

    """
    user = models.OneToOneField(
        settings.AUTH_USER_MODEL,
        verbose_name=_("User"),
        help_text=_("the profile of a user instance."),
        db_comment=_("the profile of a user instance."),
        on_delete=models.CASCADE
        )
    
    city = models.CharField(
        verbose_name=_("City"),
        help_text=_("'Optional'.this is the city of the user."),
        db_comment=_("'Optional'.this is the city of the user."),
        max_length=255,
        null=True,
        blank=True
        )
    
    address = models.CharField(
        verbose_name=_("Address"),
        help_text=_("'Optional'.this is the address of a user."),
        db_comment=_("'Optional'.this is the address of a user."),
        max_length=255,
        null=True,
        blank=True
    )

    shair_location = models.BooleanField(
        verbose_name=_("Shair Location"),
        default=False,
        help_text=_("'Optional.thie mean you want to shair your location or not!'"),
        db_comment=_("'Optional.this mean you want to shair your location or not!'")
    )

    latitude = models.DecimalField(
        verbose_name=_("Latitude"),
        help_text=_("'Optional'.this is the latitude of a user location."),
        db_comment=_("'Optional'.this is the latitude of a user location."),
        max_digits=9,
        decimal_places=6,
        null=True,
        blank=True,
        validators=[
        MinValueValidator(-90.0),
        MaxValueValidator(90.0)
    ])
    
    longitude = models.DecimalField(
        verbose_name=_("Longitude"),
        help_text=_("'Optional'.this is the longitude of a user location."),
        db_comment=_("'Optional'.this is the longitude of a user location."),
        max_digits=9,
        decimal_places=6,
        null=True,
        blank=True,
        validators=[
        MinValueValidator(-180.0),
        MaxValueValidator(180.0)
    ])

    def __str__(self) -> str:
        return f"user:{self.user}|city:{self.city}"



class Media(models.Model):
    profile = models.ForeignKey(
        Profile,
        verbose_name=_("Profile"),
        help_text=_("the profile can have lot of media(avatar or cover or resume...)"),
        db_comment=_("the profile can have lot of media(avatar or cover or resume...)"),
        on_delete=models.CASCADE,
        related_name="medias"
    )

    media_type = models.IntegerField(
        verbose_name=_("Media Type"),
        choices=MediaType.choices,
        help_text=_("this is the type of the media(avatar:0, resume:1, cover:2, gallery:3)"),
        db_comment=_("this is the type of the media(avatar:0, resume:1, cover:2, gallery:3)"),
        validators=[
            MinValueValidator(0),
            MaxValueValidator(3)
            ]
    )

    image = models.ImageField(
        verbose_name=_("Image"),
        help_text=_("this is the image field"),
        db_comment=_("this is the image field"),
        upload_to="images/%Y/%m/%d/",
        validators=[
            validate_image_size,
        ],
        null=True,
        blank=True
    )

    video = models.FileField(
        verbose_name=_("Video"),
        help_text=_("this is the video field"),
        db_comment=_("this is the video field"),
        upload_to="vidoes/%Y/%m/%d",
        validators=[
            validate_video_size,
        ],
        null=True,
        blank=True
    )

    created_at = models.DateTimeField(
        verbose_name=_("Created At"),
        help_text=_("this is the time the media is created"),
        db_comment=_("this is the time the media is created"),
        auto_now_add=True
    )

我下面有这个serializer_class用于获取用户的头像,它正在工作,但对于配置文件列表端点中的每个配置文件有两个额外的查询
serializer.py:

class ProfileSerializer(serializers.ModelSerializer):
    user = UserSerializer()

    avatar = serializers.SerializerMethodField(method_name="get_avatar_url")
    class Meta:
        model = Profile
        fields = ["id", "avatar", "user", "city", "address", "latitude", "longitude"]

    
    def get_avatar_url(self, profile):
        avatar_media = profile.medias.filter(media_type=0).first()
        if avatar_media:
            if avatar_media.image:
                return avatar_media.image
            else:
                return None
        else:
            return None

media_type == 0平均头像
我想得到的形象(头像)的配置文件和配置文件(配置文件端点:配置文件列表),但为每个配置文件发送两个额外的查询到数据库,是否有方法优化此代码或更改它?!

bwitn5fc

bwitn5fc1#

可以在查询时过滤该字段;

class ProfileSerializer(serializers.ModelSerializer):
    user = UserSerializer()
    avatar = serializers.SerializerMethodField(method_name="get_avatar_url")

    class Meta:
        model = Profile
        fields = ["id", "avatar", "user", "city", "address", "latitude", "longitude"]

    def get_avatar_url(self, profile):
        avatar_media = profile.medias.only("image").filter(media_type=0, ~Q(image="")).first()
        # or you can use .exclude
        # avatar_media = profile.medias.only("image").filter(media_type=0).exclude(image="").first()
        return getattr(avatar_media, "image", None)

您可以了解更多关于Q对象,排除和仅从文档。

wqlqzqxt

wqlqzqxt2#

经过大量的努力,我终于找到了如何优化这段代码的方法。首先,在视图中对get_serializer_context方法进行了一些更改:

def get_serializer_context(self):
if self.request.method == "GET":
    if self.kwargs.get("pk") == None and self.kwargs.get("me") == None:
        avatar_medias = Media.objects.select_related("profile").filter(profile__user=self.request.user, media_type=MediaType.AVATAR)
        return {"request": self.request, "avatars_medias": avatar_medias}

然后我们在ProfileSerializer中调用avatar medias字段:

class ProfileAdminSerializer(serializers.ModelSerializer):
user = UserSerializer()
plan = serializers.SerializerMethodField(method_name="get_plan")
avatar = serializers.SerializerMethodField(method_name="get_avatar_url")

class Meta:
    model = Profile
    fields = ["id", "avatar", "user", "city", "address", "latitude", "longitude", "plan"]

def get_avatar_url(self, profile):
    avatar_medias = self.context.get("avatars_medias")
    for media in avatar_medias:
        if media.profile == profile:
            if media.image:
                return media.image.url
    
    else:
        return

这将导致查询数据库,这是一个查询数据库的每个配置文件,现在我们得到所有的配置文件与他们的化身与一个单一的查询

相关问题