Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing with a custom user model as a ForeignKey in Django 1.5

I'm using Django 1.5 and I'm trying to make an application work with any custom user model. I've changed the app to use get_user_model everywhere and the app itself is not showing any problems so far.

The issue is that I want to be able to test the app as well, but I can't find a way to make ForeignKey model fields to test correctly using custom user models. When I run the test case attached below, I get this error:

ValueError: Cannot assign "<NewCustomUser: [email protected]>": "ModelWithForeign.user" must be a "User" instance.

This is the file I'm using for testing:

from django.conf import settings
from django.contrib.auth import get_user_model
from django.contrib.auth.tests.custom_user import CustomUser, CustomUserManager
from django.db import models
from django.test import TestCase
from django.test.utils import override_settings

class NewCustomUser(CustomUser):
    objects = CustomUserManager()
    class Meta:
        app_label = 'myapp'

class ModelWithForeign(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL)

@override_settings(
    AUTH_USER_MODEL = 'myapp.NewCustomUser'
)   
class MyTest(TestCase):
    user_info = {
        'email': '[email protected]',
        'date_of_birth': '2013-03-12',
        'password': 'password1'
    }   

    def test_failing(self):
        u = get_user_model()(**self.user_info)
        m = ModelWithForeign(user=u)
        m.save()

I'm referencing the user model in the ForeignKey argument list as described here, but using get_user_model there doesn't change anything, as the user attribute is evaluated before the setting change takes place. Is there a way to make this ForeignKey play nice with testing when I'm using custom user models?

like image 534
fcoelho Avatar asked Oct 22 '22 15:10

fcoelho


1 Answers

I asked about this on the Django mailing list as well but it seems that, at least currently, there is no way to change the settings.AUTH_USER_MODEL and have it work nicely with a ForeignKey.

So far, in order to test my app, I've created a runtests.py file from this answer:

import os, sys
from django.conf import settings

if len(sys.argv) >= 2:
    user_model = sys.argv[1]
else:
    user_model = 'auth.User'

settings.configure(
    ...
    AUTH_USER_MODEL=user_model,
    ...
)

...

And added a bash script to actually run the tests using different user models:

for i in "auth.User" "myapp.NewCustomUser"; do
    echo "Running with AUTH_USER_MODEL=$i"
    python runtests.py $i
    if [ $? -ne 0 ]; then
        break
    fi
done

The last bit is to use a function to actually retrieve the right user model info instead of just using a "static" variable:

def get_user_info():
    if settings.AUTH_USER_MODEL == 'auth.User':
        return {default user info}
    if settings.AUTH_USER_MODEL == 'myapp.NewCustomUser':
        return {my custom user info}
    raise NotImplementedError

I'm not claiming this to be a correct answer for the problem, but so far... It works.

like image 55
fcoelho Avatar answered Oct 24 '22 06:10

fcoelho