2011-11-08 4 views
1

Je suis nouveau à Django, déplacé de PHP avec Propel ORM moteur. Alors voici ce que je fais actuellement dans Django. Mon site a plusieurs modèlesModèle "Comportements" dans Django

  1. Livre,
  2. Editeur,
  3. Commentaire,
  4. article et ainsi de suite (ce n'est pas le point)

Chacun d'eux peut peut être aimé ou détesté par un utilisateur (une seule fois) en changeant la note du modèle par +1 ou -1.

En termes de PHP je créerais un comportement, par ex. "Rateable" qui ajouterait des champs et des méthodes au modèle original et à la classe de requête (comme get_rating(), order_by_rating(), etc) et créer une table séparée pour chaque modèle, par ex. book_rating_history qui contiendrait toutes les évaluations pour chaque objet, afin de déterminer si l'utilisateur peut ou ne peut pas changer la note (ou afficher toutes les notes de l'objet, si nécessaire). Donc tout ce que je devrais faire est de spécifier le comportement "Rateable" dans la déclaration du modèle, et c'est tout. Tout le reste est fait automatiquement.

La question est - comment résoudre ceci dans Django? Comment modéliser correctement? Quelles techniques utilisez-vous dans des cas similaires?

Répondre

3

Vous voudrez stocker des évaluations et des livres séparément, quelque chose comme ceci (non testé).

from django.contrib.auth.models import User 
from django.db import models 
from django.db.models import Sum 

class BookRating(models.Model): 
    user = models.ForeignKey(User) 
    book = models.ForeignKey('Book') 

    # you'll want to enforce that this is only ever +1 or -1 
    rating = models.IntegerField() 

    class Meta: 
    unique_together = (('user', 'book'),) 

class Book(models.Model): 
    title = models.CharField(max_length = 50) 

    def rating(self): 
    return BookRating.objects.filter(book = self).aggregate(Sum('rating')) 

unique_together Garantit que chaque utilisateur ne peut évaluer une fois livre donné.

Vous pouvez ensuite utiliser ce quelque chose comme:

book = Book.objects.get(pk = 1) 
rating = book.rating() 

Ajouter un commentaire si vous avez des problèmes avec - je ne l'ai pas testé, mais nous espérons que cela est suffisant pour vous aider à démarrer.

Vous pouvez probablement éviter chaque objet (livres, éditeurs, commentaires, articles) ayant un objet de notation séparé en utilisant content types, si vous le souhaitez. Vous pouvez également envisager d'utiliser les applications réutilisables existantes qui gèrent les préférences, telles que django-likes ou phileo.

+1

fonction Bonus: l'utilisateur peut changer leur note à une date ultérieure. –

0

Vous pouvez définir des méthodes spéciales (par exemple vote, get_rating, etc.) uniquement dans un modèle abstrait, puis créer vos modèles "Rateable" en utilisant celui-ci.

class Rateable(models.Model): 

    class Meta: 
     abstract = True 

    def vote(self, *args, **kwargs): 
     ... 

    def rating(self, *args, **kwargs): 
     ... 

class Book(Rateable): 
    ... 

En outre, il est préférable d'utiliser un modèle unique pour stocker les types de contenu de sorcière de données de notation comme l'a remarqué Dominic Rodger

+0

Merci les gars, j'ai lu la documentation pour le cadre de types de contenu et a décidé de l'utiliser pour les notes, les balises et autres choses similaires. – user655136