0

Please spare your valuable time and help me.

The idea of my app is that each User will receive a set of the same 30 cards, and then he has to decide each card is Important or Not.

I have 2 classes as follows:

class Card(models.Model):
    card_number = models.IntegerField(unique=True)
    content = models.TextField(null=False)

    def display(self):
        return self.content

    def __str__(self):
        return "Card  " + str(self.card_number)


class Choice(models.Model):
    user = models.ForeignKey(User)
    card = models.ForeignKey(Card)
    is_important = models.NullBooleanField(default=None)

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

    def get_choices(user):
        return Choice.objects.filter(pk=user.pk)

    def __str__(self):
        return " %s : Card %d : %s" % (self.user.username, self.card.card_number, self.is_important)

And in views.py, when user decides the card is important or not :

    card_number= request.GET.get('card_number')
    is_important= request.GET.get('is_important')    
    user = request.user

    # assume that user=admin, card_number=1 and is_important is False

    if card_number != None and is_important != None:
        try:
            card = Card.objects.get(card_number=card_number)
            choice= Choice.objects.create(user=user, card=card, is_important=is_important)
            print(choice)  # return admin: Card 1: False 
            print(Choice.objects.get(card__card_number=card_number))  # return admin: Card 1: True
            print(choice)  # return admin: Card 1: False 
        except IntegrityError:
            print("User had done with this Card")

I don't understand why:

print(choice)  # return admin: Card 1: False 

but

print(Choice.objects.get(card__card_number=1))  # return admin: Card 1: True

Thank you!

user2390182
  • 72,016
  • 6
  • 67
  • 89
Huy Than
  • 1,538
  • 2
  • 16
  • 31
  • I'm not sure this is related, but the return statements in your `Choice` model definitions need to be indented another level – Ian May 14 '16 at 19:47
  • and in the `Meta` declaration – Ian May 14 '16 at 19:48
  • can you provide an example of a GET request you make? – iulian May 14 '16 at 20:27
  • Thank you all of you. I have tried the solution of schwobaseggl, and it works like a charm. By the way, the GET request I have is : "http://127.0.0.1:8000/list/?card=3&choice=False" – Huy Than May 15 '16 at 00:19

2 Answers2

3

is_important is taken from the GET QueryDict as a (presumably) non-empty string. When you pass such a string as a parameter for a (Null)BooleanField, the ORM will cast it to a bool, and since non-empty strings evaluate to True, that's what gets stored in the db.

Assuming that you pass 'True', 'False' or 'None' as get parameter for is_important, you could do sth like:

is_important = request.GET.get('is_important')  # this is a string
is_important = {'True': True, 'False': False, 'None': None}[is_important]

I should maybe add that the instance returned by .objects.create() and the instance returned by .objects.get() are not necessarily identical even if the get call retrieves the db record that was inserted by the create call. The former will still have the attributes that were passed as kwargs (like the string 'False') whereas the latter will have the attributes as retrieved from the database (and thus the value of a BooleanField will now be cast to bool):

choice = Choice.objects.create(user=user, card=card, is_important=is_important)
# choice.is_important = 'False'

choice = Choice.objects.get(user=user, card=card, is_important=is_important)
# choice.is_important = True (= bool('False'))
user2390182
  • 72,016
  • 6
  • 67
  • 89
  • Thank you for your solution. {'True': True, 'False': False, 'None': None}[is_important] is such an intelligent way! – Huy Than May 15 '16 at 00:20
1

In addition to schwobaseggl's answer (another way) you better use Django forms with cleaned_data to prevent those complications.

trantu
  • 1,089
  • 8
  • 17
  • Thank you trantu. I don't use Django form because I think it is not necessary for this simple class Choice. Anyway, I will try forms once things get complicated. By the way, your name sounds Vietnamese? I am Vietnamese. – Huy Than May 15 '16 at 00:17
  • Hey. Tat nhien roi. MInh la nguoi Viet. Nhin cai ten la biet :) Nice to see you here, my friend :) – trantu May 15 '16 at 06:07