I have a form class (incorrect) :
class TeamGoalForm(ModelForm):
class Meta:
employees = forms.ModelMultipleChoiceField(queryset=Employee.objects.filter(departament=Department.objects.get(manager=Manager.objects.get(end_user_id = request.user.username.upper())),widget=forms.CheckboxSelectMultiple()))
department = forms.ModelChoiceField(queryset=Department.objects.all())
model = TeamGoal
fields = '__all__'
widgets = {
'employees' : forms.Select(attrs={'class': 'form-control', 'placeholder':'Select employees'}),
}
'department':forms.Select(attrs={'class': 'form-control', 'placeholder':'Select department'}),
I want to pass parameter request.user.username.upper() which I have in my view.py. How to implement this in my TeamGoalForm?
my view.py
#login_required(login_url='login')
def add_team_goal(request):
form = TeamGoalForm(is_manager(request))
if request.method == 'POST':
form = TeamGoalForm(request.POST)
if form.is_valid():
form.save()
return redirect('team_goal')
team = get_team(request)
if team.exists():
return render(request, 'smth.html', {'form':form,'team':team})
My Employee model:
# Employee section
class Employee(models.Model):
name = models.CharField(max_length=30, verbose_name='Name')
lastname = models.CharField(max_length=30, verbose_name='Lastname')
.............
history = HistoricalRecords()
def __str__(self):
return self.name + ' ' + self.lastname
My Department:
class Department(models.Model):
id = models.AutoField(primary_key=True)
title = models.CharField(max_length=30)
.........
manager = models.ForeignKey(Manager, related_name='manager_name', null=True, on_delete = models.SET_NULL)
history = HistoricalRecords()
My Managers:
class Manager(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=30)
lastname = models.CharField(max_length=30)
history = HistoricalRecords()
def __str__(self):
return self.name + ' ' + self.lastname
My TeamGoal:
class TeamGoal(models.Model):
team_goal_title = models.CharField(max_length=30, verbose_name='Title')
team_goal_description = models.CharField(max_length=100, blank=True, verbose_name='Description')
department = models.ForeignKey(Department, verbose_name='Department', on_delete = models.CASCADE, related_name='+', blank=True, null=True, help_text=u'If you assign the team goal for the whole department, please fill only Department field and skip Employee field.')
employees = models.ManyToManyField(Employee, null=True, blank=True, symmetrical=False, related_name='employee_name')
......
history = HistoricalRecords()
In my app I can create Team goal for whole department or for specific group of employees.
I would really advise not to give Manager the same name as a user and then match on that: it makes keeping records in sync quite hard. You can link to the user model with:
from django.conf import settings
class Manager(models.Model):
id = models.AutoField(primary_key=True)
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE
)
history = HistoricalRecords()
def __str__(self):
return f'{self.user.first_name} {self.user.lastname}'
you can pass the user as parameter to the ModelForm and then filter the queryset:
class TeamGoalForm(ModelForm):
def __init__(self, *args, user=None, **kwargs):
super().__init_(*args, **kwargs)
if user is not None:
self.field['employees'] = Employee.objects.filter(
department__manager__user=user
)
class Meta:
model = TeamGoal
fields = '__all__'
widgets = {
'employees' : forms.SelectMultiple(attrs={'class': 'form-control', 'placeholder':'Select employees'}),
'department':forms.SelectMultiple(attrs={'class': 'form-control', 'placeholder':'Select department'})
}
and in the view pass the logged in user to the TeamGoalForm:
#login_required(login_url='login')
def add_team_goal(request):
if request.method == 'POST':
form = TeamGoalForm(request.POST, user=request.user)
if form.is_valid():
form.save()
return redirect('team_goal')
else:
form = TeamGoalForm(user=request.user)
team = get_team(request)
return render(request, 'smth.html', {'form':form,'team':team})
Related
I trying to do a check In System where Students can do it themselves by inputting their ID's but I am really struggling.
Follow views, models, forms, and html
VIEW
class Attendance(CreateView):
template_name = 'homepage.html'
model = GetAttendance
fields = ['aluno']
success_msg = "Check In Succesfully"
def form_valid(self, form):
form.save()
success_msg = self.get_success_message(form.cleaned_data)
if success_msg:
messages.success(self.request, success_msg)
return super().form_valid(form)
def get_success_url(self):
return reverse('attendance:homepage')
def get_success_message(self, cleaned_data):
return self.success_msg % cleaned_data
MODELS
class Aluno(models.Model):
id = ShortUUIDField(primary_key=True, editable=False, alphabet="0123456789", length=5)
photo = models.ImageField(upload_to='photos/', default='static/images/defaultuser.jpeg', blank=True)
nome = models.CharField(max_length=255)
phone = models.CharField(max_length=255)
email = models.EmailField(max_length=255, unique=True)
location = models.ForeignKey(MasterUser, on_delete=models.CASCADE)
belt = models.CharField(max_length=255, choices=BELT)
stripe = models.CharField(max_length=255, choices=GRAU)
join_date = models.DateField(default=timezone.now)
last_graduation = models.DateField(default=timezone.now)
gender = models.CharField(max_length=255, choices=GENDER)
def __str__(self):
return self.nome
class GetAttendance(models.Model):
aluno = models.ForeignKey(Aluno, on_delete=models.CASCADE)
attendance = models.DateTimeField(default=timezone.now)
def __str__(self):
return str(self.aluno) + ' - ' + str(self.attendance)
That's views.py
My models.py
forms
html
check in page
Basically what I need is instead of having the form of a choice be able to input the student ID and run the model GetAttendance.
I am making a CV page,
I want to link my Skill, Language etc class(table) to Main Person table/class,
But for that, I need to submit skill table first because my person table contains the foreign key for skills.
But as per CV form name & personal info comes first.
Also, I can put the whole form on one page but I want to go to the next page for each sub information, so is it possible to pass the request data from one class-based view to another class-based view.
models.py
from django.db import models
from django.core.validators import MinLengthValidator
from django.conf import settings
import datetime
class Workexperience(models.Model):
work = models.CharField(null=True, blank=True,
max_length=256,
help_text='eg: Juniorengineer: at L&T ')
person = models.ForeignKey('Person', on_delete=models.CASCADE, blank=True, null=False, default=1 )
def __str__(self):
return self.work
class Education(models.Model):
school = models.CharField(max_length=200)
college = models.CharField(null=True, blank=True,max_length=200)
person = models.ForeignKey('Person', on_delete=models.CASCADE, blank=True, null=False, default=1 )
def __str__(self):
return self.school
class Skills(models.Model):
skill = models.CharField(
max_length=256,
help_text='Add skills sperated by commas eg: programming, Matlab')
person = models.ForeignKey('Person', on_delete=models.CASCADE, blank=True, null=False, default=1 )
def __str__(self):
return self.skill
class Languages(models.Model):
language = models.CharField(
max_length=256,
help_text='Add language sperated by commas eg: English, Gujarati')
person = models.ForeignKey('Person', on_delete=models.CASCADE, blank=True, null=False, default=1 )
def __str__(self):
return self.language
class Person(models.Model):
name = models.CharField(
max_length=100,
help_text='Enter a name (e.g. Harry Virani)',
validators=[MinLengthValidator(2, "It must be greater than 1 character")]
)
picture = models.BinaryField(null=True, blank=True, editable=True)
content_type = models.CharField(max_length=256, null=True, blank=True,
help_text='The MIMEType of the file')
profession = models.CharField(
max_length=100,
validators=[MinLengthValidator(2, "It must be greater than 1 character")]
)
owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, default='')
address = models.CharField(max_length=256)
email = models.EmailField(max_length = 254)
phone = models.CharField(
max_length=15,
help_text='Enter a phone number like this (e.g. +91000000000)',
validators=[MinLengthValidator(10, "It must be greater than 10 character")] )
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
facebook = models.URLField(null=True, blank=True, max_length=200,
help_text='enter your facebook URL' )
instagram = models.URLField(null=True, blank=True, max_length=200,
help_text='enter your instagram link URL' )
linkedin = models.URLField(null=True, blank=True, max_length=200,
help_text='enter your Linked link URL' )
skill = models.ManyToManyField(Skills, related_name='skills', default=1)
language = models.ManyToManyField(Languages, related_name='languages', default=1)
edu = models.ManyToManyField(Education, default=1,related_name='edu' )
work = models.ManyToManyField(Workexperience,default=1, blank=True, related_name='works')
# Shows up in the admin list
def __str__(self):
return self.name
views.py
I want to save it in another class which is for creating skill & other models.
class PersonCreateView(LoginRequiredMixin, View):
template_name = 'MYP/form.html'
success_url = 'MYP:myp_create_info'
def get(self, request, pk=None):
personform = PersonForm()
ctx = { 'personform': personform}
return render(request, self.template_name, ctx)
def post(self, request, pk=None) :
# if 'personform' in request.POST:
personform = PersonForm(request.POST, request.FILES or None)
if not personform.is_valid():
ctx = {'personform': personform}
return render(request, self.template_name, ctx)
pform = personform.save(commit=False)
#adding onwer
pform.owner = self.request.user
pform.save()
return redirect(self.success_url, pform.id)
class InfoCreateView(LoginRequiredMixin, View):
template_name = 'MYP/form2.html'
success_url = reverse_lazy('MYP:all')
def get(self, request, pk):
person = get_object_or_404(Person,id=pk)
skill= SkillsForm()
skill_list = Skills.objects.filter(person=person)
ctx = { 'skill':skill, 'skill_list':skill_list }
return render(request, self.template_name, ctx)
def post(self, request, pk):
if 'skill' in request.POST:
skill = SkillsForm(request.POST or None)
if not skill.is_valid() :
ctx = { 'skill':skill}
return render(request, self.template_name, ctx)
person = get_object_or_404(Person,id=pk)
print(person)
skill = Skills(skill=request.POST['skill'], person=person)
skill.save()
print(skill.person)
return redirect('MYP:myp_create_info', pk=pk)
forms.py
class PersonForm(forms.ModelForm):
max_upload_limit = 2 * 1024 * 1024
max_upload_limit_text = naturalsize(max_upload_limit)
# Call this 'picture' so it gets copied from the form to the in-memory model
# It will not be the "bytes", it will be the "InMemoryUploadedFile"
# because we need to pull out things like content_type
picture = forms.FileField(required=False, label='File to Upload <= '+max_upload_limit_text)
upload_field_name = 'picture'
# Hint: this will need to be changed for use in the ads application :)
class Meta:
model = Person
fields = ['name', 'profession', 'picture', 'address', 'email', 'phone','facebook','linkedin','instagram'] # Picture is manual
# Validate the size of the picture
def clean(self) :
cleaned_data = super().clean()
pic = cleaned_data.get('picture')
if pic is None : return
if len(pic) > self.max_upload_limit:
self.add_error('picture', "File must be < "+self.max_upload_limit_text+" bytes")
# Convert uploaded File object to a picture
def save(self, commit=True) :
instance = super(PersonForm, self).save(commit=False)
# We only need to adjust picture if it is a freshly uploaded file
f = instance.picture # Make a copy
if isinstance(f, InMemoryUploadedFile): # Extract data from the form to the model
bytearr = f.read();
instance.content_type = f.content_type
instance.picture = bytearr # Overwrite with the actual image data
if commit:
instance.save()
return instance
class WorkexperienceForm(forms.ModelForm):
class Meta:
model = Workexperience
fields = ['work']
class EducationForm(forms.ModelForm):
class Meta:
model = Education
fields = ['school','college']
class SkillsForm(forms.ModelForm):
class Meta:
model = Skills
fields = ['skill']
class LanguagesForm(forms.ModelForm):
class Meta:
model = Languages
fields = ['language']
Ignore the rest of the code it is just for image handling....
This is what I want to do but I know it is the wrong format
I want to just add id for everything later.
In my opinion, your models are messed up. Here is how I would have write them :
class WorkExperience(models.Model):
work = models.CharField(
blank=True,
max_length=256,
help_text='eg: Juniorengineer: at L&T'
)
def __str__(self):
return self.work
class Education(models.Model):
school = models.CharField(max_length=200)
college = models.CharField(blank=True, max_length=200)
def __str__(self):
return self.school
class Skill(models.Model):
name = models.CharField(
max_length=256,
help_text='Add a skill name (eg: Programming)'
)
def __str__(self):
return self.name
class Language(models.Model):
name = models.CharField(
max_length=256,
help_text='Add a language name (eg: Gujarati)'
)
def __str__(self):
return self.name
class Person(models.Model):
name = models.CharField(
max_length=100,
help_text='Enter a name (e.g. Harry Virani)',
validators=[MinLengthValidator(2, "It must be greater than 1 character")]
)
# [...Other fields...]
skills = models.ManyToManyField(Skill, related_name='persons', blank=True)
languages = models.ManyToManyField(Language, related_name='persons', blank=True)
educations = models.ManyToManyField(Education, related_name='persons', blank=True)
work_experiences = models.ManyToManyField(WorkExperience, related_name='persons', blank=True)
def __str__(self):
return self.name
Then I need to see your forms.py to better understand how you handle it in your view.
I have a custom user model from AbstractBaseUser and BaseUserManager. The user model is extended to a model called Employee. The employee model is related with(Foreignkey) two other model named WorkExperience and education. A single template form is designed with Employee, WorkExperience and Education modelform.
models.py:
class Employee(models.Model):
"""
Create employee attributes
"""
employee_user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True)
e_id = models.IntegerField(unique=True, null=True)
first_name = models.CharField(max_length=128, null=True)
last_name = models.CharField(max_length=128, null=True)
gender_choices = (
('Male', 'Male'),
('Female', 'Female'),
)
......
#receiver(post_save, sender=UserProfile)
def create_or_update_user_profile(sender, instance, created, **kwargs):
if created:
Employee.objects.create(employee_user=instance, email=instance.email)
instance.employee.save()
class WorkExperience(models.Model):
"""
Stores employee previous work experiences
"""
employee_user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True)
employee = models.ForeignKey('Employee', related_name='we_employee', on_delete=models.CASCADE, null=True)
previous_company_name = models.CharField(max_length=128, null=True)
job_designation = models.CharField(max_length=128, null=True)
from_date = models.DateField(null=True)
to_date = models.DateField(null=True)
job_description = models.CharField(max_length=256, null=True)
class Education(models.Model):
"""
Stores employee education background
"""
employee_user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True)
employee = models.ForeignKey('Employee', related_name='edu_employee', on_delete=models.CASCADE, null=True)
institution_name = models.CharField(max_length=128, null=True)
degree = models.CharField(max_length=128, null=True)
passing_year = models.IntegerField(null=True)
result = models.DecimalField(max_digits=5, decimal_places=2, null=True)
I have a CreateView of this three models. I have three modelform. I implemented CRUD using this modelforms. My problem is in UpdateView. When I call UpdateView an error is showing stating WorkExperience matching query does not exist.I think the query is not correct.
views.py:
class EmployeeUpdateView(LoginRequiredMixin, UpdateView):
"""
Update a created a employee
"""
login_url = '/authentication/login/'
template_name = 'employee/employee_update_form.html'
form_class = EmployeeAddModelForm
work_form_class = WorkExperienceForm
education_form_class = EducationForm
context_object_name = 'employee'
model = Employee
queryset = Employee.objects.all()
# Override default get method
def get(self, request, *args, **kwargs):
id_ = self.kwargs.get("id")
employee_id = Employee.objects.get(id=id_)
work_info = WorkExperience.objects.get(employee=employee_id)
education_info = Education.objects.get(employee=employee_id)
form = self.form_class(instance=employee_id)
work_form = self.work_form_class(prefix='work_form', instance=work_info)
education_form = self.education_form_class(prefix='education_form',instance=education_info)
return render(request, self.template_name, {
'form': form,
'work_form': work_form,
'education_form': education_form,
'supervisor_assigned': employee_id.supervisor_select
}
)
# Override default post method
def post(self, request, *args, **kwargs):
id_ = self.kwargs.get("id")
employee_id = Employee.objects.get(id=id_)
work_info = WorkExperience.objects.get(employee=employee_id)
education_info = Education.objects.get(employee=employee_id)
form = self.form_class(request.POST, instance=employee_id)
work_form = self.work_form_class(request.POST, prefix='work_form', instance=work_info)
education_form = self.education_form_class(request.POST, prefix='education_form',instance=education_info)
# Check form validation
if form.is_valid() and work_form.is_valid() and education_form.is_valid():
instance = form.save()
work = work_form.save(commit=False)
education = education_form.save(commit=False)
work.employee = instance
education.employee = instance
work.save()
education.save()
return redirect('employee:employee-list')
return render(request, self.template_name, {
'form': form,
'work_form': work_form,
'education_form': education_form
}
)
urls.py:
urlpatterns = [
path('employee-list/', EmployeeListView.as_view(), name='employee-list'),
path('employee-add/', EmployeeAddView.as_view(), name='employee-add'),
path('employee-list/<int:id>/', EmployeeDetailView.as_view(), name='employee-detail'),
path('employee-list/<int:id>/update/', EmployeeUpdateView.as_view(), name='employee-update'),
How can I modify my query? i think my query is not correct.
you need to use foreign Key to use the employee id :
work_info = WorkExperience.objects.get(employee__id=employee_id)
I Hope it works fine
I have three modelforms and I am trying to validate those forms in a single view. All forms are connected with OneToOne relation. I cannot validate subforms after main form ins same view. Tried few solutions and I guess I am doing something wrong and if someone can help I can redo it few times to understand it at my end. DoctorForm works fine but I couldn't find a suitable method to validate DoctorQualificationForm() and WorkExperienceForm(). Following is the code:
Models:
class User(AbstractUser):
ACC_TYPE = (
('', ''),
('Doctor', 'Doctor'),
('Patient', 'Patient')
)
account_type = models.CharField(max_length=20, choices=ACC_TYPE, null=True, blank=True)
cell_phone = models.IntegerField(null=True, blank=True)
landline = models.IntegerField(null=True, blank=True)
pic = models.ImageField(upload_to='profile/', null=True, blank=True)
secondary_email = models.EmailField(null=True, blank=True)
def __str__(self):
return str(self.username)
def get_absolute_url(self):
return reverse('user:detail', kwargs={'pk':self.user.pk})
class Role(models.Model):
LAB_ADMIN = 1
SALES_ADMIN = 2
SALES_EXCUTIVE = 3
LAB_TECH = 4
ROLE_CHOICES = (
(LAB_ADMIN, 'Lab Admin'),
(SALES_ADMIN, 'Sales Admin'),
(SALES_EXCUTIVE, 'Sales Executive'),
(LAB_TECH, 'Lab Tech'),
)
id = models.PositiveSmallIntegerField(choices=ROLE_CHOICES, primary_key=True)
doctor = models.OneToOneField('Doctor', on_delete=models.CASCADE, related_name='roles')
def __str__(self):
return self.id
class Doctor(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='doctor', null=True)
about = models.TextField()
#role = models.OneToOneField(Role, on_delete=models.CASCADE, related_name='currentrole',null=True, blank=True)
street = models.CharField(max_length=200)
city = models.CharField(max_length=200)
country = models.CharField(max_length=200)
cell_phone = models.CharField(max_length=200)
landline = models.CharField(max_length=200)
def __str__(self):
return str(self.user)
def get_absolute_url(self):
return reverse('doctor:detail', kwargs={'pk':self.pk})
class Qualitifaction(models.Model):
doctor = models.ForeignKey(Doctor, on_delete=models.CASCADE,
related_name='qualifications')
course_title = models.CharField(max_length=100)
institute_name = models.CharField(max_length=200)
location = models.CharField(max_length=200)
start_year = models.DateField(null=True)
end_year = models.DateField(null=True)
def __str__(self):
return self.course_title
def get_absolute_url(self):
return reverse('doctor:detail', kwargs={'pk':self.pk})
class WorkExperience(models.Model):
doctor = models.ForeignKey(Doctor, on_delete=models.CASCADE,
related_name='experience')
organization_name = models.CharField(max_length=100)
year_from = models.DateField(null=True)
year_to = models.DateField(null=True)
employement_role = models.CharField(max_length=200)
industry = models.CharField(max_length=200)
def __str__(self):
return self.organization_name
def get_absolute_url(self):
return reverse('doctor:detail', kwargs={'pk':self.pk})
#receiver(post_save, sender=User)
def update_user_profile(sender, instance, created, **kwargs):
if created:
if instance.account_type=='Employee':
profile = Employee.objects.get_or_create(user=instance)
elif instance.account_type=='Customer':
profile = Customer.objects.get_or_create(user=instance)
post_save.connect(update_user_profile, sender=User)
Forms:
class DoctorForm(forms.ModelForm):
model = Doctor
fields = ('about', 'street', 'city', 'country', 'cell_phone', 'landline',)
class DoctorQualificationForm(forms.ModelForm):
model = Qualitifaction
fields = ('course_title', 'institute_name', 'location', 'start_year', 'end_year')
class WorkExperienceForm(forms.ModelForm):
model = WorkExperience
fields = ('organization_name', 'year_from, 'year_to', 'employement_role', 'industry')
View:
def createDoctor(request):
if request.method == 'POST':
doctorform = DoctorForm(request.POST, instance=request.user.doctor)
qualifications_form = DoctorQualificationForm()# not sure how to ref instance here
workexperience_form = WorkExperienceForm()# not sure how to ref instance here
if doctorform.is_valid() and qualifications_form.is_valid() and workexperience_form.is_valid():
doctorform.save()
qualifications_form.save()
workexperience_form.save()
else:
doctorform = DoctorForm()
qualifications_form = DoctorQualificationForm()
workexperience_form = WorkExperienceForm()
return render(request, 'doctor/create.html', {'doctorform':doctorform, 'qualifications_form':qualifications_form, 'workexperience_form':workexperience_form})
def createDoctor(request):
if request.method == 'POST':
doctorform = DoctorForm(request.POST, instance=request.user.doctor)
qualifications_form = DoctorQualificationForm(request.POST)# not sure how to ref instance here
workexperience_form = WorkExperienceForm(request.POST)
if doctorform.is_valid() and qualifications_form.is_valid() and workexperience_form.is_valid():
doctor = doctorform.save()
qualification = qualifications_form.save(commit=False)
qualification.doctor = doctor
qualification.save()
work = workexperience_form.save(commit=False)
work.doctor = doctor
work.save()
else:
doctorform = DoctorForm()
qualifications_form = DoctorQualificationForm()
workexperience_form = WorkExperienceForm()
return render(request, 'doctor/create.html', {'doctorform':doctorform, 'qualifications_form':qualifications_form, 'workexperience_form':workexperience_form})
Although there are number of other ways to do it. But in case you have OneToOne rel in all models you just need to use validation of single or parent model. You can reference that validation in all the children as above.
I'm really having some trouble with this. I've got some custom user's setup and those users can be attached to companies via foreign key. I'm just having trouble saving them. I've tried a ton of different variations of getting the user attached to a company and I just can't crack it. The forms do work and it does both create a "customer" and a "customer company".
I know this needs to be a variation of:
if customer_form.is_valid() and customer_company_form.is_valid():
customer_company = customer_company_form.save()
customer = customer_form.save(commit=False)
customer.user = customer_company
customer_company.save()
models.py
class CustomerCompany(models.Model):
COUNTRIES = (
('USA', 'United States'),
('CAN', 'Canada')
)
name = models.CharField(max_length=100, blank=True, unique=True)
website = models.CharField(max_length=100, blank=True)
phone = models.CharField(max_length=10, blank=True)
address = models.CharField(max_length=100, blank=True)
city = models.CharField(max_length=255, blank=True)
state = USStateField(blank=True, null=True)
us_zipcode = USZipCodeField(blank=True, null=True)
ca_province = models.CharField(max_length=50, blank=True, null=True)
ca_postal_code = models.CharField(max_length=7, blank=True, null=True)
country =models.CharField(max_length=3, choices=COUNTRIES,
blank=True)
def get_absolute_url(self):
return reverse('accounts:customer_company_detail',kwargs={'pk':self.pk})
def __str__(self):
return self.name
class Customer(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE,
primary_key=True, related_name='customer_profile')
company = models.ForeignKey(CustomerCompany, on_delete=models.CASCADE, null=True)
phone = models.CharField(max_length=10)
def __str__(self):
return self.user.first_name + ' ' + self.user.last_name
forms.py
class CustomerSignupForm(UserCreationForm):
first_name = forms.CharField(max_length=50, required=True)
last_name = forms.CharField(max_length=50, required=True)
phone = forms.CharField(max_length=10, required=True)
email = forms.EmailField(required=True)
class Meta(UserCreationForm.Meta):
model = User
#transaction.atomic
def save(self, commit=True):
user = super(CustomerSignupForm, self).save(commit=False)
user.is_customer = True
user.first_name = self.cleaned_data.get('first_name')
user.last_name = self.cleaned_data.get('last_name')
user.email = self.cleaned_data.get('email')
user.save()
customer = Customer.objects.create(user=user)
customer.phone = self.cleaned_data.get('phone')
customer.save()
return user
class CustomerCompanyCreateForm(forms.ModelForm):
ca_province = CAProvinceField(required=False, label="Province")
ca_postal_code = CAPostalCodeField(required=False, label="Postal Code")
class Meta:
model = CustomerCompany
fields = ['name', 'website', 'phone', 'address', 'city', 'state',
'us_zipcode', 'country', 'ca_province', 'ca_postal_code']
labels = {
"us_zipcode": "Zipcode",
}
views.py Updated with working code
def customer_signup(request):
if request.method == 'POST':
customer_form = CustomerSignupForm(request.POST)
customer_company_form = CustomerCompanyCreateForm(request.POST)
if customer_form.is_valid() and customer_company_form.is_valid():
# first save the user object
user_obj = customer_form.save(commit=False)
# Then use this object to get to my Customer model via the related name
customer = user_obj.customer_profile
# now save the CustomerCompany
company = customer_company_form.save()
# attach the customer to the Company
customer.company = company
# now fully save the customer after he's attached to his company
customer.save()
return redirect('customer_dashboard:customer_dashboard')
else:
messages.error(request, 'Please correct the errors below.')
else:
customer_form = CustomerSignupForm()
customer_company_form = CustomerCompanyCreateForm()
return render(request, 'accounts/registration/customer_signup_combined.html', {
'customer_form' : customer_form,
'customer_company_form' : customer_company_form,
})
You're saving both forms in your view but you're not connecting the two objects.
Calling save on the customer_form will return a User object since its a User ModelForm. You can use this object to get to the Customer object via the customer_profile related_name and set the company field to the Company instance returned when you save the customer_company_form.
It should look like this:
if customer_form.is_valid() and customer_company_form.is_valid():
user_obj = customer_form.save(commit=True)
customer = user_obj.customer_profile
company = customer_company_form.save(commit=True)
customer.company = company
customer.save()
return redirect('customer_dashboard:customer_dashboard')