I'm trying to set up an app that will handle reviews about registered users. So in my Review model, I want to have a ForeignKey to my User model.
I'm using a custom user profile that looks like this:
#In /profiles/models.py
class MyUser(AbstractBaseUser):
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
company = models.CharField(default="", max_length=200)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
objects = MyUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['company']
I have included it with settings.py AUTH_USER_MODEL = "profiles.MyUser". It works fine with registration, creating users etc. So I know its working.
In my review model I write the following:
class Review(models.Model):
company = models.ForeignKey(settings.AUTH_USER_MODEL)
reviewer = models.ForeignKey(Reviewer)
rating = models.IntegerField(default=0)
review = models.TextField()
pub_date = models.DateTimeField('date published')
Instead of settings.AUTH_USER_MODEL I have also tried writing profiles.MyUser, 'profiles.MyUser' and MyUser.
I can successfully use the python manage.py makemigrations reviews command. But when I do python manage.py migrate I get errors no matter what version I use above.
The error I get is the following:
ValueError: Lookup failed for model referenced by field reviews.Review.company: profiles.MyUser
nejc92 comment was correct. I had migrated my database earlier before I set AUTH_USER_MODEL for the first time.
I removed my whole database and created new migrations for all apps and migrated everything again from scratch. It then worked.
Sounds like a bug(?) to me.
Related
I have just switched to PostegreSQL. Now whenever I add the following code to my Custom User Model, the database is broken, no new values are added to the database, for example during registration
from django.contrib.postgres.fields import ArrayField
class NewUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_('Email'), unique=True)
username = models.CharField(max_length=150, unique=True)
start_date = models.DateTimeField(default=timezone.now)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
last_login = models.DateTimeField(default=timezone.now)
code = models.ImageField(blank=True, upload_to='code',)
#part that breaks the databse:
ip_addresses = ArrayField(
models.CharField(blank=True), default=list)
From the moment also no more migrations are recognized.
Or I get something like this
django.db.utils.ProgrammingError: column "ip_addresses" does not exist
LINE 1: ...ER COLUMN "ip_addresses" TYPE varchar(15)[] USING "ip_addres...
What error I get is 50 50 chance but atleast the first error is always here.
I also tried this which did not work either
ip_addresses = ArrayField(
models.CharField(max_length=15), default=list)
I am trying to migrate, and view the admin page. both makemigrations and migrate passed, yet when i go to the admin url it reads this: "django.db.utils.OperationalError: no such column: social_app_user.id"
And once i create an id field, it changes to "django.db.utils.OperationalError: no such column: social_app_user.password"
I was under the impression that the AbstractUser model included all the default user fields, not sure about the primary key, but regardless.
Please help, thanks!
Note: the 'id' field in this models.py file was added after i got the error.
from django.contrib.auth.models import AbstractUser, UserManager
from django.db import models
class User(AbstractUser):
is_verified = models.BooleanField(default=True)
id= models.AutoField(primary_key=True, null=False)
REQUIRED_FIELDS = []
objects = UserManager()
def __str__(self):
f"{self.username} {self.email}"
return
class main_feed(models.Model):
content= models.CharField(unique=True, max_length=255, default='', null=False)
poster = models.ForeignKey('User', related_name='author', on_delete=models.CASCADE, to_field='username')
likes = models.IntegerField(default=0, null=False)
favorites = models.IntegerField(default=0, null=False)
date_posted = models.DateTimeField(auto_now=True)
def __str__(self):
f"{self.content} {self.likes} {self.poster} {self.date_posted}"
return
It turns out I had to restart my entire application and run startapp again.
This time i added the user model and set up the settings and admin file BEFORE the very first migration. then everything works dandy. But I have no idea why this is the case, shouldnt the migration update and override the default user model?
anyways the question is answered now.
I have the below in my models.py file:
class Film(models.Model):
title = models.CharField(max_length=200)
director = models.CharField(max_length=200)
description = models.CharField(max_length=200)
pub_date = models.DateField('date published')
class Comment(models.Model):
film = models.ForeignKey(Film, on_delete=models.CASCADE)
body = models.CharField(max_length=200)
When I logged into Django admin I added some films, and then added some comments, selecting which film object the comment related to. I then created a couple of users via the admin panel also.
I would like my relationships to be:
Film can have many comments / Comments belong to film
User can have many comments / Comments belong to user
I think, like with comments and films, I just need to define user as a foreign key to comment. I am struggling to do this. I am working through the Django tutorials but I can't see the tutorials covering how I can link other tables to the user.
I thought I would be able to do something like this:
user = models.ForeignKey(User, on_delete=models.CASCADE)
While importing User like this:
from django.contrib.auth.models import User
The result at the moment is if I keep user = models.ForeignKey(User, on_delete=models.CASCADE) I get err_connection_refused
Maybe have you changed your default user model in the settings?
Instead of using User directly with the the Foreign key, you should use user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) in your Comment Model, as follow
class Comment(models.Model):
film = models.ForeignKey(Film, on_delete=models.CASCADE)
body = models.CharField(max_length=200)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
You need to apply migrations to be able to add user to Comment,
python manage.py makemigrations
python manage.py migrate
if at the moment that you are applying migrations, shell shows a message telling You are trying to add a non-nullable field 'user' to comment without a default
You have 2 Options
Skip migrations and add a default value to the field in the models or set the attribute as nullable, whatever else that you need
ie
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True, blank=True)
and apply migrations again
Or select a default value to the new field, should be an id of an existing user in databse
This is because django should populate existing records in database, if exist
Use "settings.AUTH_USER_MODEL".
So, import "settings" from "django.conf", then use "settings.AUTH_USER_MODEL" as shown below:
from django.db import models
from django.conf import settings # Here
class Comment(models.Model):
film = models.ForeignKey(Film, on_delete=models.CASCADE)
body = models.CharField(max_length=200)
# Here
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
How do I extend the django-oscar customer models fields? I have extended the registration form to include more fields, in apps/customer/forms.py
class EmailUserCreationForm(forms.ModelForm):
email = forms.EmailField(label=_('Email address'))
password1 = forms.CharField(
label=_('Password'), widget=forms.PasswordInput,
validators=password_validators)
password2 = forms.CharField(
label=_('Confirm password'), widget=forms.PasswordInput)
#### The extra fields I want to add #####
first_name = forms.CharField(label=_('First name'))
last_name = forms.CharField(label=_('Last name'))
business_name = forms.CharField(label=_('Business name'))
business_address = forms.CharField(label=_('Business address'))
city = forms.CharField(label=_('City'))
I have also extended the [AbstractUser][1]'s fields in apps/customer/abstract_models.py.
class AbstractUser(auth_models.AbstractBaseUser,
auth_models.PermissionsMixin):
"""
An abstract base user suitable for use in Oscar projects.
This is basically a copy of the core AbstractUser model but without a
username field
"""
email = models.EmailField(_('email address'), unique=True)
first_name = models.CharField(
_('First name'), max_length=255, blank=True)
last_name = models.CharField(
_('Last name'), max_length=255, blank=True)
is_staff = models.BooleanField(
_('Staff status'), default=False,
help_text=_('Designates whether the user can log into this admin '
'site.'))
is_active = models.BooleanField(
_('Active'), default=True,
help_text=_('Designates whether this user should be treated as '
'active. Unselect this instead of deleting accounts.'))
date_joined = models.DateTimeField(_('date joined'),
default=timezone.now)
#######################################
# Additional user fields I have added #
#######################################
business_name = models.CharField(
_('Business name'), max_length=255, blank=True)
business_address = models.CharField(
_('Business address'), max_length=255, blank=True)
city = models.CharField(
However, when a user is created, the additional fields are not getting saved to the database. Is there a better way of extending the customer model to include additional fields I'm not aware of?
When I try to debug in the shell, I run into the issue where the model is not callable:
>>> from apps.customer.abstract_models import *
>>> mg = UserManager()
>>> mg.create_user('testemail#test.com', 'testpassword', buisness_name='test_business')
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "<my_working_dir>/apps/customer/abstract_models.py", line 34, in create_user
last_login=now, date_joined=now, **extra_fields)
TypeError: 'NoneType' object is not callable
I'm not sure the instructions given in django oscar's docs will work, as that is for customizing methods, not fields on the model.
Any help would be appreciated.
Edit:
INSTALLED_APPS = INSTALLED_APPS + get_core_apps(
['apps.shipping',
'apps.checkout',
'apps.partner',
'apps.catalogue',
'apps.customer',
])
AUTH_USER_MODEL = 'customer.User'
There are a few issues that I can see, resolving which will hopefully fix your problem:
Move your subclass of AbstractUser into apps/customer/models.py which is where Django looks for models. You've put it in apps/customer/abstract_models.py which is a non-standard location for storing models (Oscar does this for abstract models only - you are not supposed to mirror this location yourself). Django will not find them there.
Change your class name to User instead of AbstractUser, because your final model is not abstract. You are also specifying customer.User in your AUTH_USER_MODEL - these two need to match.
The model class you have posted above is incomplete so we cannot tell - but make sure that it doesn't contain abstract = True in the Meta class.
Run manage.py makemigrations which should create migrations for your new user model (if it doesn't then there's still something wrong with your app structure). (Next run manage.py migrate).
Don't forget to import the rest of the (core) customer models at the bottom of your models.py: from oscar.apps.customer.models import *. Without these you will lose all the other models that live in the core customer app.
You should also take note of the warning in the documentation regarding changing the user model (emphasis mine):
Changing AUTH_USER_MODEL has a big effect on your database structure.
It changes the tables that are available, and it will affect the
construction of foreign keys and many-to-many relationships. If you
intend to set AUTH_USER_MODEL, you should set it before creating any
migrations or running manage.py migrate for the first time.
Changing this setting after you have tables created is not supported
by makemigrations and will result in you having to manually fix your
schema, port your data from the old user table, and possibly manually
reapply some migrations.
I'm working on an existing Django project in Django 1.4. I want to upgrade to Django 1.5 for implementing a custom user model. I have to ensure that my existing information is not deleted from the database(Postgres 9.1).
This post explains the steps to be done for data migration using South but only for AbstractUser. I have to use AbstractBaseUser. Is there any way?
My existing model is like :
class Individual(models.Model):
user = models.ForeignKey(User, unique=True, blank=True, null=True)
parent = models.ForeignKey('self', unique=True, blank=True, null=True)
....(some many to many and foreign key)
I want to change it to something like this.
class User(AbstractBaseUser, Individual, PermissionsMixin):
email = models.EmailFeild(max_length=50, unique=True)
is_admin = models.BooleanField(default=False)
username = models.CharField(max_length=50,unique=True)
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email']
The individual class will contain all previous fields except the user. How can I go about doing this?
Document how to migrate from a built-in User model to a custom User model thread has some workaround discussions.