How to union some forms generated from models - python

I try to create registration form. It consists of several forms UserForm, UserProfileForm and CompanyForm which are generated from models.
models.py
from django.db import models
from django.contrib.auth.models import User
class Company(models.Model):
login = models.CharField(max_length=20, null=True)
password = models.CharField(max_length=10, null=True)
is_active = models.BooleanField()
title = models.CharField(max_length=100)
org = models.CharField(max_length=50)
inn = models.BigIntegerField()
kpp = models.BigIntegerField()
class UserProfile(models.Model):
company = models.ForeignKey(Company)
user = models.OneToOneField(User)
department = models.CharField(max_length=100)
position = models.CharField(max_length=100)
forms.py
from django.contrib.auth.models import User
from django.forms import ModelForm
from django.forms import HiddenInput
from django.forms.models import modelformset_factory
from models import Company, UserProfile
class CompanyRegistrationForm(ModelForm):
class Meta:
model = Company
exclude = ('login', 'password', 'is_active')
class UserForm(ModelForm):
class Meta:
model = User
fields = ('first_name', 'last_name', 'email')
class UserProfileForm(ModelForm):
class Meta:
model = UserProfile
exclude = ('user')
widgets = {'company': HiddenInput()}
I try do this by formsets and inheritance but unfortunately.
I want one form with one custom save method, is it possible?
ps And my views.py is
class RegistrationCreateView(CreateView):
template_name = 'accounts/registration.html'
model = Company
#form_class = CompanyRegistrationForm
success_url = 'thanks/'
def _create_credentials(self):
login_str = random.randint(1000000, 9999999)
password = ''.join([symbol for i in range(10)
for symbol in random.choice(string.letters)])
return login_str, password
def form_valid(self, form):
context = self.get_context_data()
form = context['registration_form']
if form.is_valid():
#TODO(mid): refactor this
self.object = form.save()
company_id = self.object.id
login_str, password = self._create_credentials()
self.object.password = password
self.object.login = login_str
self.object.is_active = True
form.instance = self.object
form.save()
return self.success(login_str, password, company_id)
return self.form_invalid(form)
def form_invalid(self, form):
return self.render_to_response(self.get_context_data(form=form))
def get_context_data(self, **kwargs):
context = super(RegistrationCreateView, self).get_context_data(**kwargs)
context['registration_form'] = CompanyRegistrationForm()
context['user_form'] = UserForm()
context['user_profile_form'] = UserProfileForm()
if self.request.POST:
context['registration_form'] = CompanyRegistrationForm(self.request.POST)
context['user_form'] = UserForm(self.request.POST)
context['user_profile_form'] = UserProfileForm(self.request.POST)
return context
def success(self, login_str, password, company_id):
login(self.request, self.object)
self.request.session['company_id'] = company_id
return render_to_response('accounts/thanks.html',
{'login': login_str, 'password': password},
RequestContext(self.request))

Related

User Form not showing django class based views

I am working on Hospital Management System and there are 5-6 different types of users like Patient, Doctor, Nurse, Accountant, Receptionist, etc. I've extended the User model using AbstractUser which has common fields for all users like DoB, address, etc.
models.py
class User(AbstractUser):
# user_type = models.CharField(choices=USER_TYPES, default='patient', max_length=20)
date_of_birth = models.DateField(blank=True, null=True, validators=[validate_future_date])
phone_regex = RegexValidator(regex=r'^\+?1?\d{9,15}$', message="Phone number must be entered in the format: '+9199999999'. Up to 15 digits allowed.")
mobile_num = models.CharField(max_length=15, validators=[phone_regex])
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
date_joining = models.DateTimeField(auto_now_add=True)
photo = models.ImageField(default="default.png", upload_to="patients/%Y/%m/%d", blank=True)
# other fields
def __str__(self):
return f"{self.first_name} {self.last_name}({self.username})"
class Staff(models.Model):
aadhar_number = models.BigIntegerField(verbose_name='Aadhar Number')
empCategory = models.CharField(max_length=20, blank=True, verbose_name='Employee Category')
class Meta:
abstract = True
class Patient(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
date_of_discharge = models.DateTimeField(auto_now=True)
allergies = models.TextField(blank=True, null=True)
def __str__(self):
return f"{self.user.first_name} {self.user.last_name}({self.user.username})"
class Doctor(models.Model):
DEPARTMENTS = [('Cardiologist', 'Cardiologist'),
('Dermatologists', 'Dermatologists'),
('Emergency Medicine Specialists', 'Emergency Medicine Specialists'),
('Allergists/Immunologists', 'Allergists/Immunologists'),
('Anesthesiologists', 'Anesthesiologists'),
('Colon and Rectal Surgeons', 'Colon and Rectal Surgeons')
]
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
languages = models.CharField(max_length=20)
speciality = models.CharField(max_length=20)
department = models.CharField(max_length=50, choices=DEPARTMENTS)
# patients = models.ManyToManyField(Patient, related_name='doctors')
def __str__(self):
return f"{self.user.first_name} {self.user.last_name}({self.user.username})"
class Receptionist(Staff):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
# patient = models.ManyToManyField(Patient, related_name='receptionists', blank=True)
def __str__(self):
return f"{self.user.first_name}"
class Nurse(Staff):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
class Meta:
verbose_name_plural = 'Nurses'
class Accountant(Staff):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
forms.py
class UserRegistrationForm(forms.ModelForm):
password = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Repeat Password', widget=forms.PasswordInput)
email = forms.EmailField(label='Email')
date_of_birth = forms.DateField(widget=forms.widgets.DateInput(attrs={'type': 'date'}))
class Meta:
# gives current active model either Custom User or default User model
model = get_user_model()
fields = ['username', 'first_name', 'last_name', 'email',
'date_of_birth', 'photo', 'mobile_num', 'gender',
'father_name', 'mother_name', 'blood_group', 'marital_status',
'address1', 'address2', 'city', 'zipcode', 'state'
]
exclude = ['groups', 'superuser_status',
'is_staff', 'is_superuser', ]
def clean_password2(self):
cd = self.cleaned_data
if cd['password'] != cd['password2']:
raise forms.ValidationError("Passwords don't match")
return cd['password2']
class PatientRegistrationForm(forms.ModelForm):
class Meta:
model = Patient
fields = ['allergies']
exclude = ['user', ]
views.py
class UserRegistrationMixin(TemplateResponseMixin, View):
form_class = UserRegistrationForm
template_name = 'accounts/register.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['user_form'] = self.form_class
return context
def get(self, request):
user_form = self.form_class
return self.render_to_response({'user_form':user_form})
def post(self, request):
user_form = self.form_class(data=request.POST, files=request.FILES)
if user_form.is_valid():
new_user = user_form.save(commit=False)
password = user_form.cleaned_data['password']
new_user.set_password(password)
new_user.save()
messages.success(request, f'New user "{new_user}" created!')
return self.render_to_response({'user_form':user_form})
class PatientRegistrationView(UserRegistrationMixin, CreateView):
profile_form_class = PatientRegistrationForm
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['profile_form'] = self.profile_form_class
return context
def get(self, request):
profile_form = self.profile_form_class
return self.render_to_response({'profile_form':profile_form})
def post(self, request):
profile_form = self.profile_form_class(data=request.POST, files=request.FILES)
if profile_form.is_valid():
# Patient.objects.create()
profile = profile_form.save(commit=False)
profile.user = new_user
profile.save()
messages.success(request, f'Profile for user "{new_user}" created!')
return self.render_to_response({'profile_form':profile_form})
I am trying to separate common logic for registering users and creating profiles for each user i.e. UserRegistrationMixin has logic to create a user and PatientRegistrationView will create a patient's profile and its permissions. But when I inherit from UserRegistrationMixin, user_form doesn't show. I don't have much experience in Django's GCBV. Thanks in advance.
The problem is your get method. The get_context_data doesn't called. You can check the get method of View class:
def get(self, request, *args, **kwargs):
"""Handle GET requests: instantiate a blank version of the form."""
return self.render_to_response(self.get_context_data())
You can call context = self.get_context_data() and pass the context to render_to_response.

Not able to create a SignUp page using Django

I am not able to create a User Registration page using Django where I have used a Profile model with the OnetoOne field with the default User model.
views.py
def SignUpView(request):
if request.method == 'POST':
user_form = SignUpForm(data=request.POST)
profile_form = ProfileForm(data=request.POST)
if user_form.is_valid() and profile_form.is_valid():
new_user = user_form.save(commit=False)
new_profile = profile_form.save(commit=False)
new_profile.user = new_user
userName = new_user.username
password = new_profile.password1
new_user.save(commit=True)
new_profile.save(commit=True)
user = authenticate(username = userName, password = password)
login(request, user)
return redirect('blog-home')
else:
user_form = SignUpForm()
profile_form = ProfileForm()
context = {
'user_form': user_form,
'profile_form': profile_form,
}
return render(request, 'user/signup.html', context=context)
forms.py:
class SignUpForm(UserCreationForm):
class meta:
model = User
fields = ['username', 'first_name', 'last_name', 'password1', 'password2']
class ProfileForm(forms.ModelForm):
class meta:
model = Profile
fields = ['user', 'email']
models.py:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
# img =
date_of_birth = models.DateField(blank=True, null=True)
bio = models.CharField(blank=True, max_length=500)
location = models.CharField(blank=True, max_length=50)
email = models.EmailField(unique=True, max_length=200)
def __str__(self):
return f'Profile for {self.user.username}'
It is displaying an error message on the signup page as :
ValueError at /signup/
ModelForm has no model class specified.
It could be because there's a typo in your meta class declaration.
Change it to - class Meta. Note the case.
Did you try this to get the User model?
from django.contrib.auth import get_user_model
User = get_user_model()
Change it to - class Meta
class SignUpForm(UserCreationForm):
class Meta:
model = User
fields = ['username', 'first_name', 'last_name', 'password1', 'password2']
class ProfileForm(forms.ModelForm):
class Meta:
model = Profile
fields = ['user', 'email']
If this isn't a form based on a model, don't inherit from forms.ModelForm, just use an ordinary forms.Form.

I am trying to create a registration form to add data to 2 tables simultaneously. But I am not sure what to write after the POST method

I want to create a user into auth_user. And use its id(primary key) to
fill in an entry into User_Profile to take it as a Foreign key.
Models.py:
class User_Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
contact_number = models.IntegerField()
birth_date = models.DateField(null=False)
address = models.CharField(max_length=200)
role = models.ForeignKey(Role, on_delete=models.CASCADE)
Forms.py:
class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput)
class Meta:
model = User
fields = ['username', 'email', 'password']
class UserProfileForm(forms.ModelForm):
class Meta:
model = User_Profile
fields = [ 'contact_number', 'birth_date', 'address', 'role']
Views.py:
def registration_view(request):
form = UserForm(request.POST)
form2 = UserProfileForm(request.POST)
else:
context = {
'form': form,
'form2': form2
}
return render(request, 'Schoool/registration_form.html', context)

django - linking the register form info to user profile model

I am trying to make a webapp that includes register/login operations. The login is working fine but the registration form is frustrating.
I have a class registration form that inherits from UserCreationForm. The users are created and seen in the admin page when created but the problem I am having is not being able to see them in my UserProfile model in the admin page. It does not link the information and I could not find a way the link them.
Here is the registration form:
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
class RegistrationForm(UserCreationForm):
email = forms.EmailField(required=True)
city = forms.CharField(required=False)
country = forms.CharField(required=True)
first_name = forms.CharField(required=True)
last_name = forms.CharField(required=True)
username = forms.CharField(required=True)
class Meta:
model = User
fields = (
'username',
'first_name',
'last_name',
'country',
'city',
'email'
)
def save(self, commit=True):
user = super(RegistrationForm, self).save(commit=False)
#user.first_name = self.cleaned_data['first_name']
if commit:
user.save()
return user
Here are my models:
class UserProfile(models.Model):
user = models.OneToOneField( User,
on_delete=models.CASCADE
)
username = models.TextField(max_length=30, default="")
first_name = models.TextField(max_length=30, default="")
last_name = models.TextField(max_length=30, default="")
country = models.TextField(max_length=30, default="Which country are you from?")
city = models.TextField(max_length=30, default="Which city are you from?")
class ColorChoice(models.Model):
user = models.ForeignKey(
'UserProfile',
on_delete=models.CASCADE
)
color1 = models.IntegerField()
color2 = models.IntegerField()
color3 = models.IntegerField()
color4 = models.IntegerField()
color5 = models.IntegerField()
and my view.py that does the registering:
def register(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
form.save()
return redirect('color')
else:
form = RegistrationForm()
args = {'form': form}
return render(request, 'account/create_new.html', args)
Your form is only creating a new objects for User. You would need to add a signal for example to create a new object for UserProfile.
Something like this:
def create_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
signals.post_save.connect(create_user_profile, sender=User)

Django UserCreationForm add request.user.pk ?

Hi i need add request user pk to UserCreationForm. I try many times, but with out results. In my dashboard i have user owner and i have user seller.
One model for all 3 types user. So Owner can create another user with role=seller, but for this i need add parent field with param=request.user.pk to seller
Custom UserModel
from django.db import models
from django.contrib.auth.models import AbstractUser
USER = 0
OWNER = 1
SELLER = 2
user_type_choice = (
(USER, 'User'),
(OWNER, 'Owner'),
(SELLER, 'Seller'),
)
class User(AbstractUser):
role = models.CharField(max_length=100, choices=user_type_choice, default=USER)
idn = models.CharField(max_length=10, blank=True, default=None, null=True)
mobile = models.CharField(max_length=15, blank=True, default=None, null=True)
parent = models.ForeignKey('self', null=True, blank=True)
tariff = models.IntegerField(default=None, null=True, blank=True)
class Meta(AbstractUser.Meta):
swappable = 'AUTH_USER_MODEL'
forms.py
class SellerRegisterForm(UserCreationForm):
email = forms.EmailField(required=True)
first_name = forms.CharField(required=False)
last_name = forms.CharField(required=False)
class Meta:
model = User
fields = ('username', 'email', 'password1', 'password2') """try add and remove 'parent' here in felds """
def save(self, commit=True):
user = super(SellerRegisterForm, self).save(commit=False)
user.email = self.cleaned_data['email']
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.role = ROLE_SELLER
# try add user.parent = self.request.user.pk
# but it does not work
if commit:
user.save()
return user
views.py
def register_seller(request):
if request.method == 'POST':
form = SellerRegisterForm(request.POST) # create form object
if form.is_valid():
#try add new_form = form.save(commit=False)
# new_form.parent = request.user.pk
# new_form.save() but it not working
form.save()
return HttpResponseRedirect('/accounts/login')
else:
form = SellerRegisterForm()
return render(request, 'register_owner.html', {'form': form})
You need to pass the user object through the form's __init__ method.
class SellerRegisterForm(UserCreationForm):
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user', None)
super(SellerRegisterForm, self).__init__(*args, **kwargs)
and in your view:
form = SellerRegisterForm(request.POST, user=request.user)
Then simply use self.user anywhere in your form class.

Categories