Related
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()
Im Created 2 Models.
Account
UserProfil
First Of All, User Register email, fullname, password1, password2. The data Sending To Database in table Account.
Second, User Will Login, if success, he will go to dashboard. in dashboard have a profil Form.
In The Profil Form, He Will input data profil, likes number phone, birth date. etc. and will store in table UserProfil
All of data in UserProfil relationship with Account.
Im Try to create 'Profil Form'. Like This.
my Question is How To Put the data Full_Name in this form ?
i got Error Cannot resolve keyword 'user' into field. Choices are: create_account, email, full_name ...
authentication/models.py
class Account(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_('email address'), unique=True)
full_name = models.CharField(max_length=150)
create_account = models.DateTimeField(default=timezone.now)
is_active = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
is_reviewer = models.BooleanField(default=False)
is_admin = models.BooleanField(default=False)
objects = CustomAccountManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['full_name']
def __str__(self):
return self.full_name
dashboard/models.py
class UserProfil(models.Model):
jenis_kelamin_choice = (
('Pria', 'Pria'),
('Wanita', 'Wanita' ),
)
user = models.OneToOneField(settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,)
nik = models.CharField(max_length=11, null=True, unique=True)
nidn = models.CharField(max_length=11, null=True, unique=True)
def __str__(self):
return str(self.user)
dashboard/views.py
class UserProfilFormView(CreateView):
template_name = 'dashboard/profil.html'
form_class = UserProfilForm
def form_valid(self, form):
userPofil = form.save(commit=False)
userPofil.user = Account.objects.get(user__full_name=self.request.user)
userPofil.save()
messages.success(self.request, 'Data Profil Berhasil Disimpan.')
print(self.request.user)
return super().form_valid(form)
File Traceback :
Internal Server Error: /dashboard/profil
Traceback (most recent call last):
File "C:\Users\USER\AppData\Local\Programs\Python\Python310\lib\site-
packages\django\core\handlers\exception.py", line 47, in inner
response = get_response(request)
File "C:\Users\USER\AppData\Local\Programs\Python\Python310\lib\site-
packages\django\core\handlers\base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\USER\AppData\Local\Programs\Python\Python310\lib\site-
packages\django\views\generic\base.py", line 70, in view
return self.dispatch(request, *args, **kwargs)
File "C:\Users\USER\AppData\Local\Programs\Python\Python310\lib\site-
packages\django\views\generic\base.py", line 98, in dispatch
return handler(request, *args, **kwargs)
File "C:\Users\USER\AppData\Local\Programs\Python\Python310\lib\site-
packages\django\views\generic\edit.py", line 172, in post
return super().post(request, *args, **kwargs)
File "C:\Users\USER\AppData\Local\Programs\Python\Python310\lib\site-
packages\django\views\generic\edit.py", line 142, in post
return self.form_valid(form)
File "D:\Project\hibahinternal\dashboard\views.py", line 26, in
form_valid
userPofil.user = Account.objects.get(user__full_name=self.request.user)
File "C:\Users\USER\AppData\Local\Programs\Python\Python310\lib\site-
packages\django\db\models\manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "C:\Users\USER\AppData\Local\Programs\Python\Python310\lib\site-
packages\django\db\models\query.py", line 424, in get
clone = self._chain() if self.query.combinator else self.filter(*args,
**kwargs)
File "C:\Users\USER\AppData\Local\Programs\Python\Python310\lib\site-
packages\django\db\models\query.py", line 941, in filter
return self._filter_or_exclude(False, args, kwargs)
File "C:\Users\USER\AppData\Local\Programs\Python\Python310\lib\site-
packages\django\db\models\query.py", line 961, in _filter_or_exclude
clone._filter_or_exclude_inplace(negate, args, kwargs)
File "C:\Users\USER\AppData\Local\Programs\Python\Python310\lib\site-
packages\django\db\models\query.py", line 968, in
_filter_or_exclude_inplace
self._query.add_q(Q(*args, **kwargs))
File "C:\Users\USER\AppData\Local\Programs\Python\Python310\lib\site-
packages\django\db\models\sql\query.py", line 1393, in add_q
clause, _ = self._add_q(q_object, self.used_aliases)
File "C:\Users\USER\AppData\Local\Programs\Python\Python310\lib\site-
packages\django\db\models\sql\query.py", line 1412, in _add_q
child_clause, needed_inner = self.build_filter(
File "C:\Users\USER\AppData\Local\Programs\Python\Python310\lib\site-
packages\django\db\models\sql\query.py", line 1286, in build_filter
lookups, parts, reffed_expression = self.solve_lookup_type(arg)
File "C:\Users\USER\AppData\Local\Programs\Python\Python310\lib\site-
packages\django\db\models\sql\query.py", line 1112, in solve_lookup_type
_, field, _, lookup_parts = self.names_to_path(lookup_splitted,
self.get_meta())
File "C:\Users\USER\AppData\Local\Programs\Python\Python310\lib\site-
packages\django\db\models\sql\query.py", line 1539, in names_to_path
raise FieldError("Cannot resolve keyword '%s' into field. "
django.core.exceptions.FieldError: Cannot resolve keyword 'user' into
field. Choices are: create_account, email, full_name, groups, id,
is_active, is_admin, is_reviewer, is_staff, is_superuser, last_login,
logentry, password, user_permissions, userprofil
[20/Dec/2021 19:31:48] "POST /dashboard/profil HTTP/1.1" 500 136397
Thanks
Your Account has no user field, this also would not make much sense, since that is the user account. You do not need to make a query to the Account model anyway: request.user works with the user model, here account, so you can use request.user directly:
from django.contrib.auth.mixins import LoginRequiredMixin
class UserProfilFormView(LoginRequiredMixin, CreateView):
template_name = 'dashboard/profil.html'
form_class = UserProfilForm
def form_valid(self, form):
form.instance.user = request.user
messages.success(self.request, 'Data Profil Berhasil Disimpan.')
print(self.request.user)
return super().form_valid(form)
Note: You can limit views to a class-based view to authenticated users with the
LoginRequiredMixin mixin [Django-doc].
I have created a UserProfile model with OneToOne relationship with User model.
The UserProfile model is shown below.
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
mobile_number = models.IntegerField(blank=True, unique=True, null=True)
profile_image = models.ImageField(upload_to="media", blank=True )
current_location= models.CharField(max_length=300, unique=False, blank=True)
created_at = models.DateTimeField("created at", auto_now_add=True)
university = models.CharField(max_length=100, blank=True)
def __str__(self):
return self.user.username
def create_profile(sender, **kwargs):
if kwargs['created']:
user_profile = UserProfile.objects.create(user=kwargs['instance'])
post_save.connect(create_profile, sender=User)
The serializer class is shown below.
from rest_framework import serializers
from .models import UserProfile
class UserProfileSerializer(serializers.ModelSerializer):
class Meta:
model = UserProfile
fields = ( 'mobile_number',
'current_location'
,'university','profile_image')
Iam using token authentication. How can I use the ListCreateViewand other classes to implement the post, put ,get and delete method in the best way possible. I also need to validate these data before saving(like mobile_number length should be 10 and mandatory)
I tried to build a view as shown below.
from .models import UserProfile
from .serializers import UserProfileSerializer
class UserProfileView(ListCreateAPIView):
queryset = UserProfile.objects.all()
print(queryset)
serializer_class = UserProfileSerializer
def get_queryset(self):
return UserProfile.objects.filter(user=self.request.user)
def perform_create(self, serializer):
profile = get_object_or_404(UserProfile, user=self.request.user)
print(str(self.request.user.id)+"..."+str(profile))
return serializer.save(userprofile=profile)
But it gives me error:
Got a `TypeError` when calling `UserProfile.objects.create()`. This may be because you have a writable field on the serializer class that is not a valid argument to `UserProfile.objects.create()`. You may need to make the field read-only, or override the UserProfileSerializer.create() method to handle this correctly.
how can I solve the problem.
The stack trace is shown below
Internal Server Error: /users/userprofile
Traceback (most recent call last):
File "/home/vishnu/.local/lib/python3.6/site-packages/rest_framework/serializers.py", line 932, in create
instance = ModelClass._default_manager.create(**validated_data)
File "/home/vishnu/.local/lib/python3.6/site-packages/django/db/models/manager.py", line 82, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/home/vishnu/.local/lib/python3.6/site-packages/django/db/models/query.py", line 420, in create
obj = self.model(**kwargs)
File "/home/vishnu/.local/lib/python3.6/site-packages/django/db/models/base.py", line 501, in __init__
raise TypeError("%s() got an unexpected keyword argument '%s'" % (cls.__name__, kwarg))
TypeError: UserProfile() got an unexpected keyword argument 'userprofile'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/vishnu/.local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "/home/vishnu/.local/lib/python3.6/site-packages/django/core/handlers/base.py", line 115, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/home/vishnu/.local/lib/python3.6/site-packages/django/core/handlers/base.py", line 113, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/vishnu/.local/lib/python3.6/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "/home/vishnu/.local/lib/python3.6/site-packages/django/views/generic/base.py", line 71, in view
return self.dispatch(request, *args, **kwargs)
File "/home/vishnu/.local/lib/python3.6/site-packages/rest_framework/views.py", line 505, in dispatch
response = self.handle_exception(exc)
File "/home/vishnu/.local/lib/python3.6/site-packages/rest_framework/views.py", line 465, in handle_exception
self.raise_uncaught_exception(exc)
File "/home/vishnu/.local/lib/python3.6/site-packages/rest_framework/views.py", line 476, in raise_uncaught_exception
raise exc
File "/home/vishnu/.local/lib/python3.6/site-packages/rest_framework/views.py", line 502, in dispatch
response = handler(request, *args, **kwargs)
File "/home/vishnu/.local/lib/python3.6/site-packages/rest_framework/generics.py", line 242, in post
return self.create(request, *args, **kwargs)
File "/home/vishnu/.local/lib/python3.6/site-packages/rest_framework/mixins.py", line 19, in create
self.perform_create(serializer)
File "/home/vishnu/git_repos/Agora42core/users/views.py", line 23, in perform_create
return serializer.save(userprofile=profile)
File "/home/vishnu/.local/lib/python3.6/site-packages/rest_framework/serializers.py", line 213, in save
self.instance = self.create(validated_data)
File "/home/vishnu/.local/lib/python3.6/site-packages/rest_framework/serializers.py", line 951, in create
raise TypeError(msg)
TypeError: Got a `TypeError` when calling `UserProfile.objects.create()`. This may be because you have a writable field on the serializer class that is not a valid argument to `UserProfile.objects.create()`. You may need to make the field read-only, or override the UserProfileSerializer.create() method to handle this correctly.
Original exception was:
Traceback (most recent call last):
File "/home/vishnu/.local/lib/python3.6/site-packages/rest_framework/serializers.py", line 932, in create
instance = ModelClass._default_manager.create(**validated_data)
File "/home/vishnu/.local/lib/python3.6/site-packages/django/db/models/manager.py", line 82, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/home/vishnu/.local/lib/python3.6/site-packages/django/db/models/query.py", line 420, in create
obj = self.model(**kwargs)
File "/home/vishnu/.local/lib/python3.6/site-packages/django/db/models/base.py", line 501, in __init__
raise TypeError("%s() got an unexpected keyword argument '%s'" % (cls.__name__, kwarg))
TypeError: UserProfile() got an unexpected keyword argument 'userprofile'
If you're really creating a new UserProfile object, your perform_create() method should just pass the user into the serialiser's save() method:
def perform_create(self, serializer):
return serializer.save(user=self.request.user)
But if you already have a UserProfile, which looks like it's what your expecting since you're using get_object_or_404, then you should use a UpdateAPIView instead of a ListCreateAPIView:
class UserProfileView(UpdateAPIView):
serializer_class = UserProfileSerializer
permission_classes = [IsAuthenticated]
def get_queryset(self):
return UserProfile.objects.filter(user=self.request.user)
For PUT, PATCH, you need to define(override) create and update
Validation can be done at two levels. Both are shown below:
At Serializer level,
it is just validate_field_variable_name
class UserProfileSerializer(serializers.ModelSerializer):
class Meta:
model = UserProfile
fields = ( 'mobile_number',
'current_location'
,'university','profile_image')
#For POST
def create(self, validated_data):
<your code,>
#for PATCH
def update(self, instance, validated_data):
<your code,>
#Validation
def validate_mobile_number(self, cell_number):
#Validate code here
More:
https://www.django-rest-framework.org/api-guide/validators/
Validation at Model level:
You can also do this kind of validation at model level, like length of string etc.
Particular to mobile number, there are other modules which can do this unless you want special cases to handle.
from django.db import models
from phone_field import PhoneField
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
mobile_number = PhoneField(blank=True, unique=True, null=True)
https://pypi.org/project/django-phone-field/
Trying to set up custom user model on the start of django project, but i am facing a recurrent problem that i have only been able to patch, that now is affecting the changepassword of admin interface. On change password form submit, it crashes with error:
AttributeError at /admin/custom_users/customuser/7/password/
'NoneType' object has no attribute 'strip'
Environment:
Request Method: POST
Request URL: http://127.0.0.1:8000/admin/custom_users/customuser/7/password/
Django Version: 2.2
Python Version: 3.7.3
Installed Applications:
['django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'cashflow.apps.CashflowConfig',
'custom_users.apps.CustomUsersConfig']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']
Traceback:
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/mysql/connector/connection_cext.py" in cmd_query
395. raw_as_string=raw_as_string)
During handling of the above exception (Column 'is_superuser' cannot be null), another exception occurred:
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/mysql/connector/django/base.py" in _execute_wrapper
168. return method(query, args)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/mysql/connector/cursor_cext.py" in execute
266. raw_as_string=self._raw_as_string)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/mysql/connector/connection_cext.py" in cmd_query
398. sqlstate=exc.sqlstate)
During handling of the above exception (1048 (23000): Column 'is_superuser' cannot be null), another exception occurred:
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/db/backends/utils.py" in execute
99. return super().execute(sql, params)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/db/backends/utils.py" in execute
67. return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/db/backends/utils.py" in _execute_with_wrappers
76. return executor(sql, params, many, context)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/db/backends/utils.py" in _execute
84. return self.cursor.execute(sql, params)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/mysql/connector/django/base.py" in execute
218. return self._execute_wrapper(self.cursor.execute, query, new_args)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/mysql/connector/django/base.py" in _execute_wrapper
174. utils.IntegrityError(err.msg), sys.exc_info()[2])
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/utils/six.py" in reraise
683. raise value.with_traceback(tb)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/mysql/connector/django/base.py" in _execute_wrapper
168. return method(query, args)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/mysql/connector/cursor_cext.py" in execute
266. raw_as_string=self._raw_as_string)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/mysql/connector/connection_cext.py" in cmd_query
398. sqlstate=exc.sqlstate)
During handling of the above exception (Column 'is_superuser' cannot be null), another exception occurred:
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/mysql/connector/cursor_cext.py" in statement
606. return self._executed.strip().decode('utf8')
During handling of the above exception ('NoneType' object has no attribute 'strip'), another exception occurred:
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/core/handlers/exception.py" in inner
34. response = get_response(request)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/core/handlers/base.py" in _get_response
115. response = self.process_exception_by_middleware(e, request)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/core/handlers/base.py" in _get_response
113. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/utils/decorators.py" in _wrapped_view
142. response = view_func(request, *args, **kwargs)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/views/decorators/cache.py" in _wrapped_view_func
44. response = view_func(request, *args, **kwargs)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/contrib/admin/sites.py" in inner
223. return view(request, *args, **kwargs)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/utils/decorators.py" in _wrapper
45. return bound_method(*args, **kwargs)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/views/decorators/debug.py" in sensitive_post_parameters_wrapper
76. return view(request, *args, **kwargs)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/contrib/auth/admin.py" in user_change_password
141. form.save()
File "/home/mh/devel/dreamit_control/dcontrol/custom_users/forms.py" in save
32. self.user.save()
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/contrib/auth/base_user.py" in save
66. super().save(*args, **kwargs)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/db/models/base.py" in save
741. force_update=force_update, update_fields=update_fields)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/db/models/base.py" in save_base
779. force_update, using, update_fields,
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/db/models/base.py" in _save_table
851. forced_update)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/db/models/base.py" in _do_update
900. return filtered._update(values) > 0
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/db/models/query.py" in _update
760. return query.get_compiler(self.db).execute_sql(CURSOR)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/db/models/sql/compiler.py" in execute_sql
1426. cursor = super().execute_sql(result_type)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/db/models/sql/compiler.py" in execute_sql
1097. cursor.execute(sql, params)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/db/backends/utils.py" in execute
103. sql = self.db.ops.last_executed_query(self.cursor, sql, params)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/mysql/connector/django/operations.py" in last_executed_query
127. return force_text(cursor.statement, errors='replace')
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/mysql/connector/django/base.py" in __getattr__
230. return getattr(self.cursor, attr)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/mysql/connector/cursor_cext.py" in statement
608. return self._executed.strip()
Exception Type: AttributeError at /admin/custom_users/customuser/7/password/
Exception Value: 'NoneType' object has no attribute 'strip'
on stack trace, i can see that the problem is that is_staff=NULL and is_superuser=NULL on the attempted query.
I dont know why django passes this parameters as null on passwordchange since they are set to false on model and nowhere are they as fields on the CustomUserPassForm. Had this same issue on user change form, but after adding fieldsets to CustomUserAdmin(UserAdmin) class, i was able to edit a user. (as the is_superuser and is_staff input checkboxes appeared on form in html)
models.py
class CustomUserManager(BaseUserManager):
def create_user(self, email, password, **extra_fields):
if not email:
raise ValueError('correo es obligatorio')
email = self.normalize_email(email)
extra_fields.setdefault('is_superuser', False)
extra_fields.setdefault('is_staff', False)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save()
return user
def create_superuser(self, email, password, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
extra_fields.setdefault('is_active', True)
if extra_fields.get('is_staff') is not True:
raise ValueError('superuser must have is_staff=True')
if extra_fields.get('is_superuser') is not True:
raise ValueError('superuser musthave is_superuser=True')
return self.create_user(email, password, **extra_fields)
class CustomUser(AbstractUser, PermissionsMixin):
cargo = models.TextField(max_length=50, null=True)
rut = models.IntegerField(null=True)
DIGITO_VERIFICADOR_CHOICES = (
('1','1'),
('2','2'),
('3','3'),
('4','4'),
('5','5'),
('6','6'),
('7','7'),
('8','8'),
('9','9'),
('0','0'),
('K','K')
)
digito_verificador = models.CharField(max_length=1, choices=DIGITO_VERIFICADOR_CHOICES, null=True)
nombre = models.CharField(max_length=25, default="john")
apellido = models.CharField(max_length=25, default="doe")
email = models.EmailField(verbose_name='correo', max_length=255, unique=True)
username = models.TextField(max_length=255, null=True)
is_superuser = models.BooleanField(default=False, blank=True)
is_staff = models.BooleanField(default=False, blank=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = CustomUserManager()
forms.py
class CustomUserCreationForm(UserCreationForm):
class Meta(UserCreationForm):
model = get_user_model()
fields = ['email', 'rut', 'digito_verificador',]
class CustomUserChangeForm(UserChangeForm):
rut = forms.IntegerField(min_value=1000000)
#is_superUser = forms.BooleanField()
class Meta:
model = get_user_model()
fields = ['rut', 'digito_verificador',]
#['email', 'is_superuser','is_staff' ]
class CustomUserPassForm(AdminPasswordChangeForm):
# is_staff = forms.BooleanField(initial=False)
# is_superuser = forms.BooleanField(initial=False)
#fields = ['is_staff','is_superuser']
def save(self, commit=True):
password = self.cleaned_data["password1"]
self.user.set_password(password)
print(self.user)
if commit:
self.user.save()
return self.user
admin.py
class CustomUserAdmin(UserAdmin):
add_form = CustomUserCreationForm
form = CustomUserChangeForm
change_password_form = CustomUserPassForm
model = get_user_model()
list_display = ['email', ]
fieldsets = (
(None, {'fields': ('email', 'password')}),
('personal info',{'fields': ('nombre', 'apellido',('rut','digito_verificador'))}),
('permissions', {'fields':('is_superuser', 'is_staff')})
)
add_fieldsets = (
(None, {
'classes':('wide',),
'fields':('email', 'password1', 'password2'),
}
),
)
admin.site.register(CustomUser, CustomUserAdmin)
Have been two days reading tutorials and documentation, including official django guide, all which leave out any information about implementation of change_password_form.
The problem was the save method of the CustomUserPassForm. For some reason (i havent done the complete followup) the user attribute had is_staff and is_superuser set to NULL. forcing these to false patched the problem.
class CustomUserPassForm(AdminPasswordChangeForm):
def save(self, commit=True):
password = self.cleaned_data["password1"]
self.user.set_password(password)
self.user.is_staff = False
self.user.is_superuser = False
if commit:
self.user.save()
return self.user
Now if anyone can shed some light as to why, i'd be appreciated (also, how to set the is_staff and is_superuser to the same value that is actually held in db.)
I am getting the error below. I think that for some reason my UserMixin import does not include the has_role property that #role_required requires. Do I need to use RoleMixin. Can anyone help?
Traceback (most recent call last):
File "/Users/henry.arnold/anaconda/lib/python3.5/site-packages/flask/app.py", line 1820, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "/Users/henry.arnold/anaconda/lib/python3.5/site-packages/flask/app.py", line 1403, in handle_exception
reraise(exc_type, exc_value, tb)
File "/Users/henry.arnold/anaconda/lib/python3.5/site-packages/flask/_compat.py", line 33, in reraise
raise value
File "/Users/henry.arnold/anaconda/lib/python3.5/site-packages/flask/app.py", line 1817, in wsgi_app
response = self.full_dispatch_request()
File "/Users/henry.arnold/anaconda/lib/python3.5/site-packages/flask/app.py", line 1477, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/Users/henry.arnold/anaconda/lib/python3.5/site-packages/flask/app.py", line 1381, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/Users/henry.arnold/anaconda/lib/python3.5/site-packages/flask/_compat.py", line 33, in reraise
raise value
File "/Users/henry.arnold/anaconda/lib/python3.5/site-packages/flask/app.py", line 1475, in full_dispatch_request
rv = self.dispatch_request()
File "/Users/henry.arnold/anaconda/lib/python3.5/site-packages/flask_debugtoolbar/__init__.py", line 125, in dispatch_request
return view_func(**req.view_args)
File "/Users/henry.arnold/anaconda/lib/python3.5/site-packages/flask_login.py", line 792, in decorated_view
return func(*args, **kwargs)
File "/Users/henry.arnold/anaconda/lib/python3.5/site-packages/flask_user/decorators.py", line 69, in decorated_view
if not current_user.has_roles(*role_names):
File "/Users/henry.arnold/anaconda/lib/python3.5/site-packages/werkzeug/local.py", line 338, in __getattr__
return getattr(self._get_current_object(), name)
AttributeError: 'User' object has no attribute 'has_roles'
My model
import datetime as dt
from flask_login import UserMixin
from flaskapp.database import Column, Model, SurrogatePK, db
from flaskapp.teams.models import Teams
class User(UserMixin, SurrogatePK, Model):
"""A user of the app."""
__tablename__ = 'users'
user_id = Column(db.BigInteger, unique=True, nullable=False)
first_name = Column(db.String(30), nullable=True)
last_name = Column(db.String(80), nullable=True)
email = Column(db.String(80), unique=True, nullable=False)
isaf_id = Column(db.String(10), nullable=True)
primary_team_id = Column(db.Integer, db.ForeignKey(Teams.id), nullable=True)
primary_team = db.relationship('Teams', foreign_keys='User.primary_team_id')
is_admin = Column(db.Boolean(), default=False)
created_at = Column(db.DateTime, nullable=False, default=dt.datetime.utcnow)
roles = db.relationship('Role', secondary='user_roles',
backref=db.backref('users', lazy='dynamic'))
def __init__(self, user_id=user_id, first_name=first_name, last_name=last_name, email=email, is_admin=is_admin, **kwargs):
"""if int(user_id) in current_app.config['ADMINS']:
self.is_admin = True
else:
self.is_admin = False"""
db.Model.__init__(self, user_id=user_id, first_name=first_name, last_name=last_name, email=email, is_admin=is_admin, **kwargs)
"""Create instance."""
#property
def full_name(self):
"""Full user name."""
return '{0} {1}'.format(self.first_name, self.last_name)
def __repr__(self):
"""Represent instance as a unique string."""
return '{0} {1}'.format(self.first_name, self.last_name)
# Define Role model
class Role(db.Model):
role_id = db.Column(db.Integer(), primary_key=True)
name = db.Column(db.String(50), unique=True)
# Define UserRoles model
class UserRoles(db.Model):
id = db.Column(db.Integer(), primary_key=True)
user_id = db.Column(db.Integer(), db.ForeignKey('users.user_id', ondelete='CASCADE'))
role_id = db.Column(db.Integer(), db.ForeignKey('role.role_id', ondelete='CASCADE'))
to create the user I do the following
#blueprint.route('/callback/<provider>')
def oauth_callback(provider):
if not current_user.is_anonymous:
return redirect(url_for('public.home'))
oauth = OAuthSignIn.get_provider(provider)
user_id, first_name, last_name, email, is_admin = oauth.callback()
if user_id is None:
flash('Authentication failed.')
return redirect(url_for('public.home'))
user = User.query.filter_by(user_id=user_id).first()
if not user:
User.create(user_id=user_id, first_name=first_name, last_name=last_name, email=email, is_admin = is_admin)
user = User.query.filter_by(user_id=user_id).first()
if is_admin:
print('is admin')
admin = Role.query.filter(Role.name == 'admin').first()
user.roles.append(admin)
User.query.filter_by(user_id=user_id).update({'is_admin': True})
else:
print('is not admin')
User.query.filter_by(user_id=user_id).update({'is_admin': False})
login_user(user, True)
db.session.commit()
return redirect(url_for('public.home'))
I think check the user is an admin
from flask import Blueprint, flash, redirect, render_template, request, url_for
from flask_login import current_user, login_required
from flask_user import roles_required
from flaskapp.events.forms import CreateEventForm
from flaskapp.events.models import Events
from flaskapp.database import db
from datetime import date
from collections import OrderedDict
#blueprint.route('/add_event', methods=['POST', 'GET'])
#login_required
#roles_required('admin')
def add_event():
UserMixin class from flask_login does not provide has_roles attribute (source). You can provide it by yourself in your User class:
class User(UserMixin, SurrogatePK, Model):
# ... Everything that you've written so far
def has_roles(self, *args):
return set(args).issubset({role.name for role in self.roles})
Also, you can use UserMixin class not from flask_login module, but from flask_user module (yes, there is a confusion in names). The latter class indeed does provide has_roles method. In this case all you need to do is change this line
from flask_login import UserMixin
to this:
from flask_user import UserMixin