Architecture de la publication de contenu
Lors du développement d'une fonctionnalité de partage social dans une application, la structure des données envoyées par le client est cruciale pour la performance et la maintenance future. Voici l'évolution d'un format de données pour une publication incluant du texte et des images.
// Structure optimisée pour la gestion des fichiers
{
"image_principale": "https://cdn.exemple.com/couverture.jpg",
"description": "Exploration du développement mobile avec Django",
"categorie_id": 10,
"localisation": "Paris, France",
"fichiers_media": [
{
"url": "https://cdn.exemple.com/img1.jpg",
"cle_stockage": "img1.jpg"
},
{
"url": "https://cdn.exemple.com/img2.jpg",
"cle_stockage": "img2.jpg"
}
]
}
L'inclusion de la cle_stockage (ou cos_key) permet au backend d'identifier précisément les fichiers dans le stockage objet (S3, COS, OSS) lors d'opérations de suppression ou de modification, sans avoir à parser l'URL.
Implémentation du Backend avec Django REST Framework
Pour gérer ces données, nous utilisons des sérialiseurs imbriqués pour valider à la fois la publictaion principale et les métadonnées des images associées.
from rest_framework import serializers, generics
from .models import Publication, MediaPublication
class MediaSerializer(serializers.ModelSerializer):
class Meta:
model = MediaPublication
fields = ['url', 'cle_stockage']
class PublicationCreateSerializer(serializers.ModelSerializer):
fichiers_media = MediaSerializer(many=True)
class Meta:
model = Publication
exclude = ['auteur', 'vues', 'date_creation']
def create(self, validated_data):
# Extraction des données imbriquées
medias = validated_data.pop('fichiers_media')
# Création de l'instance principale
instance_pub = Publication.objects.create(**validated_data)
# Création groupée des médias liés
MediaPublication.objects.bulk_create([
MediaPublication(**item, publication=instance_pub) for item in medias
])
return instance_pub
class PublicationView(generics.CreateAPIView):
queryset = Publication.objects.all()
serializer_class = PublicationCreateSerializer
def perform_create(self, serializer):
# Injection automatique de l'ID de l'utilisateur (simulé ici)
serializer.save(auteur_id=1)
Optimisation de l'affichage : Le flux en cascade (Waterfall)
Pour l'interface utilisateur, le design en cascade est populaire. En Mini-Program, l'approche la plus flexible utilise Flexbox combiné à une logique de séparation des données (colonnes paires/impaires).
/* Styles CSS pour le flux */
.conteneur-cascade {
display: flex;
flex-direction: row;
justify-content: space-between;
}
.colonne {
width: 48%;
}
.carte-item image {
width: 100%;
border-radius: 8rpx;
}
<!-- Structure WXML -->
<view class="conteneur-cascade">
<view class="colonne">
<block wx:for="{{listeData}}" wx:key="id">
<view wx:if="{{index % 2 == 0}}" class="carte-item">
<image src="{{item.image_principale}}" mode="widthFix"></image>
<text>{{item.description}}</text>
</view>
</block>
</view>
<view class="colonne">
<block wx:for="{{listeData}}" wx:key="id">
<view wx:if="{{index % 2 != 0}}" class="carte-item">
<image src="{{item.image_principale}}" mode="widthFix"></image>
<text>{{item.description}}</text>
</view>
</block>
</view>
</view>
Filtrage et Pagination Avancée
Pour améliorer les performances lors du défilement infini, il est préférable d'utiliser des filtres basés sur l'identifiant (ID) plutôt que sur un décalage (offset) pur, afin d'éviter le scan complet des tables SQL volumineuses.
from rest_framework.filters import BaseFilterBackend
class ScrollPaginationFilter(BaseFilterBackend):
def filter_queryset(self, request, queryset, view):
dernier_id = request.query_params.get('lastId')
direction = request.query_params.get('dir', 'down')
if dernier_id:
if direction == 'up':
# Chargement des nouveaux éléments (refresh)
return queryset.filter(id__gt=dernier_id).order_by('id')
# Chargement des anciens éléments (pagination)
return queryset.filter(id__lt=dernier_id)
return queryset[:10]
Initialisation de données via Scripting ORM
Lors de la phase de test, l'utilisation d'un script autonome pour peupler la base de données est plus efficace que l'insertion manuelle. Il est nécessaire de configurer l'environnement Django au préalable.
import os
import django
# Configuration de l'environnement Django
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mon_projet.settings")
django.setup()
from mon_app.models import Publication
def generer_donnees(n=20):
for i in range(n):
Publication.objects.create(
description=f"Article de test numéro {i}",
image_principale="https://cdn.exemple.com/test.png",
auteur_id=1
)
print(f"Insertion de {n} entrées terminée.")
if __name__ == "__main__":
generer_donnees()
La distinction entre sys.path (chemins de recherche des modules Python) et os.environ (variables système pour la configuration Django) est essentielle pour que le script puisse accéder aux modèles et à la base de données du projet.