How to avoid the use of ManytoMany field in Django? - python

I have the Role model. Account model take the reference from Role model using ManytoMany Field. But, I don't want to use manytomany field. It's necessary to not use ManyToMany field. Is anyone can suggest something better.
I don't want to use use ManyToMany field because, since many to many are a Django feature and not database
The given below model works fine with ManyToMany Field, I want the same with it.
from django.db import models
from django.db.models.fields import proxy
from django.contrib.auth.models import BaseUserManager, AbstractBaseUser
from django.utils.translation import gettext_lazy as _
from django.core.validators import RegexValidator
import uuid
from django.utils import timezone
import math
from django.core.validators import MinValueValidator, MaxValueValidator
ADMIN = 0
CUSTOMER = 1
SELLER = 2
DELIVERY_PARTNER = 4
class Role(models.Model):
'''
The Role entries are managed by the system,
automatically created via a Django data migration.
'''
ROLE_CHOICES = (
(ADMIN, 'admin'),
(CUSTOMER, 'customer'),
(SELLER, 'seller'),
(DELIVERY_PARTNER, 'delivery'),
)
id = models.PositiveSmallIntegerField(choices=ROLE_CHOICES, primary_key=True)
def __str__(self):
return self.get_id_display()
class UserManager(BaseUserManager):
'''
creating a manager for a custom user model
https://docs.djangoproject.com/en/3.0/topics/auth/customizing/#writing-a-manager-for-a-custom-user-model
https://docs.djangoproject.com/en/3.0/topics/auth/customizing/#a-full-example
'''
def create_user(self, mobile_number, password=None):
"""
Create and return a `User` with an email, username and password.
"""
if not mobile_number:
raise ValueError('Users Must Have an email address')
user = self.model(
mobile_number=self.normalize_email(mobile_number)
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, mobile_number, password):
"""
Create and return a `User` with superuser (admin) permissions.
"""
if password is None:
raise TypeError('Superusers must have a password.')
user = self.create_user(mobile_number, password)
user.is_superuser = True
user.is_staff = True
user.save()
return user
class Account(AbstractBaseUser):
'''Account Model to store mobile number and authentication'''
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
email = models.EmailField(
verbose_name='email address',
max_length=255,
null = True,
)
type = models.ManyToManyField(Role,default=[1])
phone_regex = RegexValidator(regex=r'^\+?1?\d{9,15}$', message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.")
mobile_number = models.CharField(validators=[phone_regex], max_length=17, blank=False,null = False, unique=True)
otp = models.CharField(max_length=6, null = True, unique=True)
user_registered_on = models.DateTimeField(default=timezone.now, blank=True)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
USERNAME_FIELD = 'mobile_number'
REQUIRED_FIELDS = []
# Tells Django that the UserManager class defined above should manage
# objects of this type.
objects = UserManager()
def get_full_name(self):
pass
def get_short_name(self):
pass
# #property
# def is_superuser(self):
# return self.is_superuser
#property
def is_staff(self):
return self.is_superuser
def has_perm(self, perm, obj=None):
return self.is_superuser
def has_module_perms(self, app_label):
return self.is_superuser
#is_staff.setter
def is_staff(self, value):
self._is_staff = value
def __int__(self):
return self.mobile_number
def verify_user_type(self,type):
for x in self.type.all():
if x.id == type:
return True
return False
class Meta:
'''
to set table name in database
'''
db_table = "login"

I don't want to use use ManyToManyField because, since many to many are a Django feature and not database
There is nothing special about a ManyToManyField. Behind the curtains it creates a model (named appname_modename_m2mfieldname) with two ForeignKeys: one to the "source model" and one to the "target model". This is a pattern known as a junction table [wiki], which is how many-to-many relations are normally defined in a relational database.
You can even work with the "hidden" model with Account.type.through, which will return a reference to a model class.
While you can define an extra model for the junction table yourself, it makes no sense, and will only make the ORM more complicated. For more information, see the database representation section on the ManyToManyField [Django-doc].

Related

Can't login in admin panel with superuser or with normal users with custom User Model

I created a AbstractUser model in Django which adds some custom fields, but now whenever I create a user (whether by calling User.create_user() or with python manage.py createsuperuser), the user is created fine with a hashed password, but I cannot use the password to login. When I try to login on the admin console, I get "Please enter the correct username and password for a staff account. Note that both fields may be case-sensitive." I cannot for the life of me figure out what is going wrong since in my database, the correct username + a hashed password appear when I create a user.
This is my user Model
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.contrib.auth.base_user import BaseUserManager
class AccountManager(BaseUserManager):
use_in_migrations = True
def _create_user(self, username, password, avg_recipe_rating=None, num_ratings_received=0, num_recipes_created=0):
user = self.model(username=username)
user.set_password(password)
user.num_ratings_received=num_ratings_received
user.num_recipes_created=num_recipes_created
user.avg_recipe_rating=avg_recipe_rating
user.save(using=self._db)
return user
def create_user(self,username, password, avg_recipe_rating=None, num_ratings_received=0, num_recipes_created=0):
return self._create_user(username, password, avg_recipe_rating, num_ratings_received, num_recipes_created)
def create_superuser(self,username, password, avg_recipe_rating=None, num_ratings_received=0, num_recipes_created=0):
return self._create_user(username, password, avg_recipe_rating, num_ratings_received, num_recipes_created)
class User(AbstractUser):
user_id = models.AutoField(primary_key=True)
avg_recipe_rating = models.FloatField(blank=True, null=True)
num_ratings_received = models.IntegerField(null=False)
num_recipes_created = models.IntegerField()
last_login = None
groups = None
user_permissions = None
first_name = None
last_name = None
email = None
date_joined = None
objects = AccountManager()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = []
#property
def is_staff(self):
return True
#property
def is_active(self):
return True
#property
def is_superuser(self):
return True
class Meta:
managed = True
db_table = 'SampleUser'

How to set up Django permissions for a custom user?

Good evening!
I have the following, a table containing my custom users (our dear Fellows) which will serve to login our users (by using the custom model).
◢ The custom backends with it's custom user model for the Fellows table.
from django.contrib.auth.hashers import check_password
from django.contrib.auth.models import User
from .models import CustomUser
class FellowBackend:
def authenticate(self, request, **kwargs):
'''Authenticates the user (custom model).'''
# Parameters
user_id = kwargs['username']
password = kwargs['password']
# Tentatives.
try:
user = CustomUser.objects.get(id = user_id)
# If the password matches.
if check_password(password, user.password):
return user
else:
# Triggers default login failed.
return None
except CustomUser.DoesNotExist:
return None
def get_user(self, user_id):
'''TODO: Test if this override is required.'''
try:
return CustomUser.objects.get(pk = user_id)
except CustomUser.DoesNotExist:
return None
◢ The custom user model.
class Faction(models.Model):
id = models.AutoField(db_column='ID', primary_key=True) # Field name made lowercase.
name = models.CharField(db_column='Name', max_length=64) # Field name made lowercase.
class Meta:
managed = False
db_table = 'Faction'
class CustomUser(AbstractBaseUser):
id = models.PositiveBigIntegerField(db_column='ID', primary_key=True) # ID.
display_name = models.CharField(db_column='Name', max_length=64, db_collation='utf8mb4_general_ci')
password = models.CharField(db_column='User_Password', max_length=256, blank=True, null=True)
gold = models.IntegerField(db_column='Gold') # Credits.
faction = models.ForeignKey('Faction', models.RESTRICT, db_column='Faction', default=1) # ID Faction.
last_login = models.DateTimeField(db_column='Last_Login', blank=True, null=True) # Last Login.
# Admin Panel Abstract Fields
active = models.BooleanField(default=True)
staff = models.BooleanField(default=False)
USERNAME_FIELD = 'id'
REQUIRED_FIELD = [] # id (username) and password required by default.
class Meta:
managed = False
db_table = 'Fellows'
def __str__(self):
return self.display_name # Test.
def has_perm(self, perm, obj=None):
"Does the user have a specific permission?"
# Simplest possible answer: Yes, always
return True
def has_module_perms(self, app_label):
"Does the user have permissions to view the app `app_label`?"
# Simplest possible answer: Yes, always
return True
#property
def is_staff(self):
"""Is the user a member of staff?"""
return self.staff
#property
def is_active(self):
"""Is the user active?"""
return self.active
So far so good, I can connect, do my stuff and even access the admin panel to manage every registered models if I am part of the staff.
However, let us say I want to add permissions between members of the staff, someone I hire for example to manage exclusively the Items table (from app Armory) while the other admin can have a total access to the models from any app.
◢ The armory app will contain the Item model (and it's references).
class Rarity(models.Model):
...
class ItemType(models.Model):
...
class Item(models.Model):
id = models.AutoField(db_column='ID', primary_key=True) # Identifier
name = models.CharField(db_column='Name', unique=True, max_length=64) # Name of the item.
description = models.TextField(db_column='Description', max_length=512, blank=True, null=True) # Description of the item.
source = models.CharField(db_column='Source', max_length=128, blank=True, null=True) # Source icon of the item.
rarity = models.ForeignKey('Rarity', models.CASCADE, db_column='Rarity') # ID of the rarity.
item_type = models.ForeignKey('ItemType', models.CASCADE, db_column='Item_Type') # ID of the item type.
item_value = models.PositiveIntegerField(db_column='Item_Value') # Value of the item.
sell = models.BooleanField(db_column='Sell') # If the item can be sold.
gift = models.BooleanField(db_column='Gift') # If the item can be sent.
dismantle = models.BooleanField(db_column='Dismantle') # If the item can be dismantled.
world = models.BooleanField(db_column='World') # If the item can be found in the world (using the bot's !wheel command).
class Meta:
db_table = 'n_rpg_items'
def __str__(self):
return self.name
◢ And an articles app that will contain the Article model.
from django.conf import settings
from django.db import models
class Article(models.Model):
id = models.AutoField(db_column='ID', primary_key=True) # ID
author = models.ForeignKey(settings.AUTH_USER_MODEL, db_column="ID_User", on_delete=models.CASCADE) # User ID
title = models.CharField(db_column='Title', max_length=32) # Title
content = models.TextField(db_column='Content') # Content
posted = models.DateTimeField(db_column='Posted') # Date Posted
source = models.CharField(db_column='Source', max_length=64, blank=True, null=True) # Source picture url of the article.
class Meta:
managed = False
db_table = 'Articles'
def __str__(self):
return 'Article : ' + self.title
To be more precise, when logging in the admin panel, admin_a will only be able to manage Items, while admin_b will be able to manage everything, Items and Articles.
The problem is, I searched for a while, the doc didn't helped me and I can't find anything that satisfies what I want to achieve so I am probably doing this wrong...
I was thinking about doing my own admin backends by adding a Role in the Fellows table but soon there will be no more use of framework if I start reinventing the wheel... :(
If anybody could share with me which solutions are conceivable, even a start, I would greatly appreciate!

How to creat mutiple UserProfiles that inherit from AbstractUser in Django?

Original Question
I want to create 3 UserProfile for 3 types of users. At first, I made a CharFiled as a mark to differentiate them, but then I realized that I have to put some ForeignKey to associate those users. As for this step, I don't know how to make it come true.
To make it specific:
3 types of users that inherit from AbstractUser, each of them can log into the system
There is a hierarchy among them, much like:
AdminstratorA(not a superuser)
AdminstratorB
|--TeacherA
|--TeacherB
|--StudentA
|--StudentB|
following are my failures(simplified version), Using Django2.1 python3.7
got a problem, because I could only set one AUTH_USER_MODEL = 'users.UserProfile' at mysite\settings.py
apps\users\model
from django.contrib.auth.models import AbstractUser
from django.db import models
class AdministratorUser(AbstractUser):
pass
class TeacherUser(AbstractUser):
administrator = models.ForeignKey(AdministratorUser, on_delete=models.CASCADE)
class StudentUser(AbstractUser):
teacher = models.ForeignKey(TeacherUser, on_delete=models.CASCADE)
I set the main table and other 3 tables as complement. Based on that, I designed my admin site based on xadmin, and the data doesn't represent well. I have no idea about it. So I try to redesign my model, which is the plan I described on the top.
apps\users\model
from django.contrib.auth.models import AbstractUser
from django.db import models
class UserProfile(AbstractUser):
user_type_choices = (
('student', 'student'),
('teacher', 'teacher'),
('teacher', 'teacher'),
)
identity = models.CharField(choices=user_type_choices, max_length=100, default='student')
class AdministratorUser(models.Model):
user_profile = models.OneToOneField(UserProfile, on_delete=models.CASCADE)
class TeacherUser(models.Model):
user_profile = models.OneToOneField(UserProfile, on_delete=models.CASCADE)
administrator = models.ForeignKey(AdministratorUser, on_delete=models.CASCADE)
class StudentUser(models.Model):
user_profile = models.OneToOneField(UserProfile, on_delete=models.CASCADE)
teacher = models.ForeignKey(TeacherUser, on_delete=models.CASCADE)
It really depends what you're trying to achieve, but the simplest approach would be similar to the is_staff and is_superuser fields in the standard User model.
class UserProfile(AbstractUser):
is_type1_user = models.BooleanField(default=False)
is_type2_user = models.BooleanField(default=False)
is_type3_user = models.BooleanField(default=False)
You could make use of Django's generic relations by customising the User model as well as the UserManager in the following way:
First of all you need to import the relevant stuff:
from django.apps import apps
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericRelation
from django.contrib.auth.models import AbstractUser, UserManager as OriginalUserManager
The UserManager:
class UserManager(OriginalUserManager):
def _create_user(self, username, email, password, **extra_fields):
"""
Create and save a user with the given username, email, and password.
"""
if not username:
raise ValueError('The given username must be set')
email = self.normalize_email(email)
username = self.model.normalize_username(username)
user = self.model(username=username, email=email, **extra_fields)
user.set_password(password)
# handle profile creation at user creation
profile_model = User.TYPE_MODELS.get(user.user_type)
profile_model = apps.get_model(app_label='app1', model_name=profile_model)
if profile_model is None:
raise Exception(
"Profile model has not been set in User.TYPE_MODELS for user type {}".format(user.user_type))
profile = profile_model.objects.create()
user.content_type = ContentType.objects.get_for_model(profile_model)
user.object_id = profile.id
user.content_object = profile
user.save(using=self._db)
return user
The User model:
class User(AbstractUser):
TYPE_1 = 0
TYPE_2 = 1
TYPE_CHOICES = (
(TYPE_1, "Type 1"),
(TYPE_2, "Type 2"),
)
TYPE_MODELS = dict((
(TYPE_1, "ProfileType1"),
(TYPE_2, "ProfileType2"),
))
user_type = models.PositiveSmallIntegerField(choices=TYPE_CHOICES, default=TYPE_1)
# Below the mandatory fields for generic relation
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey()
objects = UserManager()
class Meta:
unique_together = ('content_type', 'object_id',)
#property
def profile(self):
return self.content_object
Then you can define your profiles as such (for example):
class BaseProfileModel(models.Model):
_user = GenericRelation(User)
#property
def user(self):
ctype = ContentType.objects.get_for_model(self.__class__)
try:
event = User.objects.get(content_type__pk=ctype.id, object_id=self.id)
except User.DoesNotExist:
return None
return event
class ProfileType1(BaseProfileModel):
x = models.IntegerField(default=0)
class ProfileType2(BaseProfileModel):
y = models.IntegerField(default=0)
Now the way you can use them is in the following way:
Create a user with a default user type:
user = User.objects.create_user("someusername")
user.profile --> will yield a ProfileType1 instance
Create a user with a secific user type
user = User.objects.create_user("someothername", user_type=User.TYPE_2)
user.profile --> will yield a ProfileType2 instance
In both cases if we have in our hands the profile instance we can obtain the user by doing:
profile.user --> will yield our original user instance

Custom Django Usermodel

i just tried to create my own custom Django user model but it fails if i try to create a new user through the frontend:
Request Method: POST Request URL: http://127.0.0.1:8000/signup/ Django
Version: 2.1b1 Exception Type: AttributeError Exception Value:
'Manager' object has no attribute 'get_by_natural_key'
First i created a new Django App "accounts"
then i've added the following to models.py of the accounts app:
from django.db import models
from django.contrib.auth.models import (
BaseUserManager, AbstractBaseUser
)
#User Model Manager
class UserManager(BaseUserManager):
def create_user(self, username, password=None):
"""
Creates and saves a User with the given username and password.
"""
if not username:
raise ValueError('Error: The User you want to create must have an username, try again')
user = self.model(
user=self.normalize_username(username),
)
user.set_password(password)
user.save(using=self._db)
return user
def create_staffuser(self, username, password):
"""
Creates and saves a staff user with the given username and password.
"""
user = self.create_user(
username,
password=password,
)
user.staff = True
user.save(using=self._db)
return user
def create_superuser(self, username, password):
"""
Creates and saves a superuser with the given username and password.
"""
user = self.create_user(
username,
password=password,
)
user.staff = True
user.admin = True
user.save(using=self._db)
return user
class User(AbstractBaseUser):
user = models.CharField(
verbose_name='username',
max_length=30,
unique=True,
)
active = models.BooleanField(default=True)
staff = models.BooleanField(default=False) # a admin user; non super-user
admin = models.BooleanField(default=False) # a superuser
# notice the absence of a "Password field", that's built in.
USERNAME_FIELD = 'user'
REQUIRED_FIELDS = [] # Username & Password are required by default.
def get_full_name(self):
# The user is identified by their Username address
return self.user
def get_short_name(self):
# The user is identified by their Username address
return self.user
def __str__(self): # __unicode__ on Python 2
return self.user
def has_perm(self, perm, obj=None):
"""Does the user have a specific permission?"""
# Simplest possible answer: Yes, always
return True
def has_module_perms(self, app_label):
"""Does the user have permissions to view the app `app_label`?"""
# Simplest possible answer: Yes, always
return True
#property
def is_staff(self):
"""Is the user a member of staff?"""
return self.staff
#property
def is_admin(self):
"""Is the user a admin member?"""
return self.admin
#property
def is_active(self):
"""Is the user active?"""
return self.active
model.py of my actual blog app:
from django.db import models
from django.utils import timezone
from smartfields import fields
from smartfields.dependencies import FileDependency
from smartfields.processors import ImageProcessor
# Categorys of Post Model
class Category(models.Model):
title = models.CharField(max_length=255, verbose_name="Title")
description = models.TextField(max_length=1000, null=True, blank=True)
cover = fields.ImageField(upload_to='categorycovers/', blank=True, null=True, dependencies=[
FileDependency(processor=ImageProcessor(
format='JPEG', scale={'max_width': 350, 'max_height': 350}))
])
icon = fields.ImageField(upload_to='categoryicons/', blank=True, null=True, dependencies=[
FileDependency(processor=ImageProcessor(
format='JPEG', scale={'max_width': 16, 'max_height': 16}))
])
class Meta:
verbose_name = "Category"
verbose_name_plural = "Categories"
ordering = ['title']
def __str__(self):
return self.title
#Post Model
class Post(models.Model):
author = models.ForeignKey('accounts.User', on_delete=models.CASCADE)
title = models.CharField(max_length=75)
content = models.TextField(max_length=10000)
tag = models.CharField(max_length=50, blank=True)
category = models.ForeignKey(Category, verbose_name="Category", on_delete=models.CASCADE, null=True)
postattachment = fields.FileField(upload_to='postattachment/%Y/%m/%d/', blank=True ,null=True)
postcover = fields.ImageField(upload_to='postcover/%Y/%m/%d/', null=True, dependencies=[
FileDependency(processor=ImageProcessor(
format='JPEG', scale={'max_width': 200, 'max_height': 200}))
])
created_date = models.DateField(auto_now_add=True)
published_date = models.DateField(blank=True, null=True)
def publish(self):
self.published_date = timezone.now()
self.save()
class Meta:
ordering = ["-title"]
def __str__(self):
return self.title
#Comment(s) of Post Model
class Comment(models.Model):
author = models.ForeignKey('accounts.User', on_delete=models.CASCADE)
post=models.ForeignKey(Post, on_delete=models.CASCADE)
content = models.TextField()
created_date = models.DateField(default=timezone.now)
published_date = models.DateField(blank=True, null=True)
def publish(self):
self.published_date = timezone.now()
self.save()
def __str__(self):
return self.text
After that i jumpt back to settings.py and added the custom user model to my acctual blog application:
AUTH_USER_MODEL = 'accounts.User'
and i also added
INSTALLED_APPS = [
...
'accounts',
...
]
I dont want any email address for my users. i simply and only want them to be authenticated through the username...
Any hints? Thanks :)
Django AbstractBaseUser class has no field username
in your declaration you declare a username field and named it user
but USERNAME_FIELD is username
change your model like this
class User(AbstractBaseUser):
user = models.CharField(
verbose_name='username',
max_length=30,
unique=True,
)
active = models.BooleanField(default=True)
staff = models.BooleanField(default=False) # a admin user; non super-user
admin = models.BooleanField(default=False) # a superuser
USERNAME_FIELD = 'user'
REQUIRED_FIELDS = [] # Username & Password are required by default.
...
also you can rename user field in User model to username and problem solved.
In error django.core.exceptions.FieldError: Unknown field(s) (username) specified for User, Django complained about unknown field username in your Custom User model, you don't have username field but you stated USERNAME_FIELD = 'username'.
The simple solution is to rename your user field to username.
If you need that name for some reason (user) you should change username to user in get_full_name and get_short_name and don't forget also in create_user (user = self.model(user =self.normalize_username(username),))
Try:
Reaname all created users to some other name (ex. my_user) because you have tow varibales with the same name (the USERNAME_FIELD and the user created)
from django.db import models
from django.contrib.auth.models import (
BaseUserManager, AbstractBaseUser
)
#User Model Manager
class UserManager(BaseUserManager):
def create_user(self, user, password=None):
"""
Creates and saves a User with the given username and password.
"""
if not user:
raise ValueError('Error: The User you want to create must have an username, try again')
my_user = self.model(
user=self.normalize_username(user),
)
my_user.set_password(password)
my_user.save(using=self._db)
return my_user
def create_staffuser(self, user, password):
"""
Creates and saves a staff user with the given username and password.
"""
my_user = self.create_user(
user,
password=password,
)
my_user.staff = True
my_user.save(using=self._db)
return my_user
def create_superuser(self, user, password):
"""
Creates and saves a superuser with the given username and password.
"""
my_user = self.create_user(
user,
password=password,
)
my_user.staff = True
my_user.admin = True
my_user.save(using=self._db)
return my_user
class User(AbstractBaseUser):
user = models.CharField(
verbose_name='username',
max_length=30,
unique=True,
)
active = models.BooleanField(default=True)
staff = models.BooleanField(default=False) # a admin user; non super-user
admin = models.BooleanField(default=False) # a superuser
# notice the absence of a "Password field", that's built in.
USERNAME_FIELD = 'user'
REQUIRED_FIELDS = [] # Username & Password are required by default.
def get_full_name(self):
# The user is identified by their Username address
return self.user
def get_short_name(self):
# The user is identified by their Username address
return self.user
def __str__(self): # __unicode__ on Python 2
return self.user
def has_perm(self, perm, obj=None):
"""Does the user have a specific permission?"""
# Simplest possible answer: Yes, always
return True
def has_module_perms(self, app_label):
"""Does the user have permissions to view the app `app_label`?"""
# Simplest possible answer: Yes, always
return True
#property
def is_staff(self):
"""Is the user a member of staff?"""
return self.staff
#property
def is_admin(self):
"""Is the user a admin member?"""
return self.admin
#property
def is_active(self):
"""Is the user active?"""
return self.active
Your settings.py file looks great.
I hope this will help.

Django 1.11 Custom User-model with Groups

I am trying to add a ForeignKey between my User(AbstractBaseUser)-model and the built in Group-model. My issue now is that I cannot create a superuser, as it requires to fill the group field with 'something'.
I have created a group through the shell, called admin with id 1. However, I can't find a way to create my superuser, and set the group to admin on creation ..
Here is models.py in my /accounts app:
from django.db import models
from django.forms import ModelForm
from django.contrib.auth.models import (
BaseUserManager,
AbstractBaseUser,
Group
)
class UserManager(BaseUserManager):
def create_user(self, email, group, password=None):
if not email:
raise ValueError('Users must have an email address')
user = self.model(
email = UserManager.normalize_email(email),
password = password,
group = group
)
user.set_password(password)
user.save()
return user
def create_superuser(self, email, group, password):
user = self.create_user(
email = UserManager.normalize_email(email),
group = group
)
user.is_admin = True
user.is_staff = True
user.is_superuser = True
user.save()
return user
class User(AbstractBaseUser):
objects = UserManager()
date_added = models.DateField(auto_now=False, auto_now_add=True)
email = models.EmailField(unique=True, db_index=True)
group = models.ForeignKey(Group)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['group']
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
def __str__(self):
return self.email
def get_full_name(self):
return self.email
def get_short_name(self):
return self.email
def has_perm(self, perm, obj=None):
return True
def has_perms(self, perm, obj=None):
return True
def has_module_perms(self, app_label):
return True
def is_staff(self):
return self.is_admin
Whenever I run migrate.py createsuperuser, it asks for email, password and Group (Group ID).
If I type admin, it gives this error:
ValueError: invalid literal for int() with base 10: 'admin'
if I type 1 (the id), it gives this error:
ValueError: Cannot assign "'1'": "User.group" must be a "Group" instance.
Meet the same problem.
Actually, group is PermissionsMixin's attribution, so what you need to do is implement PermissionsMixin and AbstractBaseUser
class User(AbstractBaseUser, PermissionsMixin):
You could change
group = group
to
group = Group.objects.get(id=group)
Within your create_superuser def.
Then you can just use the group id (which is 1 in your case) which the superuser wizard expects.
In case you'll end up working with multiple instances, I would look into creating that group in a migration instead of through the shell (so it will automatically be there when you set up a new instance and run migrations).

Categories