2

I have a models.py like so:

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


# everything has a colour...
class Colour(models.Model):
    colour = models.CharField(max_length=100)

    def __unicode__(self):
        return self.colour


# a thing can have a colour...
class Thing(models.Model):
    name = models.CharField(max_length=155)
    colour = models.ForeignKey(Colour)
    description = models.CharField(max_length=255)

    def __unicode__(self):
        return self.name


# a user can save his choices
class UserLikes(models.Model):
    user = models.ForeignKey(User)
    colour = models.ForeignKey(Colour)
    thing = models.ForeignKey(Thing)

    class Meta:
        verbose_name_plural = "User Likes"

    def __unicode__(self):
        return '%d - %s' % (self.pk, self.user)

And in my views:

def ThingPicker(request):
    if request.method == 'POST':
        form = ThingForm(request.POST)
        if form.is_valid():
            colour = form.cleaned_data['colour']
            thing = form.cleaned_data['thing']
            likes = UserLikes(user=request.user, colour=colour, thing=thing)
            likes.save()
            return HttpResponseRedirect('/profile/')
        else:
            return render_to_response('thing_picker.html', {
                'form': form,
            }, RequestContext(request))
    else:
        form = ThingForm()
        return render_to_response('thing_picker.html', {
            'form': form,
        }, RequestContext(request))

And in my tests.py I want to do something like this (EDITED):

class ViewTests(TestCase):
    def setUp(self):
        self.client = Client()      

    def test_thingpicker(self):
        User.objects.create_superuser('foo', '[email protected]', 'bar')
        self.client.login(username='foo', password='bar') # request.user is now user foo

        response = self.client.post('/colours/things/', {'colour': 1, 'thing': 2})
        userlike = UserLikes.objects.get(pk=1)
        self.assertEqual(userlike.colour_id, 1)

I get an error:

DoesNotExist: UserLikes matching query does not exist.

If I try with the test client in shell:

>>>  c = Client()
>>>  user1 = User.objects.create_superuser('foo', '[email protected]', 'bar')
>>>  c.login(username='foo', password='bar')
>>>  c.post('/colours/things/', {'user': user1, 'colour': 1, 'thing': 2})
>>>  userlike = UserLikes.objects.get(pk=1)
>>>  userlike.colour_id
1L

I get the expected result.

2 Answers 2

1

There's something weird with your view code (accidental cut and paste?), but from the following line of code:

likes = UserLikes(user=request.user, colour=colour, thing=thing)

I am guessing that you are getting the current logged in user. To correctly get your newly created superuser from your Test case, you should do this:

def test_thingpicker(self):
    user1 = User.objects.create_user('foo', '[email protected]', 'bar')

    self.client.login(username='foo', password='bar') # request.user is now user foo

    response = self.client.post('/colours/things/', {'colour': 1, 'thing': 2})
    userlike = UserLikes.objects.get(user=user1, color=1, thing=2)

In addition, you should note that request.user may be an AnonymousUser (see https://docs.djangoproject.com/en/dev/topics/auth/#django.contrib.auth.models.AnonymousUser) and hence you should check whether the user is logged in before creating an UserLikes.

You can do so by using the @login_required decorator (https://docs.djangoproject.com/en/dev/topics/auth/#the-login-required-decorator) or manually checking request.user.is_authenticated() (https://docs.djangoproject.com/en/dev/topics/auth/#django.contrib.auth.models.AbstractBaseUser.is_anonymous).

Why UserLikes was not created

From the view:

colour = form.cleaned_data['colour']
thing = form.cleaned_data['thing']
likes = UserLikes(user=request.user, colour=colour, thing=thing)

Note that the Model definition for UserLikes uses ForeignKey for Colour and Thing. I am guessing that colour and thing in the form is an IntegerField, so you need to retrieve the actual Colour and Thing objects.

color = Colour.objects.get(pk=form.cleaned_data['colour'])
thing = Thing.objects.get(pk=form.cleaned_data['thing'])
likes = UserLikes(user=request.user, colour=colour, thing=thing)

Of course, you need to ensure that a Colour and Thing object has been already created before.

Sign up to request clarification or add additional context in comments.

8 Comments

Thanks. So I changed the test code so that I test against the logged in user. I can simuate this with the Client in the shell, but the test still fails saying: DoesNotExist: UserLikes matching query does not exist..
I believe that the PK for your newly created UserLikes is not 1. Can you edit the original post for your View to show the correct code? There is currently a line of assertion mixed with the View code. I've edited the last line of code for test_thingpicker for a way to get the userlike object that you have just created.
oh yeah - saw the typo. Not sure why the pk wouldn't be 1 on a newly created db though?? Surely on a brand new db the pk will always be 1 won't it?
And your code adjustment still does not work for me. It is as though the UserLikes object is never created.
See my updated answer. You should also assert that an UserLikes object has been created before checking the PK (eg. UserLikes.objects.count() == 1) to ensure that UserLikes has been created successfully.
|
0

The final code which worked:

tests.py:

class ViewTests(TestCase):
    """
    Run before each test in class
    """
    def setUp(self):
        self.client = Client()
        self.user = User.objects.create_superuser(
            'foo',
            '[email protected]',
            'pass'
        )
        self.colour = Colour.objects.create(colour='Green')
        self.thing = Thing.objects.create(
            name='Leaf',
            colour=self.colour,
            description='leafy'
        )
        self.logged_in = self.client.login(
            username='foo',
            password='pass'
        )

    """
    Test whether user can login and post choice
    to db and then check if data can be retreived.
    """
    def test_thingpicker(self):
        # check new User object created
        self.assertEqual(User.objects.count(), 1)
        # check use is logged in
        self.assertEqual(self.logged_in, True)  # check login success

        # post some data
        response = self.client.post(
            '/colours/things/', {
            'colour': self.colour.pk,
            'thing': self.thing.pk
            })
        self.assertEqual(response.status_code, 200)

        # check object
        self.assertEqual(UserLikes.objects.count(), 1)
        userlikes = UserLikes.objects.get(
            user=self.user,
            colour_id=self.colour.pk,
            thing=self.thing.pk
        )
        self.assertEqual(userlikes.colour_id, self.colour.pk)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.