I am new in Django.
I have a problem with authenticate(). It only authenticates the superuser.
For any other user it returns None.
I use "user_id" field instead of "username" field.
I don't want to use Django forms.
this is my models.py.
models.py
class UserProfileManager(BaseUserManager):
def create_user(self, user_id, first_name, last_name, user_class, password = None):
user = self.model(first_name = first_name, last_name = last_name , user_id = user_id, user_class = user_class)
user.set_password(password)
user.save(using = self._db)
return user
def create_superuser(self, user_id, first_name, last_name , password = None):
user = self.create_user(user_id, first_name, last_name, None, password = password)
user.is_superuser = True
user.is_staff = True
user.save(using = self._db)
return user
class UserProfile(AbstractBaseUser, PermissionsMixin):
first_name = models.CharField(max_length = 255)
last_name = models.CharField(max_length = 255)
user_id = models.IntegerField(unique = True, null = True)
user_class = models.ForeignKey(Class, on_delete = models.PROTECT, default = None, unique = False, null = True)
is_active = models.BooleanField(default = True)
is_staff = models.BooleanField( default = False)
objects = UserProfileManager()
USERNAME_FIELD = 'user_id'
# REQUIRED_FIELDS = ['first_name', 'last_name']
def get_short_name(self):
return self.first_name
def get_full_name(self):
return '{} {}'.format(self.first_name, self.last_name)
def __str__(self):
return '{} {}'.format(self.first_name, self.last_name)
this is my views.py.
views.py
class HomeView(TemplateView):
template_name = 'user_profile/home.html'
def post(self, request, *args, **kwargs):
if request.method == 'POST':
user_id = request.POST.get('user_id')
password = request.POST.get('password')
print('id :', user_id, '\npassword : ',password)
user = authenticate(user_id = user_id , password = password)
print(user)
if user is not None :
if user.is_active:
login(request,user)
return redirect('user_profile:home')
else:
return render(request, 'user_profile/not_active.html')
else:
return render(request, 'user_profile/not_valid.html')
else:
return render(request, 'user_profile/home.html')
because the users are not active. And username_field puts the email or username or another unique field except id
Related
i keep getting this error when i try to register for the second time i have tried multiple possible solutions but i keep getting it anyway any help ?
IntegrityError at /registration/transporteur
this is my code:
here i try to have multi type users
models.py
class CustomUser(AbstractBaseUser, PermissionsMixin):
username = models.CharField(max_length= 15, )
first_name = models.CharField(max_length= 15)
last_name = models.CharField(max_length= 15)
email = models.EmailField(_('email address'),unique= True,)
phone_number = models.CharField(max_length= 15)
address = models.CharField(verbose_name = "Address", max_length= 50, null = True, blank= True)
# profile_picture = models.ImageField(null = True)
# longitude = models.CharField(verbose_name = "Longitude", max_length= 100, null = True, blank= True)
# lagitude = models.CharField(verbose_name = "Lagitude", max_length= 100, null = True, blank= True)
date_joined = models.DateTimeField(auto_now_add=True)
last_login = models.DateTimeField(auto_now=True)
is_transporteur = models.BooleanField(default= False)
is_client = models.BooleanField(default= False)
is_staff = models.BooleanField(default= False)
is_superuser = models.BooleanField(default= False)
is_active = models.BooleanField(default= False)
USERNAME_FIELD = "email"
REQUIRED_FIELDS = ["first_name", "last_name", "username", "phone_number", "address"]
objects = CustomUserManager()
def __str__(self):
return self.username
def has_perm(self, perm: str, obj: None):
return self.is_admin
def has_module_perms(self, app_label):
return True
class Trasporteur(CustomUser):
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE, related_name="trasporteur_account")
matricule = models.CharField(max_length = 20, blank=True, null=True)
car_type = models.CharField(max_length = 20, choices = CAR_tYPES)
rating = models.IntegerField(blank=True, null = True)
current_location = models.CharField(max_length = 20, blank=True, null=True)
is_on_travail = models.BooleanField(default=False)
bio = models.TextField()
# last_transports = models.ManyToManyField('transport_services.TrasportService', on_delete=models.CASCADE, related_name="trasporteur_transports")
def __str__(self):
return self.user.username
class Client(CustomUser):
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE, related_name="client_account")
current_location = models.CharField(max_length = 20, blank=True, null=True)
# last_transports = models.ManyToManyField('transport_services.TrasportService', on_delete=models.CASCADE, related_name="client_transports")
def __str__(self):
return self.user.username
managers.py
class CustomUserManager(BaseUserManager):
def create_user(self, username, email, password, **extra_fields):
if not username:
raise ValueError(_('The username must be set'))
if not email:
raise ValueError(_('The Email must be set'))
username = username
email = self.normalize_email(email)
user = self.model(username = username, email = email, **extra_fields)
user.set_password(password)
user.save()
return user
def create_superuser(self, username, email, password, **extra_fields):
"""
Create and save a SuperUser with the given email and password.
"""
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 must have is_superuser=True.'))
return self.create_user(username, email, password, **extra_fields)
serializers.py
there is a separate registration and retrieve serializers for each class and the custom user one is just for test it is also the main one
class CustomUserSerializer(serializers.ModelSerializer):
class Meta:
model = CustomUser
fields = '__all__'
class TransporteurSerializer(serializers.ModelSerializer):
user = serializers.CharField(read_only=True,)
class Meta:
model = Trasporteur
fields = '__all__'
class ClientSerializer(serializers.ModelSerializer):
user = serializers.CharField(read_only=True,)
class Meta:
model = Client
fields = '__all__'
class TransporteurCustomRegistrationSerializer(RegisterSerializer):
user = serializers.PrimaryKeyRelatedField(read_only=True,)
first_name = serializers.CharField(required=True)
last_name = serializers.CharField(required=True)
phone_number = serializers.CharField(required=True)
address = serializers.CharField(required=True)
matricule = serializers.CharField(required=True)
car_type = serializers.ChoiceField(choices= CAR_tYPES)
def get_cleaned_data(self):
data = super(TransporteurCustomRegistrationSerializer, self).get_cleaned_data()
extra_data = {
'first_name' : self.validated_data.get('first_name', ''),
'last_name' : self.validated_data.get('last_name', ''),
'phone_number' : self.validated_data.get('phone_number', ''),
'address' : self.validated_data.get('address', ''),
'matricule' : self.validated_data.get('matricule', ''),
'car_type' : self.validated_data.get('car_type', ''),
}
data.update(extra_data)
return data
def save(self, request):
user = super(TransporteurCustomRegistrationSerializer, self).save(request)
user.is_transporteur = True
user.username = self.data.get('username')
user.email = self.data.get('email')
user.first_name = self.data.get('first_name')
user.last_name = self.data.get('last_name')
user.phone_number = self.data.get('phone_number')
user.address = self.data.get('address')
user.matricule = self.data.get('matricule')
user.car_type = self.data.get('car_type')
user.save()
transporteur = Trasporteur(
user=user,
email=self.cleaned_data.get('email'),
first_name=self.cleaned_data.get('first_name'),
last_name=self.cleaned_data.get('last_name'),
phone_number = self.cleaned_data.get('phone_number'),
address = self.cleaned_data.get('address'),
matricule=self.cleaned_data.get('matricule'),
car_type=self.cleaned_data.get('car_type'),
)
transporteur.save()
return user
class ClientCustomRegistrationSerializer(RegisterSerializer):
user = serializers.PrimaryKeyRelatedField(read_only=True,)
first_name = serializers.CharField(required=True)
last_name = serializers.CharField(required=True)
phone_number = serializers.CharField(required=True)
address = serializers.CharField(required=True)
def get_cleaned_data(self):
data = super(ClientCustomRegistrationSerializer, self).get_cleaned_data()
extra_data = {
'first_name' : self.validated_data.get('first_name', ''),
'last_name' : self.validated_data.get('last_name', ''),
'phone_number' : self.validated_data.get('phone_number', ''),
'address' : self.validated_data.get('address', ''),
}
data.update(extra_data)
return data
def save(self, request):
user = super(ClientCustomRegistrationSerializer, self).save(request)
user.is_client = True
user.email = self.data.get('email')
user.first_name = self.data.get('first_name')
user.last_name = self.data.get('last_name')
user.phone_number = self.data.get('phone_number')
user.address = self.data.get('address')
user.save()
client = Client(
user=user,
email=self.cleaned_data.get('email'),
first_name=self.cleaned_data.get('first_name'),
last_name=self.cleaned_data.get('last_name'),
phone_number = self.cleaned_data.get('phone_number'),
address = self.cleaned_data.get('address'),
)
client.save()
return user
settings related to django rest auth
AUTH_USER_MODEL = 'users.CustomUser'
ACCOUNT_USER_MODEL_USERNAME_FIELD = 'username'
ACCOUNT_UNIQUE_USERNAME = True
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_UNIQUE_EMAIL = False
ACCOUNT_USERNAME_REQUIRED = True
ACCOUNT_AUTHENTICATION_METHOD = 'username'
ACCOUNT_EMAIL_VERIFICATION = 'optional'
ACCOUNT_CONFIRM_EMAIL_ON_GET = True
ACCOUNT_EMAIL_CONFIRMATION_ANONYMOUS_REDIRECT_URL = '/?verification=1'
ACCOUNT_EMAIL_CONFIRMATION_AUTHENTICATED_REDIRECT_URL = '/?verification=1'
SITE_ID = 1
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
thanks for your help
Solved by removing the inheritance from custom user. You wouldn't inherit from the abstract class.
Trasporteur(CustomUser) => Trasporteur(models.Model):
In Django, I want to build a form that collects shipping addresses from users! Then save them to database
There is views.py starts with defining a function "is_valid_form(values)"
def is_valid_form(values):
valid = True
for field in values:
if field == '':
valid = False
return valid
class EnCheckoutView(View):
def get(self, *args, **kwargs):
try:
order = Order.objects.get(user=self.request.user, ordered=False)
form = CheckoutForm()
context = {
'form': form,
'couponform': CouponForm(),
'order': order,
'DISPLAY_COUPON_FORM': True
}
shipping_address_qs = Address.objects.filter(user=self.request.user, address_type='S', default=True)
if shipping_address_qs.exists():
context.update({
'default_shipping_address': shipping_address_qs[0]
})
return render(self.request, 'en-checkout-page.html', context)
except ObjectDoesNotExist:
messages.info(self.request, 'You do not have an active order.')
return redirect('core:en-checkout')
def post(self, *args, **kwargs):
try:
order = Order.objects.get(user=self.request.user, ordered=False)
except ObjectDoesNotExist:
messages.warning(self.request, 'You do not have an active order')
return redirect('core:en-order-summary')
form = CheckoutForm(self.request.POST or None)
if form.is_valid():
use_default_shipping = form.cleaned_data.get("use_default_shipping")
if use_default_shipping:
print('Using the default shipping address')
address_qs = Address.objects.filter(user=self.request.user, default=True)
if address_qs.exists():
shipping_address = address_qs[0]
order.shipping_address = shipping_address
order.save()
else:
messages.info(self.request, 'No default shipping address available')
return redirect('core:en-checkout')
else:
print('User is entering a new shipping address')
customer_name = form.cleaned_data.get('customer_name')
phone = form.cleaned_data.get('phone')
email = form.cleaned_data.get('email')
shipping_address1 = form.cleaned_data.get('shipping_address1')
shipping_address2 = form.cleaned_data.get('shipping_address2')
en_shipping_country = form.cleaned_data.get('en_shipping_country')
shipping_zip = form.cleaned_data.get("shipping_zip")
if is_valid_form([customer_name, phone, shipping_address1]):
shipping_address = Address(
user=self.request.user,
customer_name=customer_name,
phone=phone,
email=email,
street_address=shipping_address1,
apartment_address=shipping_address2,
country=en_shipping_country,
zip=shipping_zip,
address_type='S'
)
shipping_address.save()
order.shipping_address = shipping_address
order.save()
set_default_shipping = form.cleaned_data.get('set_default_shipping')
if set_default_shipping:
shipping_address.default = True
shipping_address.save()
else:
messages.info(self.request, 'Please ***fill in the required shipping address fields')
en_payment_option = form.cleaned_data.get('en_payment_option')
if en_payment_option == 'S':
return redirect('core:en-payment', en_payment_option='Pay with credit card')
elif en_payment_option == 'P':
return redirect('core:ar-delivery', en_payment_option='Cash on delivery')
else:
messages.warning(self.request, 'Invalid payment option selected')
return redirect('core:en/checkout')
Why this form does not save the address to the database?
I could have posted forms.py, html template, and models.py, but I guess that will explain the problem.
forms.py
EN_PAYMENT_CHOICES = (
('S', 'Pay with credit card'),
('P', 'Cash on delivery')
)
class CheckoutForm(forms.Form):
customer_name = forms.CharField(max_length=100, required=True)
phone = forms.IntegerField(required=True)
email = forms.EmailField()
shipping_address1 = forms.CharField(required=True)
shipping_address2 = forms.CharField(required=False)
ar_shipping_country = CountryField(blank_label='(اختار البلد)').formfield(
required=False,
widget=CountrySelectWidget(attrs={
'class': 'custom-select d-block w-100',
}))
en_shipping_country = CountryField(blank_label='(Choose a country)').formfield(
required=False,
widget=CountrySelectWidget(attrs={
'class': 'custom-select d-block w-100',
}))
shipping_zip = forms.CharField(required=False)
set_default_shipping = forms.BooleanField(required=False)
use_default_shipping = forms.BooleanField(required=False)
payment_option = forms.ChoiceField(
widget=forms.RadioSelect, choices=PAYMENT_CHOICES)
en_payment_option = forms.ChoiceField(
widget=forms.RadioSelect, choices=EN_PAYMENT_CHOICES)
models.py
class Address(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
customer_name = models.CharField(max_length=100, null=True)
phone = models.IntegerField(null=True)
email = models.EmailField(null=True)
street_address = models.CharField(max_length=250)
apartment_address = models.CharField(max_length=250)
country = CountryField(multiple=False, null=True)
zip = models.CharField(max_length=100)
address_type = models.CharField(max_length=1, choices=ADDRESS_CHOICES)
default = models.BooleanField(default=False)
def __str__(self):
return self.user.username
class Meta:
verbose_name_plural = 'Addresses'
The code works well but when trying to add a new user to the site it logs in as the superuser only.
Model
class RegistrationForm(forms.Form):
username = forms.CharField(label = 'Username', max_length = 30)
first_name = forms.CharField(label = 'First name', max_length = 30,widget=forms.TextInput(attrs={'class' : 'Name'}))
last_name = forms.CharField(label = 'Last name', max_length = 30,widget=forms.TextInput(attrs={'class' : 'Name'}))
email1 = forms.EmailField(label = 'email', required = True,widget=forms.TextInput(attrs={'class' : 'email'}))
email2 = forms.EmailField(label = 'Re-enter email',widget=forms.TextInput(attrs={'class' : 'email'}))
password1 = forms.CharField(label= "Password", widget = forms.PasswordInput(attrs={'class' : 'password1'}))
birthday = forms.DateField(label = 'Birthday',widget=forms.TextInput(attrs={'class' : 'birthday'}))
class Meta:
model = User
fields = ('username', 'email', 'password1','password2')
def save(self, commit = True):
user = super(RegistrationForm, self).save(commit = False)
user.email1 = self.cleaned_data['email1']
user.email2 = self.cleaned_data['email2']
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.birthday = self.cleaned_data['birthday']
if commit:
user.save()
return user
def clean_username(self):
email1 = self.cleaned_data['email1']
if not re.search(r"(^[a-zA-Z0-9_.+-]+#[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)", email1):
raise forms.ValidationError('Use a real email address eg. something#example.com.')
try:
user.objects.get(email1 = email1)
except ObjectDoesNotExist:
return username
raise forms.ValidationError('email is already in use.')
def clean_username(self):
username = self.clean_data['username']
if not re.search(r'^\w+$', username):
raise forms.ValidationError('Username can only contain alphanumeric characters and the underscore.')
try:
user.objects.get(username = username)
except ObjectDoesNotExist:
return username
raise forms.ValidationError('Username is already taken.')
Views
def register_page(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
form.save()
user = User.objects.create_user(
username = form.clean_data['username'],
password = form.clean_data['password1'],
email = form.clean_data['email']
)
return HttpResponseRedirect('/register/success/')
else:
args = {}
args.update(csrf(request))
args['form'] = RegistrationForm()
print(args)
return render(request, 'registration/register.html', args)
I tried adding another field (pin) in forms.py and models.py
The error i got was
"FieldError at /student/signup/
Cannot resolve keyword 'pin' into field. Choices are: date_joined, email, first_name, groups, id, is_active, is_staff, is_superuser, last_login, last_name, logentry, password, user_infos, user_permissions, username"
forms.py
class RegisterForm(forms.Form):
GRADE_CHOICES = (
(9,'9'), (10,'10'), (11,'11'), (12,'12') ,
)
curr_year = date.today().year
GRAD_YEAR_CHOICES = (
(curr_year,curr_year), (curr_year+1,curr_year+1), (curr_year+2,curr_year+2), (curr_year+3,curr_year+3) ,
)
first_name = forms.CharField(max_length = 25)
last_name = forms.CharField( max_length = 25)
emailid = forms.EmailField()
passwd1 = forms.CharField(max_length=100,widget=forms.PasswordInput)
passwd2 = forms.CharField(max_length=100,widget=forms.PasswordInput)
gradyear = forms.ChoiceField( choices=GRAD_YEAR_CHOICES)
grade = forms.ChoiceField( choices=GRADE_CHOICES)
pin = forms.IntegerField()
def clean(self):
cleaned_data = super(RegisterForm, self).clean()
print cleaned_data
if cleaned_data['passwd1'] != cleaned_data['passwd2']:
raise forms.ValidationError({'passwd1':['Password do not match']})
if User.objects.filter(email=cleaned_data['emailid']).count():
raise forms.ValidationError({'emailid':['Email already taken ']})
if User.objects.filter(pin=cleaned_data['pin']).count():
raise forms.ValidationError({'pin':['Pin already taken ']})
return cleaned_data
views.py
def signup(request):
print "signup"
if request.method == 'POST':
print "post signup"
form = RegisterForm(request.POST)
try:
if form.is_valid():
print form.cleaned_data
u = User.objects.create_user(form.cleaned_data['emailid'], form.cleaned_data['emailid'], form.cleaned_data['passwd1'] )
ui = UserInfo()
ui.user = u
ui.class_of = form.cleaned_data['gradyear']
ui.grade = form.cleaned_data['grade']
ui.balance = 0
print "Hi"
ui.pin = form.cleaned_data['pin']
print ui.pin
u.first_name = form.cleaned_data['first_name']
u.last_name = form.cleaned_data['last_name']
u.save()
ui.save()
user = authenticate(username=form.cleaned_data['emailid'], password=form.cleaned_data['passwd1'])
login(request,user)
print "after login in signup"
return redirect("/")
else:
print "error"
print form.errors
except:
raise
print "error here"
print form.errors
pass
#return render(request, 'student/register.html', {'form': form})
else:
form = RegisterForm()
return render(request, 'student/register.html', {'form': form})
models.py:
class UserInfo(models.Model):
user = models.OneToOneField(User, related_name='user_infos')
class_of = models.IntegerField()
#username = user.username
#fname = user.fname
#lname = user.last_name
#email = user.email
#Staff = user.is_staff
pub_date = models.DateTimeField( auto_now=True)
grade = models.IntegerField()
balance = models.DecimalField(max_digits=6, decimal_places=2)
pin = models.IntegerField()
#first_name = models.CharField(max_length = 25)
I don't think not be doing this right. Is there any way to add another column in a database another way?
You have "pin" field in your UserInfo model, but in forms.py you are trying to filter User model:
if User.objects.filter(pin=cleaned_data['pin']).count():
User model does not have "pin" field, so you are getting that error message.
Also I suggest you to learn and start using ModelForms: https://docs.djangoproject.com/en/1.8/topics/forms/modelforms/
I created an authentication backend:
from login.models import zUser
import hashlib
class AuthBackend:
def authenticate(self, username=None, password=None): #переписана функція для пошуку користувача в таблиці zusers
password = hashlib.md5(password).hexdigest() #хешування отриманого пароля в md5
try:
user = zUser.objects.get(userpass = password, login = username)
except zUser.DoesNotExist:
return None
return user
def get_user(self, user_id): #повернути користувача за id
try:
user = zUser.objects.get(id=user_id)
except zUser.DoesNotExist:
return None
return user
But in my view, where I call auth.login(request, user), I have an error:
The following fields do not exist in this model or are m2m fields: last_login
def Login(request):
if request.method == 'POST':
username = request.POST.get('username') #введений логін
password = request.POST.get('password').encode('utf-8') #введений пароль
user = auth.authenticate(username = username, password = password)
if user is not None:
user_id = getattr(user, "userid") #отримання userid користувача
auth.login(request, user)
return redirect('/')
else:
return redirect('/') #перенаправлення на головну сторінку
else:
return render_to_response('index.html', context_instance=RequestContext(request))
Then I add to settings:
AUTHENTICATION_BACKENDS = (
'login.auth_backends.AuthBackend',
'django.contrib.auth.ModelBackend'
)
But now there is other error:
Module "django.contrib.auth.ModelBackend" does not define a "ModelBackend" attribute/class
Update: Here is my zUser table
class zUser(models.Model): #модель користувача, створена по аналогії до таблиці zusers
userpass = models.CharField(max_length=50, blank=True)
telefon = models.CharField(max_length=25, blank=True)
remark = models.CharField(max_length=250, blank=True)
fio = models.CharField(max_length=50, blank=True)
userid = models.DecimalField(unique=True, max_digits=65535, decimal_places=65535, blank=True,primary_key=True)
changeonlogon = models.CharField(max_length=1, blank=True)
userlocked = models.CharField(max_length=1, blank=True)
login = models.CharField(max_length=300, blank=True)
#crypto = models.CharField(max_length=300, blank=True)
class Meta:
managed = False
db_table = 'zusers'