I am trying to create a form in Django that can create one Student object with two Contact objects in the same form. The second Contact object must be optional to fill in (not required).
Schematic view of the objects created in the single form:
Contact 1
Student <
Contact 2 (not required)
I have the following models in models.py:
class User(AbstractUser):
is_student = models.BooleanField(default=False)
is_teacher = models.BooleanField(default=False)
class Student(models.Model):
ACCOUNT_STATUS_CHOICES = (
('A', 'Active'),
('S', 'Suspended'),
('D', 'Deactivated'),
)
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
year = models.ForeignKey(Year, on_delete=models.SET_NULL, null=True)
school = models.ForeignKey(School, on_delete=models.SET_NULL, null=True)
student_email = models.EmailField() # named student_email because email conflicts with user email
account_status = models.CharField(max_length=1, choices=ACCOUNT_STATUS_CHOICES)
phone_number = models.CharField(max_length=50)
homework_coach = models.ForeignKey(Teacher, on_delete=models.SET_NULL, null=True, blank=True, default='')
user = models.OneToOneField(User, on_delete=models.CASCADE, null=True)
plannings = models.ForeignKey(Planning, on_delete=models.SET_NULL, null=True)
def __str__(self):
return f"{self.first_name} {self.last_name}"
class Contact(models.Model):
student = models.ForeignKey(Student, on_delete=models.CASCADE)
contact_first_name = models.CharField(max_length=50)
contact_last_name = models.CharField(max_length=50)
contact_phone_number = models.CharField(max_length=50)
contact_email = models.EmailField()
contact_street = models.CharField(max_length=100)
contact_street_number = models.CharField(max_length=10)
contact_zipcode = models.CharField(max_length=30)
contact_city = models.CharField(max_length=100)
def __str__(self):
return f"{self.contact_first_name} {self.contact_last_name}"
In forms.py, I have created two forms to register students and contacts. A student is also connected to a User object for login and authentication, but this is not relevant. Hence, when a user is created, the user is defined as the user.
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from django.db import transaction
from .models import Student, Teacher, User, Year, School, Location, Contact
class StudentSignUpForm(UserCreationForm):
ACCOUNT_STATUS_CHOICES = (
('A', 'Active'),
('S', 'Suspended'),
('D', 'Deactivated'),
)
#student
first_name = forms.CharField(max_length=50, required=True)
last_name = forms.CharField(max_length=50, required=True)
year = forms.ModelChoiceField(queryset=Year.objects.all(), required=False)
school = forms.ModelChoiceField(queryset=School.objects.all(), required=False) # not required for new schools / years that are not yet in the database
student_email = forms.EmailField(required=True)
account_status = forms.ChoiceField(choices=ACCOUNT_STATUS_CHOICES)
phone_number = forms.CharField(max_length=50, required=True)
homework_coach = forms.ModelChoiceField(queryset=Teacher.objects.all(), required=False)
class Meta(UserCreationForm.Meta):
model = User
fields = (
'username',
'first_name',
'last_name',
'year',
'school',
'student_email',
'account_status',
'phone_number',
'homework_coach',
'password1',
'password2',
)
#transaction.atomic
def save(
self,
first_name,
last_name,
year,
school,
student_email,
account_status,
phone_number,
homework_coach,
):
user = super().save(commit=False)
user.is_student = True
user.save()
Student.objects.create( # create student object
user=user,
first_name=first_name,
last_name=last_name,
year=year,
school=school,
student_email=student_email,
account_status=account_status,
phone_number=phone_number,
homework_coach=homework_coach
)
return user
class ContactForm(forms.ModelForm):
contact_first_name = forms.CharField(max_length=50, required=True)
contact_last_name = forms.CharField(max_length=50, required=True)
contact_phone_number = forms.CharField(max_length=50, required=False)
contact_email = forms.EmailField(required=False) # not required because some students might not know contact information
contact_street = forms.CharField(max_length=100, required=False)
contact_street_number = forms.CharField(max_length=10, required=False)
contact_zipcode = forms.CharField(max_length=10, required=False)
contact_city = forms.CharField(max_length=100, required=False)
class Meta:
model = Contact
fields = '__all__'
In views.py, I have created a view that saves the data (so far only student data, not contact data).
class StudentSignUpView(CreateView):
model = User
form_class = StudentSignUpForm
template_name = 'registration/signup_form.html'
def get_context_data(self, **kwargs):
kwargs['user_type'] = 'student'
return super().get_context_data(**kwargs)
def form_valid(self, form):
# student
first_name = form.cleaned_data.get('first_name')
last_name = form.cleaned_data.get('last_name')
year = form.cleaned_data.get('year')
school = form.cleaned_data.get('school')
student_email = form.cleaned_data.get('student_email')
account_status = form.cleaned_data.get('account_status')
phone_number = form.cleaned_data.get('phone_number')
homework_coach = form.cleaned_data.get('email')
user = form.save(
# student
first_name=first_name,
last_name=last_name,
year=year,
school=school,
student_email=student_email,
account_status=account_status,
phone_number=phone_number,
homework_coach=homework_coach,
)
login(self.request, user)
return redirect('home')
And in registration/signup_form.html, the template is as follows:
{% block content %} {% load crispy_forms_tags %}
<form method="POST" enctype="multipart/form-data">
{{ formset.management_data }}
{% csrf_token %}
{{formset|crispy}}
<input type="submit" value="Submit">
</form>
{% endblock %}
Urls.py:
from .views import StudentSignUpView
urlpatterns = [
path('', views.home, name='home'),
path('signup/student/', StudentSignupView.as_view(), name='student_signup'),
]
How can I create one view that has one form that creates 1 Student object and 2 Contact objects (of which the 2nd Contact is not required)?
Things I have tried:
Using formsets to create multiple contacts at once, but I only managed to create multiple Contacts and could not manage to add Students to that formset.
I added this to views.py:
def formset_view(request):
context={}
# creating the formset
ContactFormSet = formset_factory(ContactForm, extra = 2)
formset = ContactFormSet()
# print formset data if it is valid
if formset.is_valid():
for form in formset:
print(form.cleaned_data)
context['formset']=formset
return render(request, 'registration/signup_form.html', context)
Urls.py:
urlpatterns = [
path('', views.home, name='home'),
path('signup/student/', views.formset_view, name='student_signup'),
]
But I only managed to create multiple Contacts and was not able to add a Student object through that form. I tried creating a ModelFormSet to add fields for the Student object, but that did not work either.
######## EDIT ##########
Following #nigel222's answer, I have now created the following form:
class StudentSignUpForm(forms.ModelForm):
class Meta:
model = Student
fields = (
'username',
'email',
'first_name',
'last_name',
'year',
'school',
'student_email',
'account_status',
'phone_number',
'homework_coach',
'password1',
'password2',
'contact1_first_name',
'contact1_last_name',
'contact1_phone_number',
'contact1_email',
'contact1_street',
'contact1_street_number',
'contact1_zipcode',
'contact1_city',
'contact2_first_name',
'contact2_last_name',
'contact2_phone_number',
'contact2_email',
'contact2_street',
'contact2_street_number',
'contact2_zipcode',
'contact2_city',
)
# user
username = forms.CharField(label='Username', min_length=5, max_length=150)
email = forms.EmailField(label='Email')
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Confirm Password', widget=forms.PasswordInput)
# contact 1
contact1_first_name = forms.CharField(max_length=50, required=True)
contact1_last_name = forms.CharField(max_length=50, required=True)
contact1_phone_number = forms.CharField(max_length=50, required=False)
contact1_email = forms.EmailField(required=False) # not required because some students might not know contact information
contact1_street = forms.CharField(max_length=100, required=False)
contact1_street_number = forms.CharField(max_length=10, required=False)
contact1_zipcode = forms.CharField(max_length=10, required=False)
contact1_city = forms.CharField(max_length=100, required=False)
# contact 2
contact2_first_name = forms.CharField(max_length=50, required=True)
contact2_last_name = forms.CharField(max_length=50, required=True)
contact2_phone_number = forms.CharField(max_length=50, required=False)
contact2_email = forms.EmailField(required=False) # not required because some students might not know contact information
contact2_street = forms.CharField(max_length=100, required=False)
contact2_street_number = forms.CharField(max_length=10, required=False)
contact2_zipcode = forms.CharField(max_length=10, required=False)
contact2_city = forms.CharField(max_length=100, required=False)
def username_clean(self):
username = self.cleaned_data['username'].lower()
new = User.objects.filter(username = username)
if new.count():
raise ValidationError("User Already Exist")
return username
def email_clean(self):
email = self.cleaned_data['email'].lower()
new = User.objects.filter(email=email)
if new.count():
raise ValidationError(" Email Already Exist")
return email
def clean_password2(self):
password1 = self.cleaned_data['password1']
password2 = self.cleaned_data['password2']
if password1 and password2 and password1 != password2:
raise ValidationError("Password don't match")
return password2
def save(self, commit = True):
user = User.objects.create_user(
self.cleaned_data['username'],
self.cleaned_data['email'],
self.cleaned_data['password1']
)
return user
#transaction.atomic
def form_valid(self, form):
student = form.save()
user = super().save(commit=False)
user.is_student = True
user.save()
contact1 = Contact(
student = student,
contact_first_name = form.cleaned_data['contact1_first_name'],
contact_last_name = form.cleaned_data['contact1_last_name'],
contact_phone_number = form.cleaned_data['contact1_phone_number'],
contact_email = form.cleaned_data['contact1_email'],
contact_street = form.cleaned_data['contact1_street'],
contact_street_number = form.cleaned_data['contact1_street_number'],
contact_zipcode = form.cleaned_data['contact1_zipcode'],
contact_city = form.cleaned_data['contact1_city'],
)
contact1.save()
if (form.cleaned_data['contact2_first_name'] and
form.cleaned_data['contact2_last_name'] # blank if omitted
):
contact2 = Contact(
student=student,
contact_first_name = form.cleaned_data['contact2_first_name'],
contact_last_name = form.cleaned_data['contact2_last_name'],
contact_phone_number = form.cleaned_data['contact2_phone_number'],
contact_email = form.cleaned_data['contact2_email'],
contact_street = form.cleaned_data['contact2_street'],
contact_street_number = form.cleaned_data['contact2_street_number'],
contact_zipcode = form.cleaned_data['contact2_zipcode'],
contact_city = form.cleaned_data['contact2_city'],
)
contact2.save()
return redirect('home')
And because the form is now a ModelForm, instead of a UserCreationForm, I had to add various functions to validate the user's credentials, such as save(), clean_password2() and email_clean().
And created this view in views.py:
def student_signup(request):
if request.method == 'POST':
student_signup_form = StudentSignUpForm()
if student_signup_form.is_valid():
student_signup_form.form_valid(student_signup_form)
return redirect('home')
else:
student_signup_form = StudentSignUpForm()
return render(request, 'registration/signup_form.html', {'student_signup_form': student_signup_form})
The forms render perfectly now: there are fields for the User's password and username, the Student's name etc, and finally the two contacts, all in one form. So we're getting there!
The only problem is that when I fill the form in, nothing is saved in the database after I hit submit. Does anyone know why this happens?
What I'd try:
I don't understand your StudentSignUpForm magic. However, if it's effectively the same as a ModelForm:
class StudentSignUpForm(forms.Modelform):
class Meta:
model = Student
fields = ('first_name', 'last_name', ...)
then just add non-model fields
contact1_first_name = forms.CharField(max_length=50, required=True)
contact1_last_name = forms.CharField(max_length=50, required=True)
contact1_phone_number = forms.CharField(max_length=50, required=False)
...
contact2_first_name = forms.CharField(max_length=50, required=True)
...
contact2_zipcode = forms.CharField(max_length=10, required=False)
contact2_city = forms.CharField(max_length=100, required=False)
And then put everything together in form_valid:
#transaction.atomic
def form_valid( self, form):
student = form.save()
contact1 = Contact(
student = student,
contact_first_name = form.cleaned_data['contact1_first_name'],
contact_last_name = ...
)
contact1.save()
if (form.cleaned_data['contact2_first_name'] and
form.cleaned_data['contact2_last_name'] # blank if omitted
):
contact2 = Contact(
student=student,
contact_first_name = form.cleaned_data['contact2_first_name'],
...
)
contact2.save()
return HttpResponseRedirect( ...)
If you want to do further validation beyond what's easy in a form definition you can. (You may well want to check that if conatct2_first_name is specified, contact2_last_name must also be specified).
def form_valid( self, form):
# extra validations, add errors on fail
n=0
if form.cleaned_data['contact2_first_name']:
n+=1
if form.cleaned_data['contact2_last_name']:
n+=1
if n==1:
form.add_error('contact2_first_name',
'Must provide first and last names for contact2, or omit both for no second contact')
form.add_error('contact2_last_name',
'Must provide first and last names for contact2, or omit both for no second contact')
contact2_provided = (n != 0)
...
if not form.is_valid():
return self.form_invalid( self, form)
with transaction.atomic():
student = form.save()
contact1 = ( ... # as before
if contact2_provided:
contact2 = ( ...
Thanks to #nigel222 I have come a long way in creating the form. However, the form did not save the data to the database properly, but I managed to change the view and the form a little bit and it works now.
This is a blueprint on how to create two objects in one form in Django. It creates one Student model (linked to a User model) and two Contact models (of which one is optional).
Forms.py:
class StudentSignUpForm(forms.ModelForm):
class Meta:
model = Student
fields = (
'username',
'first_name',
'last_name',
'year',
'school',
'student_email',
'account_status',
'phone_number',
'homework_coach',
'password1',
'password2',
'contact1_first_name',
'contact1_last_name',
'contact1_phone_number',
'contact1_email',
'contact1_street',
'contact1_street_number',
'contact1_zipcode',
'contact1_city',
'contact2_first_name',
'contact2_last_name',
'contact2_phone_number',
'contact2_email',
'contact2_street',
'contact2_street_number',
'contact2_zipcode',
'contact2_city',
)
# user
username = forms.CharField(label='Username', min_length=5, max_length=150)
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Confirm Password', widget=forms.PasswordInput)
# contact 1
contact1_first_name = forms.CharField(max_length=50, required=True)
contact1_last_name = forms.CharField(max_length=50, required=True)
contact1_phone_number = forms.CharField(max_length=50, required=False)
contact1_email = forms.EmailField(required=False) # not required because some students might not know contact information
contact1_street = forms.CharField(max_length=100, required=False)
contact1_street_number = forms.CharField(max_length=10, required=False)
contact1_zipcode = forms.CharField(max_length=10, required=False)
contact1_city = forms.CharField(max_length=100, required=False)
# contact 2
contact2_first_name = forms.CharField(max_length=50, required=False) # not required because second contact is optional
contact2_last_name = forms.CharField(max_length=50, required=False)
contact2_phone_number = forms.CharField(max_length=50, required=False)
contact2_email = forms.EmailField(required=False) # not required because some students might not know contact information
contact2_street = forms.CharField(max_length=100, required=False)
contact2_street_number = forms.CharField(max_length=10, required=False)
contact2_zipcode = forms.CharField(max_length=10, required=False)
contact2_city = forms.CharField(max_length=100, required=False)
def username_clean(self):
username = self.cleaned_data['username'].lower()
new = User.objects.filter(username = username)
if new.count():
raise ValidationError("User Already Exist")
return username
def clean_password2(self):
password1 = self.cleaned_data['password1']
password2 = self.cleaned_data['password2']
if password1 and password2 and password1 != password2:
raise ValidationError("Password don't match")
return password2
#transaction.atomic
def form_valid(self, form):
user = User.objects.create_user(
self.cleaned_data['username'],
self.cleaned_data['password1']
)
user.is_student = True
user.save()
student = form.save(commit=False)
student.user = user
student = form.save()
contact1 = Contact(
student = student,
contact_first_name = form.cleaned_data['contact1_first_name'],
contact_last_name = form.cleaned_data['contact1_last_name'],
contact_phone_number = form.cleaned_data['contact1_phone_number'],
contact_email = form.cleaned_data['contact1_email'],
contact_street = form.cleaned_data['contact1_street'],
contact_street_number = form.cleaned_data['contact1_street_number'],
contact_zipcode = form.cleaned_data['contact1_zipcode'],
contact_city = form.cleaned_data['contact1_city'],
)
contact1.save()
if (form.cleaned_data['contact2_first_name'] and
form.cleaned_data['contact2_last_name'] # blank if omitted
):
contact2 = Contact(
student=student,
contact_first_name = form.cleaned_data['contact2_first_name'],
contact_last_name = form.cleaned_data['contact2_last_name'],
contact_phone_number = form.cleaned_data['contact2_phone_number'],
contact_email = form.cleaned_data['contact2_email'],
contact_street = form.cleaned_data['contact2_street'],
contact_street_number = form.cleaned_data['contact2_street_number'],
contact_zipcode = form.cleaned_data['contact2_zipcode'],
contact_city = form.cleaned_data['contact2_city'],
)
contact2.save()
return redirect('home')
Models.py:
class Student(models.Model):
ACCOUNT_STATUS_CHOICES = (
('A', 'Active'),
('S', 'Suspended'),
('D', 'Deactivated'),
)
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
year = models.ForeignKey(Year, on_delete=models.SET_NULL, null=True, blank=True, default='')
school = models.ForeignKey(School, on_delete=models.SET_NULL, null=True, blank=True, default='')
student_email = models.EmailField() # named student_email because email conflicts with user email
account_status = models.CharField(max_length=1, choices=ACCOUNT_STATUS_CHOICES, default='A')
phone_number = models.CharField(max_length=50)
homework_coach = models.ForeignKey(Teacher, on_delete=models.SET_NULL, null=True, blank=True, default='')
user = models.OneToOneField(User, on_delete=models.CASCADE, null=True)
plannings = models.ForeignKey(Planning, on_delete=models.SET_NULL, null=True)
def __str__(self):
return f"{self.first_name} {self.last_name}"
class Contact(models.Model):
student = models.ForeignKey(Student, on_delete=models.CASCADE)
contact_first_name = models.CharField(max_length=50)
contact_last_name = models.CharField(max_length=50)
contact_phone_number = models.CharField(max_length=50)
contact_email = models.EmailField()
contact_street = models.CharField(max_length=100)
contact_street_number = models.CharField(max_length=10)
contact_zipcode = models.CharField(max_length=30)
contact_city = models.CharField(max_length=100)
def __str__(self):
return f"{self.contact_first_name} {self.contact_last_name}"
Urls.py:
urlpatters = [
path('signup/student/', views.student_signup, name='student_signup'),
]
Views.py:
def student_signup(request):
if request.method == 'POST':
student_signup_form = StudentSignUpForm(request.POST)
if student_signup_form.is_valid():
student_signup_form.form_valid(student_signup_form)
return redirect('home')
else:
return HttpResponse("Form is not valid")
else:
student_signup_form = StudentSignUpForm()
return render(request, 'registration/signup_form.html', {'student_signup_form': student_signup_form})
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})
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.