How instanciate table in createsuperuser - django

I have two tables Employee and Sector, the employee table has for foreign key the sector code (sectorCode) property of the Sector table. The Employee table inherits from the AbstractBaseUser class.
I would like to create a superuser with the command python manage.py createsuperuser.
I get an error: ValueError: Cannot assign "'Code1'": "Employee.sectorCode" must be a "Sector" instance.
(I added in the Sector table a row NameSector1; Code1)
I input these values:
λ python manage.py createsuperuser
registrationNumber: 001
Name: TestN1
FirstName: TestFN1
sectorCode: Code1
Password: ...
Error ...
How can I instantiate sector class in dialog ?
models.py
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
class MyUserManager(BaseUserManager):
def create_user(self, registrationNumber, firstName, name, sectorCode, password=None):
if not firstName: raise ValueError("firstName required")
if not name: raise ValueError("name required")
if not registrationNumber: raise ValueError("registrationNumber required")
if not sectorCode: raise ValueError("sectorCode required")
user=self.model(firstName = firstName, name = name, registrationNumber = registrationNumber, sectorCode = sectorCode)
user.set_password(password); user.save()
return user
def create_superuser(self, firstName, name, registrationNumber, sectorCode, password=None):
user=self.create_user(firstName = firstName, name = name, registrationNumber = registrationNumber, sectorCode = sectorCode, password = password)
user.is_admin=True; user.is_superuser=True
user.save()
return user
class Sector(models.Model):
nameSector = models.CharField(verbose_name = "nameSector", max_length=50)
sectorCode = models.CharField(verbose_name = "sectorCode", max_length=3, primary_key=True)
class Meta: db_table = "Sector"
class Employee(AbstractBaseUser):
firstName = models.CharField(verbose_name = "firstName", max_length=20)
name = models.CharField(verbose_name = "name", max_length=20)
registrationNumber = models.CharField(verbose_name="registrationNumber", max_length=20, primary_key=True)
sectorCode = models.ForeignKey(Sector, on_delete=models.CASCADE)
USERNAME_FIELD="registrationNumber"
REQUIRED_FIELDS = ["name", "firstName", "sectorCode"]
objects = MyUserManager()
class Meta: db_table = "Employee"

If you know the sector exists, you can work with:
class MyUserManager(BaseUserManager):
def create_user(
self, registrationNumber, firstName, name, sectorCode, password=None
):
if not firstName:
raise ValueError("firstName required")
if not name:
raise ValueError("name required")
if not registrationNumber:
raise ValueError("registrationNumber required")
if not sectorCode:
raise ValueError("sectorCode required")
user = self.model(
firstName=firstName,
name=name,
registrationNumber=registrationNumber,
sectorCode_id=sectorCode,
)
user.set_password(password)
user.save()
return user
# …
If you want to create a Sector in case that one is missing, you can use:
class MyUserManager(BaseUserManager):
def create_user(
self, registrationNumber, firstName, name, sectorCode, password=None
):
if not firstName:
raise ValueError("firstName required")
if not name:
raise ValueError("name required")
if not registrationNumber:
raise ValueError("registrationNumber required")
if not sectorCode:
raise ValueError("sectorCode required")
sector, __ = Sector.objects.get_or_create(
sectorCode=sectorCode, defaults={'nameSector': sectorCode}
)
user = self.model(
firstName=firstName,
name=name,
registrationNumber=registrationNumber,
sectorCode=sector,
)
user.set_password(password)
user.save()
return user
# …
Code1 will however not be valid, since the sector code has a maximum length of three characters.
Note: normally the name of the fields in a Django model are written in snake_case, not PascalCase, so it should be: first_name instead of firstName.

Related

Need help in django model

I have written a model for my django project.
This is my model
from django.utils.translation import ugettext_lazy as _
from django.db import models
from django.utils.crypto import get_random_string
from django.db import models
from django.contrib.auth.models import(
BaseUserManager,
AbstractBaseUser,
PermissionsMixin,
)
def generate_vid():
"""Generates a vid for the users"""
not_unique = True
while not_unique:
vid = get_random_string(10, 'abcdefg0123456789')
if not User.objects.filter(v_id = vid).exists():
not_unique=False
return vid
class UserManager(BaseUserManager):
"""Model for user manager"""
def create_user(self, username, password, **params):
"""Create and return a user"""
u_type = params.pop('usertype','v')
params.update({'usertype':u_type})
p_username = params.pop('parent_username', 0)
if(u_type=='v'):
pass
else:
parent_id = User.objects.filter(username = p_username).values_list('v_id')
params.update({'parent_id': parent_id})
user = self.model(username=username, **params)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, username, password, **params):
"""Create and return a user"""
params.setdefault('is_staff',True)
params.setdefault('is_superuser',True)
params.setdefault('is_active',True)
if params.get('is_staff') is not True:
raise ValueError(_('Superuser must have is_staff=True.'))
if params.get('is_superuser') is not True:
raise ValueError(_('Superuser must have is_superuser=True.'))
return self.create_user(username, password, **params)
class User(AbstractBaseUser, PermissionsMixin):
"""Models for user"""
v_id = models.CharField(
max_length=10,
default=generate_vid,
primary_key = True,
)
username = models.CharField(max_length=20, unique=True)
email = models.EmailField(blank=True, unique = True)
parent_id = models.ForeignKey('User', on_delete=models.SET_DEFAULT, default=0)
usertype = models.CharField(max_length=1, choices=[('f', 'family'), ('v', 'veteran')])
REQUIRED_FIELDS = ['usertype']
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
USERNAME_FIELD = 'username'
objects = UserManager()
def __str__(self):
return self.username
Now I want to impose the condition while creating a user such that every time I provide usertype=f, and I provide a username(say username='Test")
the parent_id of that particular entry is automatically set as the v_id of the username provided.
The parent_id is a self referential foreignkey.
This is the error showing while testing the feature
File "/py/lib/python3.9/site-packages/rest_framework/serializers.py", line 205, in save
self.instance = self.create(validated_data)
File "/app/user/serializers.py", line 17, in create
return get_user_model().objects.create_user(**validated_data)
File "/app/base/models.py", line 39, in create_user
user = self.model(username=username, **params)
File "/py/lib/python3.9/site-packages/django/db/models/base.py", line 485, in __init__
_setattr(self, field.name, rel_obj)
File "/py/lib/python3.9/site-packages/django/db/models/fields/related_descriptors.py", line 215, in __set__
raise ValueError(
ValueError: Cannot assign "<QuerySet []>": "User.parent_id" must be a "User" instance.
I think you can try signals to set data after creating a user account. You can choose from several types, but I would recommend you focus on pre_save and post_save.
UPDATE
I wrote examples, but the website will probably better illustrate it. In general, there are quite a few signals, but the most commonly used are pre_save and post_save.
#2 UPDATE
Try use a first or latest. Details in documentation.
parent_id = User.objects.filter(username = p_username).first()

Django Social Authentication Create New User With Custom Model

I'm trying to develop a Facebook social authentication feature on an application that uses a custom Django user model and django-rest-framework-social-oauth2 as the social authentication package. My custom user model is called 'Account' and it inherits from the AbstractBaseUser class. The Account model is shown below:
class Account(AbstractBaseUser):
# Account model fields:
email = models.EmailField(verbose_name='email', max_length=60, unique=True)
username = models.CharField(max_length=30, unique=True)
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
date_joined = models.DateTimeField(verbose_name='date joined', auto_now_add=True)
last_login = models.DateTimeField(verbose_name='last login', auto_now=True)
is_admin = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
# The user will log in with their email instead of username:
USERNAME_FIELD = 'email'
# Required fields when registering, other than the email:
REQUIRED_FIELDS = ['username', 'first_name', 'last_name']
# Telling the Account object how to use the account manager:
objects = MyAccountManager()
The function that handles creating a new user is called 'create_user' and is defined within my custom written MyAccountManager class which extends the Django BaseUserManager class. This is given below:
class MyAccountManager(BaseUserManager):
def create_user(self, email, username, first_name, last_name, password=None):
# Checking to see if correct function parameters have been passed in:
if not email:
raise ValueError('Users must have an email address')
if not username:
raise ValueError('Users must have a username')
if not first_name:
raise ValueError('Users must have a first name')
if not last_name:
raise ValueError('Users must have a last name')
# Creating the new user:
user = self.model(
email = self.normalize_email(email),
username = username,
first_name = first_name,
last_name = last_name,
)
user.set_password(password)
user.save(using = self._db)
return user
I've set up a working django-rest-framework-social-oauth2 url for creating a new user with a Facebook account. The relevant Facebook configuration in the Django settings.py file is shown below:
SOCIAL_AUTH_FACEBOOK_KEY = config('SOCIAL_AUTH_FACEBOOK_KEY')
SOCIAL_AUTH_FACEBOOK_SECRET = config('SOCIAL_AUTH_FACEBOOK_SECRET')
SOCIAL_AUTH_FACEBOOK_SCOPE = ['email']
SOCIAL_AUTH_FACEBOOK_PROFILE_EXTRA_PARAMS = { 'fields': 'id, name, email' }
The issue that I've been having is the following:
When the create_user function is called for a user that is using Facebook social login, the parameters email, first_name and last_name, that are required in the create_user function are not being provided by Facebook and I'm getting the error message shown in the image. The error message states the following:
create_user() missing 2 required positional arguments: 'first_name' and 'last_name'
Error Message from Django
Does anyone know how I would be able to access these additional parameters (email, first name, last name) from Facebook so that the correct parameters are passed into the create_user function?
Further Information
On implementing the pipeline suggestion I am still left with the same issue whereby the custom create_user function is missing both the first_name and last_name parameters. I think the reason that this occurring is due to the suggested pipeline cleanup_social_account function being called after create_user, where in my case both first_name and last_name are required fields, and as such a user object cannot be created in the database if they are not provided at the time the create_user function is called.
I am receiving this error due to the following function in the suggested custom pipeline:
social_core.pipeline.user.create_user
The code for this function in the social_core installed library is the following:
def create_user(strategy, details, backend, user=None, *args, **kwargs):
if user:
return {'is_new': False}
fields = dict((name, kwargs.get(name, details.get(name)))
for name in backend.setting('USER_FIELDS', USER_FIELDS))
if not fields:
return
return {
'is_new': True,
'user': strategy.create_user(**fields)
}
The details parameter passed into the above function contains the values that I need (first_name and last_name). However, they are not actually being added into the fields variable when it is created. The fields variable is shown above and is defined by the following:
fields = dict((name, kwargs.get(name, details.get(name)))
for name in backend.setting('USER_FIELDS', USER_FIELDS))
In summary:
The issue appears to be that first_name and last_name are not appearing within backend.settings('USER_FIELDS', USER_FIELDS), and therefore are not being added to the fields variable, and as such are not being passed into strategy.create_user(**fields).
So social_auth auto-populates those fields for me when I just get name and email from Facebook. It knows to bring in first_name and last_name. Since it doesn't seem to be working for you, you can create a custom pipeline function.
settings.py:
SOCIAL_AUTH_PIPELINE = (
'social_core.pipeline.social_auth.social_details',
'social_core.pipeline.social_auth.social_uid',
'social_core.pipeline.social_auth.auth_allowed',
'social_core.pipeline.social_auth.social_user',
'social_core.pipeline.user.get_username',
'social_core.pipeline.social_auth.associate_by_email',
'social_core.pipeline.user.create_user',
# YOUR CUSTOM PIPELINE FUNCTION HERE. I CREATED A FILE/MODULE
# NAMED pipeline.py AND STUCK IT IN THERE. MAKE SURE TO PUT THIS
# AFTER CREATE USER.
'path.to.custom.pipeline.cleanup_social_account',
'social_core.pipeline.social_auth.associate_user',
'social_core.pipeline.social_auth.load_extra_data',
'social_core.pipeline.user.user_details',
)
pipeline.py:
def cleanup_social_account(backend, uid, user=None, *args, **kwargs):
"""
3rd party: python-social-auth.
Social auth pipeline to cleanup the user's data. Must be placed
after 'social_core.pipeline.user.create_user'.
"""
# Check if the user object exists and a new account was just created.
if user and kwargs.get('is_new', False):
*** THIS IS UNTESTED, BUT FACEBOOK'S DATA SHOULD COME INTO THE DETAILS KWARG ***
user.first_name = kwargs['details']['first_name']
user.last_name = kwargs['details']['last_name']
user.save()
return {'user': user}
Just add SOCIAL_AUTH_GOOGLE_OAUTH2_USER_FIELDS = ['username', 'email', 'first_name', 'last_name'] in your settings.py file and these fields should be added to **kwargs in you create_user method.
Sample Usage
In settings.py file add this
SOCIAL_AUTH_GOOGLE_OAUTH2_USER_FIELDS = ['first_name', 'last_name', 'email']
In your UserManager class modify create_user like below
def create_user(self, password=None, **kwargs):
"""Create and return a `User` with an email, username and password."""
first_name = kwargs.get('first_name')
last_name = kwargs.get('last_name')
email = kwargs.get('email')
if first_name is None or last_name is None:
raise TypeError(f"Invalid FirstName: {first_name}, LastName: {last_name}, Email: {email}")
if email is None:
raise TypeError("Users must have an email address.")
user = self.model(
first_name=first_name,
last_name=last_name,
email=self.normalize_email(email),
)
user.set_password(password)
user.save()
return user

Django get_or_create only if form constraints are met

I have a form that asks for a song's Artist, Title and Mix. Artist and Title are required fields but Mix is not. The form should only save if Artist, Title and Mix does not exists. If the form has either empty Artist or Title field it should show "This field is required" on submit. The issue I'm having is if the Title field is empty but Artist is populated, it'll still create the Artist object with get_or_create (See ###forms.py below). How do I only create Artist object if the form is valid?
###########models.py
class Artist (models.Model):
name = models.CharField(max_length=100)
class Track (models.Model):
artist = models.ForeignKey(Artist, blank=True, null=True, on_delete=models.SET_NULL, verbose_name="Artist")
user = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True, on_delete=models.SET_NULL, verbose_name="Submitted by", default=1)
title = models.CharField(max_length=100, verbose_name="Title")
mix = models.CharField(max_length=100, blank=True, verbose_name="Mix")
###########views.py
class TrackCreateView(SuccessMessageMixin, AjaxCreateView):
form_class = ProfileForm
success_message = "Thank you for submitting track: %(artist)s - %(title)s - %(mix)s"
def get_initial(self):
self.initial.update({ 'user': self.request.user })
return self.initial
def get_success_message(self, cleaned_data):
return self.success_message % dict(cleaned_data,
artist=self.object.artist,
title=self.object.title,
)
###########forms.py
class ProfileForm(forms.ModelForm):
class Meta:
model = Track
fields = [
"artist",
"title",
"mix",
]
artist = forms.CharField(widget=forms.TextInput(attrs={'maxlength': '100',}))
def __init__(self, *args, **kwargs):
self.user = kwargs['initial']['user']
super(ProfileForm, self).__init__(*args, **kwargs)
# Set layout for fields.
my_field_text= [
('artist', 'Artist', ''),
('title', 'Title', ''),
('mix', 'Mix', ''),
]
for x in my_field_text:
self.fields[x[0]].label=x[1]
self.fields[x[0]].help_text=x[2]
self.helper = FormHelper()
self.helper.layout = Layout(
Div(
Div('artist', css_class="col-sm-4"),
Div('title', css_class="col-sm-4"),
Div('mix', css_class="col-sm-4"),
css_class = 'row'
),
)
def save(self, commit=True):
obj = super(ProfileForm, self).save(False)
obj.user = self.user
commit and obj.save()
return obj
def clean(self):
cleaned_data = super(ProfileForm, self).clean()
artist = self.cleaned_data.get('artist')
title = self.cleaned_data.get('title')
mix = self.cleaned_data.get('mix')
if artist and title:
title = ' '.join([w.title() if w.islower() else w for w in title.split()])
if mix:
mix = ' '.join([w.title() if w.islower() else w for w in mix.split()])
if Track.objects.filter(artist=artist, title=title, mix=mix).exists():
msg = "Record with Artist and Title already exists."
if mix:
msg = "Record with Artist, Title & Mix already exists."
self.add_error('mix', msg)
self.add_error('artist', msg)
self.add_error('title', msg)
if not artist:
raise forms.ValidationError("Artist is a required field.")
else:
artist, created = Artist.objects.get_or_create(name=artist)
self.cleaned_data['artist'] = artist
self.cleaned_data['title'] = title
self.cleaned_data['mix'] = mix
return self.cleaned_data
How about changing your comparison, by first checking if your form is valid in clean()?
def clean(self):
...
if not artist:
raise ValidationError("artist is a required field")
if not title:
raise ValidationError("title is a required field")
...
The above makes it a two-step process for the user, since if a user leaves both artist and title blank, they ony get the artist notice.
You could make a better (sub) if statement and a combined ValidationError, or solve that by using clean_artist and clean_title, just for raising the ValidationError (not using get_or_create in the field clean methods):
def clean_artist(self):
# no get_or_create here
...
if not artist:
raise ValidationError("artist is a required field")
def clean_title(self):
# no get_or_create here
...
if not title:
raise ValidationError("title is a required field")
def clean(self):
...
if title and artist:
# get_or_create stuff here
...
This way, you should get both errors independently, but the get_or_create is still done in the main clean, only if title and artist are valid.

python-social not saving response to custom model

Ive been running into a number of problem in relation to using django's custom model. This one in particular is not raising any errors. For some reason after authenticating via steam and returning to the landing page the database tables for both steamuser_user (custom user) and social_auth_usersocialauth are empty. Nothing is being saved, no errors are being displayed etc.
My custom model which is quite similar to the one on django docs official page is as follows:
from django.db import models
from django.contrib.auth.models import AbstractBaseUser
from django.contrib.auth.models import BaseUserManager
# Create your models here.
class UserManager(BaseUserManager):
def create_user(self, steamid, username, password=None):
if not steamid:
msg = 'User has no Steam ID set'
raise ValueError(msg)
if not username:
msg = 'User has no name set'
raise ValueError(msg)
user = self.model(steamid=steamid,
username=username)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, steamid, username, password):
super_user = self.create_user(steamid=steamid,
username=username,
password=password)
super_user.is_staff = True
super_user.is_admin = True
super_user.is_mod = True
super_user.save(using=self._db)
return super_user
class User(AbstractBaseUser):
steamid = models.CharField(max_length=20, unique=True)
username = models.CharField(max_length=80)
email = models.EmailField(null=True,blank=True)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_admin = models.BooleanField(default=False)
is_mod = models.BooleanField(default=False)
date_joined = models.DateTimeField(auto_now_add=True)
reputation = models.IntegerField(max_length=6, default=0)
USERNAME_FIELD = 'steamid'
objects = UserManager()
def __unicode__(self):
return self.username
def get_full_name(self):
return self.steamid
def get_short_name(self):
return self.username
The settings I've used are as follows:
SOCIAL_AUTH_USER_MODEL = 'steamuser.User'
AUTH_USER_MODEL = 'steamuser.User'
TEMPLATE_CONTEXT_PROCESSORS = global_settings.TEMPLATE_CONTEXT_PROCESSORS + (
'social.apps.django_app.context_processors.backends',
'social.apps.django_app.context_processors.login_redirect',
)
AUTHENTICATION_BACKENDS = (
'social.backends.steam.SteamOpenId',
'django.contrib.auth.backends.ModelBackend',
)
#Steam OpenAuth
SOCIAL_AUTH_STEAM_API_KEY = 'B1D7C629D093D4B72577F2F11DE4EBE2'
LOGIN_URL = '/'
SOCIAL_AUTH_LOGIN_REDIRECT_URL = '/'
SOCIAL_AUTH_ENABLED_BACKENDS = (
'steam',
)
Any help would be appreciated!
EDIT
Backends steam.py
def get_user_details(self, response):
player = self.get_json(USER_INFO, params={
'key': self.setting('API_KEY'),
'steamids': self._user_id(response)
})
if len(player['response']['players']) > 0:
player = player['response']['players'][0]
details = {'steamid': player.get('steamid'),
'username': player.get('personaname'),
}
else:
details = {}
return details
EDIT 2
Well despite my logical reasoning, I just gave up and created a custom pipeline to create the new steam user as follows:
from django.contrib.auth import get_user_model
def create_steamuser(details, user=None, *args, **kwargs):
if user:
return {'is_new': False}
if not details:
return
try:
steam_user = get_user_model().objects.get(steamid=details['steamid'])
except steam_user.DoesNotExist:
get_user_model().objects.create_user(details['steamid'], details['username'])
return {
'is_new': True,
}
Now I still have the problem where social_user is not being created. I've set the social user model to use my new custom model but there must be something that I am missing.
python-social-auth won't be able to pass the steamid and date_joined parameters to your custom create_user() method in the manager. To make that possible you have three options:
Set =None to those parameters and set some default vaules for them
Override the default create_user pipeline and pass the extra parameters.
Add a custom pipeline function before create_user and fill details with steamid and date_joined, then define SOCIAL_AUTH_STEAM_USER_FIELDS = ('username', 'email', 'steamid', 'date_joined').

Django authentication - modifying existing user on signup

I am building a photo sharing site with django where users are allowed to create groups to share photos. I have problems creating a proper user data model/logic which would cover all my requirements.
The basic requirements are:
User A is allowed to create a group where he can add another users (User B)
If the user B which has to be added to the group already exists then we will use this existing user B to be added to manytomany field of the group model representing the group
If the user B doesn't exist we will create a sort of "dummy" user. Setting the user_active to false. This is because the user B doesn't have set any sort of verification or password yet.
Now if the new added user B wants to be registered to the site, instead of creating a new user I would like to change the already existing user with the provided data from the signup form.
I would like to mention that I plan to use also the django-allauth for the social accounts users.
My question (considering the Django 1.5) is what would be the preferred way how to make this working:
Is this is something I should create my own User Manager or should I look into authentication backends ? I am really lost at this point.
Below is the diagram which represent both of the scenarios, signing up and adding of the user to the group:
http://i821.photobucket.com/albums/zz136/jorge_sanchez4/f79934d4-d0a4-4862-ab8b-7e1d09cd5642_zps06ec08f3.jpg
UPDATE:
So I tried following, created the custom user model where in the __new__ method I am returning the relevant object if it already exists and the is_active is set to False. Below is the both UserManager and user model:
class GruppuUserManager(BaseUserManager):
def create_user(self, username, email=None, password=None, phonenumber=None, **extra_fields):
now = timezone.now()
if not username:
raise ValueError('The given username must be set')
if not phonenumber:
raise ValueError('The given phonenumber must be set')
''' now lookup the user if it exists and is_active is set
then it is duplicate, otherwise return the user
and set the is_active to true '''
email = self.normalize_email(email)
if GruppUser.objects.filter(phonenumber__exact=phonenumber).exists():
if GruppUser.objects.filter(phonenumber__exact=phonenumber).values('is_active'):
''' duplicate - raise error '''
raise ValueError('The user is duplicate ')
else:
''' get the subscriber and set all the values '''
user = GruppUser.objects.filter(phonenumber__exact=phonenumber)
user.set_password(password)
user.is_active=True
if email:
user.email = email
user.save(using=self._db)
return user
user = self.model(username=username, email=email,
is_staff=False, is_active=True, is_superuser=False,
last_login=now, date_joined=now, phonenumber=phonenumber, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, username, email=None, password=None, phonenumber=None, **extra_fields):
u = self.create_user(username, email, password, phonenumber, **extra_fields)
u.is_staff = True
u.is_active = True
u.is_superuser = True
u.save(using=self._db)
return u
class GruppUser(AbstractBaseUser, PermissionsMixin):
''' django 1.5 - creating custom user model '''
id = models.AutoField(primary_key=True)
username = models.CharField(_('username'), max_length=30, unique=True,
help_text=_('Required. 30 characters or fewer. Letters, numbers and '
'#/./+/-/_ characters'),
validators=[
validators.RegexValidator(re.compile('^[\w.#+-]+$'), _('Enter a valid username.'), 'invalid')
])
first_name = models.CharField(_('first name'), max_length=30, blank=True)
last_name = models.CharField(_('last name'), max_length=30, blank=True)
email = models.EmailField(_('email address'), 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)
phonenumber = models.CharField(max_length=10)
#following = models.ManyToManyField(Stream,blank=True,null=True)
blocked_con = models.ManyToManyField(Blocked_Content,blank=True,null=True)
mmsemail = models.EmailField(_('email address'), blank=True)
smsemail = models.EmailField(_('email address'), blank=True)
verified = models.BooleanField(_('verified'), default=False,
help_text=_('Defines if the user has been verified'))
objects = GruppuUserManager()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['phonenumber']
class Meta:
verbose_name = _('user')
verbose_name_plural = _('users')
def __init__(self,phone=None,*args, **kwargs):
''' save the phone number '''
super(GruppUser,self).__init__(*args, **kwargs)
self.phonetocheck = phone
#staticmethod
def __new__(cls,phone=None,*args, **kwargs):
''' lookup for the same user '''
if GruppUser.objects.filter(phonenumber__exact=phone).exists():
if self.objects.filter(phonenumber__exact=phone).values('is_active'):
''' duplicate - raise error '''
raise ValueError('The user is duplicate')
else:
''' get the subscriber and set all the values '''
user = self.objects.filter(phonenumber__exact=phone)
user.is_active = True
return user
return super(GruppUser,cls).__new__(cls,*args, **kwargs)
def get_full_name(self):
"""
Returns the first_name plus the last_name, with a space in between.
"""
full_name = '%s %s' % (self.first_name, self.last_name)
return full_name.strip()
def get_short_name(self):
"Returns the short name for the user."
return self.first_name
def email_user(self, subject, message, from_email=None):
"""
Sends an email to this User.
"""
send_mail(subject, message, from_email, [self.email])
Anyway the strange issue I am having right now is that I can't connect to the admin site which is giving me following error:
I have traced the django and it seems that the query set is somehow shifted to the left:
(Pdb) context[self.user].phonenumber
u''
(Pdb) context[self.user].date_joined
u'9135261969'
(Pdb) context[self.user].is_active
datetime.datetime(2013, 9, 8, 20, 47, 30, tzinfo=<UTC>)
But the data in mysql is correct:
mysql> select is_active from demo_app_gruppuser;
+-----------+
| is_active |
+-----------+
| 1 |
+-----------+
1 row in set (0.00 sec)
mysql> select phonenumber from demo_app_gruppuser;
+-------------+
| phonenumber |
+-------------+
| 9135261969 |
+-------------+
1 row in set (0.00 sec)
mysql> select date_joined from demo_app_gruppuser;
+---------------------+
| date_joined |
+---------------------+
| 2013-09-08 20:47:30 |
+---------------------+
1 row in set (0.00 sec)
Here is the backtrace when trying to login to the admin:
20. context[self.varname] = LogEntry.objects.filter(user__id__exact=user_id).select_related('content_type', 'user')[:int(self.limit)]
File "/usr/site/gruppe/lib/python2.7/site-packages/django/db/models/manager.py" in filter
155. return self.get_query_set().filter(*args, **kwargs)
File "/usr/site/gruppe/lib/python2.7/site-packages/django/db/models/query.py" in filter
667. return self._filter_or_exclude(False, *args, **kwargs)
File "/usr/site/gruppe/lib/python2.7/site-packages/django/db/models/query.py" in _filter_or_exclude
685. clone.query.add_q(Q(*args, **kwargs))
File "/usr/site/gruppe/lib/python2.7/site-packages/django/db/models/sql/query.py" in add_q
1259. can_reuse=used_aliases, force_having=force_having)
File "/usr/site/gruppe/lib/python2.7/site-packages/django/db/models/sql/query.py" in add_filter
1190. connector)
File "/usr/site/gruppe/lib/python2.7/site-packages/django/db/models/sql/where.py" in add
71. value = obj.prepare(lookup_type, value)
File "/usr/site/gruppe/lib/python2.7/site-packages/django/db/models/sql/where.py" in prepare
339. return self.field.get_prep_lookup(lookup_type, value)
File "/usr/site/gruppe/lib/python2.7/site-packages/django/db/models/fields/__init__.py" in get_prep_lookup
322. return self.get_prep_value(value)
File "/usr/site/gruppe/lib/python2.7/site-packages/django/db/models/fields/__init__.py" in get_prep_value
555. return int(value)
Exception Type: ValueError at /admin/
Exception Value: invalid literal for int() with base 10: 'root'
Also in pdb is interesting that self.user.id which should be in this case 1 is returning "root" back. Seems that somehow django messed up what my pk are in this model even when I specified it in the model :
id = models.AutoField(primary_key=True)
Turns out that using __new__ method on Django model is not good idea, using the Model Manager create_user is working ok.