2010-11-21 4 views
1

Je n'arrive pas à comprendre comment utiliser les résultats de la requête. J'ai posé une demi-douzaine de questions à ce sujet mais je ne comprends toujours pas. Je copie du code précédent et je le fais fonctionner d'une manière ou d'une autre mais puisque je ne comprends pas le concept sous-jacent le code tombe en panne si je fais un changement mineur. J'apprécierais vraiment si vous pouviez me dire comment vous visualisez ce qui se passe ici et si vous me l'expliquez. Je vous remercie.IndexError: index de liste hors limites (dans les résultats de la requête)

class ReceiveEmail(InboundMailHandler): 
    def receive(self, message): 
     logging.info("Received email from %s" % message.sender) 
     plaintext = message.bodies(content_type='text/plain') 
     for text in plaintext: 
      txtmsg = "" 
      txtmsg = text[1].decode() 
      logging.info("Body is %s" % txtmsg) 
      logging.info("CC email is %s" % ((message.cc).split(",")[1]))    

     query = User.all()   
     query.filter("userEmail =", ((message.cc).split(",")[1])) 
     results = query.fetch(1)     

     for result in results:      
      result.userScore += 1     

     um = results[0]        
     um.userScore = result.userScore    
     um.put() 

Dans ce code, si je comprends bien, la requête prend la deuxième adresse e-mail dans la liste cc et va chercher le résultat.

J'incrémenter le userScore par 1.

Ensuite, je veux mettre à jour cet objet Datastore je le dis

 um = results[0]        
     um.userScore = result.userScore    
     um.put() 

Mais ce qui donne un indice sur la plage Erreur:

um = results[0] 
IndexError: list index out of range 

Pourquoi? J'imagine que results[0] est l'élément zeroeth des résultats. Pourquoi est-il hors de portée? La seule chose que je peux penser est que, la liste peut être None. Mais je ne comprends pas pourquoi. Il doit avoir le 1 objet qui a été récupéré.

De plus, si je tente de tester pour la première adresse e-mail en changeant l'index de [1] à [0]

query.filter("userEmail =", ((message.cc).split(",")[0])) 

alors je ne suis pas le IndexError.

Qu'est-ce que je fais mal ici?

Merci!

EDIT

Voir les commentaires:

(message.cc).split(",")[0]) 

laissé un espace devant les e-mails (en commençant par le second e-mail), de sorte que la requête n'a pas été les jumelant;

>>> cc.split(",") 
['[email protected]', ' [email protected]', ' [email protected]'] 

ajouter un espace après la virgule fixe le problème:

>>> listcc = cc.split(", ") 
>>> listcc 
['[email protected]', '[email protected]', '[email protected]'] 
>>> 
+1

Comment êtes-vous sûr qu'il y a des résultats à chercher en premier lieu? –

+0

Oui, bonne question. J'envoie un e-mail depuis le champ Dev Console Inbound Mail with cc qui contient 'user11 @ example.com' et' cc777 @ example.com'. Je m'assure que ces 2 emails sont déjà dans la base de données afin que la requête puisse les récupérer. Mais je viens d'essayer à nouveau ni index 0 ni 1 fonctionne maintenant. Pouvez-vous suggérer des moyens de vérifier ce que la requête voit? Merci. – Zeynel

+0

@Ignacio Vazquez-Abrams: Vous avez peut-être raison; la requête semble échouer: si les résultats: pour aboutir à des résultats: result.userScore + = 1 um = résultats [0] = um.userScore result.userScore um.put() autre: logging.info ("requête a échoué") – Zeynel

Répondre

1

Pour comprendre la rupture de code vers le bas et regarder pièce par pièce:

class ReceiveEmail(InboundMailHandler): 
    def receive(self, message): 
     logging.info("Received email from %s" % message.sender) 

     # Get a list of CC addresses. This is basically a for loop. 
     cc_addresses = [address.strip() for address in message.cc.split(",")] 
     # The CC list goes with the message, not the bodies. 
     logging.info("CC email is %s" % (cc_addresses)) 

     # Get and iterate over all of the *plain-text* bodies in the email. 
     plaintext = message.bodies(content_type='text/plain') 
     for text in plaintext: 
      txtmsg = "" 
      txtmsg = text[1].decode() 
      logging.info("Body is %s" % txtmsg) 

     # Setup a query object. 
     query = User.all() 
     # Filter the user objects to get only the emails in the CC list. 
     query.filter("userEmail IN", cc_addresses) 
     # But, only get at most 10 users. 
     users = query.fetch(10) 

     logging.info('Got %d user entities from the datastore.' % len(users)) 

     # Iterate over each of the users increasing their score by one. 
     for user in users: 
      user.userScore += 1 

     # Now, write the users back to the datastore. 
     db.put(users) 
     logging.info('Wrote %d user entities.' % len(users)) 

Je voudrais faire un ajustement à votre structure de modèle. Lorsque vous créez l'entité Utilisateur, je définirais le nom_clé à l'adresse e-mail. Vous serez en mesure de rendre vos requêtes beaucoup plus efficaces.

Quelques références:

+0

Bonjour Robert: Merci pour cette explication détaillée. C'était très utile. J'ai étudié les trois liens que vous avez référencés. Un merci spécial pour avoir modifié et organisé le code; cela a beaucoup plus de sens maintenant. Dans le cas de 'put()', je comprends que nous avons récupéré 10 lignes de la table 'User' en filtrant' cc_addresses' de la colonne 'userEmail'. Ensuite, nous avons mis à jour 'userScore' et' db.put (users)' nous avons écrit les lignes que nous avons mises à jour dans le datastore. En regardant la visionneuse de banque de données de la console de développement; Je vois cela, le moteur de l'application sait mettre à jour juste le 'userScore'. – Zeynel

+0

Il met réellement à jour toutes les propriétés sur les entités, mais parce que nous avons seulement changé 'userScore' c'est la seule propriété changée. –

Questions connexes