Related
I've created models in a Django project, one of which is an extended User model. Initially, I was creating a user through 2 forms, UserCreationForm and EmployeeForm based of a ModelForm, then using a function based view to validate the data and save it. It all worked fine until I tried to introduce the third form and wanted to use the CreateView.
Here are the models:
class Employee(models.Model):
SENIOR = 'Sr'
JUNIOR = 'Jr'
FIRST = 'I'
SECOND = 'II'
THIRD = 'III'
GENERATIONAL_SUFFIX = [
(SENIOR, 'Senior'),
(JUNIOR, 'Junior'),
(FIRST, 'First'),
(SECOND, 'Second'),
(THIRD, 'Third'),
]
MALE = 'male'
FEMALE = 'female'
OTHER = 'other'
SEX = [
(MALE, 'Male'),
(FEMALE, 'Female'),
(OTHER, 'Other'),
]
user = models.OneToOneField(User, on_delete=models.CASCADE)
phone_regex = RegexValidator(regex=r'^\d{11}$', message="Phone number must be entered in the format: '09151234567'.")
phone_number = models.CharField(validators=[phone_regex], max_length=11, blank=True)
middle_name = models.CharField(max_length=20, blank=True)
sex = models.CharField(max_length=6, choices=SEX, blank=True)
suffix = models.CharField(max_length=3, choices=GENERATIONAL_SUFFIX, blank=True)
birthday = models.DateField(null=True, blank=True)
hire_date = models.DateField(null=True, blank=True)
image = models.ImageField(blank=True, default='blank_profile_picture.jpg')
slug = models.SlugField(max_length=60, blank=True, null=True)
updated = models.DateTimeField(auto_now=True)
#property
def get_full_name(self):
first_name = self.user.first_name
middle_name = self.middle_name
last_name = self.user.last_name
if middle_name is None:
full_name = f'{first_name}{" "}{last_name}'
return full_name
else:
full_name = f'{first_name}{" "}{middle_name}{" "}{last_name}'
return full_name
def save(self, *args, **kwargs):
self.slug = slugify(self.get_full_name)
super().save(*args, **kwargs)
def __str__(self):
return self.get_full_name
class EmployeePosition(models.Model):
employee = models.ForeignKey(Employee, on_delete=models.CASCADE)
position = models.ForeignKey(Position, on_delete=models.CASCADE)
position_change_reason = models.ForeignKey(PositionChangeReason, on_delete=models.CASCADE, default='Hired As')
effective_date = models.DateField()
def __str__(self):
return str(self.position)
Here are the 3 forms:
class EmployeeRegistrationForm(UserCreationForm):
email = forms.EmailField(required=True, widget=forms.EmailInput(attrs={'class': 'form-control mb-2',
'placeholder': 'juandelacruz#email.com'}))
first_name = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-control mb-2', 'placeholder': 'Juan'}))
last_name = forms.CharField(
widget=forms.TextInput(attrs={'class': 'form-control mb-2', 'placeholder': 'Dela Cruz'}))
password1 = None
password2 = None
class Meta:
model = User
fields = ['email', 'first_name', 'last_name']
def clean(self):
password = User.objects.make_random_password(length=10,
allowed_chars='abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789')
self.cleaned_data['password1'] = password
self.cleaned_data['password2'] = password
return super().clean()
def save(self, commit=True):
user = super().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.is_active = False
if len(user.first_name.split()) and len(user.last_name.split()) > 1:
username = f'{"".join(user.first_name.split()[:2])}{"."}{"".join(user.last_name.split())}'
elif len(user.first_name.split()) > 1:
username = f'{"".join(user.first_name.split()[:2])}{"."}{user.last_name}'
elif len(user.last_name.split()) > 1:
username = f'{user.first_name}{"."}{"".join(user.last_name.split())}'
else:
username = f'{user.first_name}{"."}{user.last_name}'
username = username.lower()
user.username = username
user.set_password(self.cleaned_data['password1'])
if commit:
user.save()
return user
class EmployeeForm(forms.ModelForm):
class Meta:
model = Employee
fields = ['phone_number', 'middle_name', 'sex', 'suffix', 'birthday', 'hire_date']
widgets = {
'phone_number': forms.TextInput(attrs={'class': 'form-control mb-2', 'placeholder': '09151234567'}),
'middle_name': forms.TextInput(attrs={'class': 'form-control mb-2', 'placeholder': 'Rodriguez'}),
'suffix': forms.Select(attrs={'class': 'form-select mb-2'}),
'sex': forms.Select(attrs={'class': 'form-select mb-2'}),
'birthday': forms.DateInput(attrs={'type': 'date', 'class': 'form-control mb-2'}, format='%m/%d/%Y'),
'hire_date': forms.DateInput(attrs={'type': 'date', 'class': 'form-control mb-2'}, format='%m/%d/%Y'),
}
class EmployeePositionForm(forms.ModelForm):
position_change_reason = forms.Select()
effective_date = forms.DateField()
class Meta:
model = EmployeePosition
fields = ['employee', 'position', 'position_change_reason', 'effective_date']
widgets = {
'position': forms.Select(attrs={'class': 'form-select mb-2', 'id': 'position'}),
}
def check_position_change_reason(self):
position_change_reason = self.cleaned_data['position_change_reason']
if not position_change_reason:
position_change_reason = EmployeePosition.position_change_reason.get_default()
return position_change_reason
def check_effective_date(self):
effective_date = self.cleaned_data['effective_date']
if not effective_date:
effective_date = Employee.hire_date
return effective_date
def save(self, commit=True):
position = super().save(commit=False)
position.position_change_reason = self.cleaned_data['position_change_reason']
position.effective_date = self.cleaned_data['effective_date']
position.position = self.cleaned_data['position']
return position
In the third form, I tried to set default values for two fields in case user doesn't enter them.
Here's how the view looks like:
class RegisterEmployeeView(LoginRequiredMixin, CreateView):
model = User
form_class = EmployeeRegistrationForm
profile_form_class = EmployeeForm
position_form_class = EmployeePositionForm
template_name = 'accounts/register.html'
success_url = '/'
def get(self, request, *args, **kwargs):
form = self.form_class(**self.get_form_kwargs())
profile_form = self.profile_form_class(prefix='profile_form')
position_form = self.position_form_class(prefix='position_form')
return render(request, self.template_name,
{'form': form, 'profile_form': profile_form, 'position_form': position_form})
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
profile_form = self.profile_form_class(request.POST)
position_form = self.position_form_class(request.POST)
if form.is_valid() and profile_form.is_valid() and position_form.is_valid():
user = form.save()
profile = profile_form.save(commit=False)
position_profile = position_form.save(commit=False)
profile.user = user
position_profile.employee = profile.employee
profile.save()
position_profile.save()
messages.success(self.request, f'{User.first_name}{" "}{User.last_name}{" was registered successfully."}')
return HttpResponseRedirect(self.get_success_url())
else:
context = {'form': form, 'profile_form': profile_form, 'position_form': position_form}
return render(request, self.template_name, context)
I've read dozens of articles here and other sites that have similar issues, but couldn't work it out. It seems similar to what Risadinha said here: "it's not saving and not redirecting" := that is what happens when there is a validation error. But I can't wrap my head around this as I'm still learning Django.
Update:
I've followed Iain's suggestion to subclass the form as I'm planning to re-use the form. Would this be the right way to subclass it?
class EmployeeInitialPositionForm(EmployeePositionForm):
class Meta:
model = EmployeePosition
exclude = ['employee']
I am building a hospital management app and I am currently building the Nurse's webpage. In that webpage, I would like the following to display: a list of all employed nurses, a list of their workshifts, and what departments they work for.
I am trying to get the department section to display but I keep getting an error "too many values to unpack (expected 2)".
What can I do so that the nurses' department shows?
Models.py
from django.db import models
# Create your models here.
#Work Related aka Department and Work Shift
class Department(models.Model):
name = models.CharField(max_length=200, null=True, blank=True)
def __str__(self):
return self.name
class WorkShift(models.Model):
name = models.CharField(max_length=200, null=True, blank=True)
start_datetime = models.DateTimeField(null=True, blank=True)
end_datetime = models.DateTimeField(null=True, blank=True)
def __str__(self):
return self.name
#Personel Related aka Employees and Patients
class Doctor(models.Model):
name = models.CharField(max_length=200, null=True, blank=True)
email = models.CharField(max_length=200, null=True)
phone = models.CharField(max_length=200, null=True)
department = models.ForeignKey(Department, null=True, blank=True, on_delete=models.CASCADE)
work_shift = models.OneToOneField(WorkShift, blank=True, null=True, on_delete=models.CASCADE)
def __str__(self):
return self.name
class Nurse(models.Model):
name = models.CharField(max_length=200, null=True)
email = models.CharField(max_length=200, null=True)
phone = models.CharField(max_length=200, null=True)
sector = models.ForeignKey(Department, null=True, blank=True, on_delete=models.CASCADE)
reports_to = models.ForeignKey(Doctor, blank=True, null=True, on_delete=models.CASCADE)
work_shift = models.OneToOneField(WorkShift, default="", blank=True, null=True, on_delete=models.CASCADE)
def __str__(self):
return self.name
class Patient(models.Model):
STATUS = (
('Sick', 'Sick'),
('Healing', 'Healing'),
('Cured', 'Cured'),
('Deceased', 'Deceased'),
)
name = models.CharField(max_length=200, null=True, blank=True)
description = models.TextField(blank=True, null=True)
status = models.CharField(max_length=200, null=True, blank=True, choices=STATUS)
department = models.ForeignKey(Department, default="", null=True, blank=True, on_delete=models.CASCADE)
care = models.ForeignKey(Nurse, default="", blank=True, null=True, on_delete=models.CASCADE)
date_created = models.DateTimeField(auto_now_add=True, blank=True, null=True)
def __str__(self):
return self.name
from django.shortcuts import render, redirect
Views.py
# Create your views here.
from django.shortcuts import render
from .models import Doctor, Nurse, Patient, Department, WorkShift
from django.http import HttpResponse
from .forms import DoctorForm, NurseForm, PatientForm
# Create your views here.
def index(request):
patient = Patient.objects.all()
nurse = Nurse.objects.all()
doctor = Doctor.objects.all()
department = Department.objects.all()
total_patient = patient.count()
sick = patient.filter(status='Sick').count()
healing = patient.filter(status='Healing').count()
cured = patient.filter(status='Cured').count()
total_nurse = nurse.count()
# if request.method == 'POST':
# form =
context = {
'patient':patient, 'nurse':nurse,
'doctor':doctor, 'total_patient':total_patient,
'sick':sick, 'healing':healing, 'cured':cured,
'total_nurse':total_nurse,
'department':department
}
return render(request, 'lifesaver/index.html', context)
#All Patient Related
def patient(request):
patient = Patient.objects.all()
context = {'patient':patient}
return render(request, 'lifesaver/patient.html', context)
def patient_add(request):
patient = Patient.objects.all()
form = PatientForm()
if request.method == 'POST':
form = PatientForm(request.POST)
if form.is_valid():
print("Patient Form is Valid")
form.save()
else:
print("Patient Form is Invalid")
print(form.errors)
return redirect('patient')
context = {'form':form,}
return render(request, 'lifesaver/patient_add.html', context)
def patient_update(request, pk):
patient = Patient.objects.get(id=pk)
form = PatientForm(instance=patient)
if request.method == 'POST':
form = PatientForm(request.POST, instance=patient)
if form.is_valid():
print('Update completed')
form.save()
return redirect('patient')
else:
print('Update not completed')
print(form.errors)
context = {'form':form}
return render(request, 'lifesaver/patient_update.html', context)
#All Doctor Related
def doctor(request):
doctor = Doctor.object.all()
context = {}
return render(request, 'lifesaver/doctor.html', context)
def doctor_add(request):
doctor = Doctor.object.all()
form = DoctorForm()
context = {'doctor':doctor, 'form':form}
return render(request, 'lifesaver/doctor')
def doctor_update(request):
doctor = Doctor.object.all()
form = DoctorForm()
context = {'doctor':doctor, 'form':form}
# Nurse Related
def nurse(request):
nurse = Nurse.objects.all()
workshift = WorkShift.objects.all()
department = Nurse.objects.get('sector')
context = {'nurse':nurse, 'workshift':workshift, 'department':department}
return render(request, 'lifesaver/nurse.html', context)
def nurse_add(request):
nurse = Nurse.objects.all()
form = NurseForm()
if request.method == 'POST':
form = NurseForm(request.POST)
if form.is_valid():
print("Nurse Form is Valid")
form.save()
else:
print("Nurse Form is Invalid")
print(form.errors)
return redirect('nurse')
context = {'form':form,}
return render(request, 'lifesaver/nurse_add.html', context)
def nurse_update(request):
nurse = Nurse.objects.all()
form = NurseForm()
context = {}
return render(request, 'lifesaver/nurse_update.html', context)
#Work Related
def department(request):
department = Department.objects.all()
context = {'department':department}
return render(request, 'lifesaver/department.html', context)
Forms.py
from django import forms
from django.forms import ModelForm
from .models import Doctor, Nurse, Patient, Department, WorkShift
from django.contrib.auth.forms import UserCreationForm
class DoctorForm(forms.ModelForm):
name = forms.CharField(widget = forms.TextInput(attrs =
{
'placeholder': 'Add a New Doctor',
'class': 'form-control'
}
))
department = forms.ModelChoiceField(queryset=Department.objects.all(), widget=forms.Select(attrs=
{
'class': 'selectpicker',
'placeholder': 'Department',
}
))
class Meta:
model = Doctor
fields = ['name', 'department']
class NurseForm(forms.ModelForm):
name = forms.CharField(widget = forms.TextInput(attrs =
{
'placeholder': 'Add a New Nurse',
'class': 'form-control'
}
))
class Meta:
model = Nurse
fields = ['name']
class PatientForm(ModelForm):
name = forms.CharField(widget = forms.TextInput(attrs =
{
'placeholder': 'Add a New Nurse',
'class': 'form-control'
}
))
description = forms.CharField(widget = forms.TextInput(attrs =
{
'placeholder': "Describe the patient's symptoms",
'class': 'form-control'
}
))
department = forms.ModelChoiceField(queryset=Department.objects.all(), widget=forms.Select(attrs=
{
'class': 'selectpicker',
'placeholder': 'Select Department',
}
))
class Meta:
model = Patient
fields = ['name', 'description', 'department', 'care', 'status']
#Work Related
class WorkShiftForm(ModelForm):
class Meta:
model = WorkShift
fields = '__all__'
Nurse.html
{% extends 'lifesaver/main.html' %}
{% block content %}
{% for nurse in nurse %}
{{nurse.name}}
{{nurse.report_to}}
{{nurse.care}}
{{nurse.work_shift}}
{{department}}
{% endfor %}
{% endblock %}
In models.py, Nurse object has field 'sector' which is a Foreign Key to a Department record. So part of the problem is you're trying to output the wrong field name in your template as there is no actual department field defined on Nurse model.
Try these edits to views.py:
nurses = Nurse.objects.all()
then in your context: context = {..., 'nurses': nurses, ...}
Then in nurse.html:
{% for nurse in nurses: %}
...
{{ nurse.sector.name }}
{% endfor %}
That should at least get your nurse objects rendered in the template. But you have a potential issue in calling nurse.sector when that FK is defined in the Nurse model with null=True. So a better practice would be to define an accessor method in the Nurse model to check if sector is present before calling it's name, i.e.:
# in Nurse model
def department_name(self):
if self.sector_id:
return self.sector.name
else:
return '' # or some other default
Then you could edit nurse.html again replacing my code above with:
{% for nurse in nurses: %}
...
{{ nurse.department_name }}
{% endfor %}
This is just scratching the surface of how you could handle this but it hopefully answers your question and prevents a common error once you make these edits.
You'll also probably want to look into Django QuerySet API's select_related() and prefetch_related() methods to avoid N+1 query issues that are possible in your current code. See here and here for more background.
So for example, to avoid N+1, instead of calling nurses = Nurse.objects.all() instead do nurses = Nurse.objects.select_related('sector').all(). That will do a join to the Department model on the FK. This answer to one of the above N+1 questions has more details.
you need to pass a field and a value, e.g.
Nurse.objects.get('sector' = 'dentistry')
or if you want to display a specific nurses department you would use this in your template:
{{nurse.department.name}}
I've created an orderform and was trying to extract information from the form. However, each time when i called for forms.get("firstname") or anything, i will face the error that the object has no attribute 'get" even though it is a form. more specifically, the error is "AttributeError: 'OrderForm' object has no attribute 'get'"
Here is the relevant code:
in models.py:
class BaseModel(models.Model):
eid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
date_created = models.DateTimeField(auto_now_add=True, db_index=True)
class Meta: abstract = True
#classmethod
def get_or_none(cls, **kwargs):
try:
return cls.objects.get(**kwargs)
except cls.DoesNotExist:
return None
class Order(BaseModel):
itemname = models.CharField(max_length =100, default="")
firstname = models.CharField(max_length = 20)
lastname = models.CharField(max_length = 20)
email = models.EmailField()
phone = PhoneNumberField(null=False, blank=False)
comments = models.TextField()
delivery = models.BooleanField(default=False)
def __str__(self):
return str(self.eid)
in forms.py:
class OrderForm(forms.ModelForm):
itemname = forms.ModelMultipleChoiceField(queryset=Post.objects.filter(title__contains="Bae"), required=True)
class Meta:
model = Order
fields = ('itemname', 'firstname', 'lastname', 'email', 'phone','delivery', 'comments')
labels = {'itemname': 'Order Item', 'firstname': 'First Name', 'lastname':"Last Name", 'email':"Email", 'phone':"Phone Number", 'delivery':'Deliver?', 'comments':'Comments'}
in views.py. This is where the error occurs:
def order(request):
if request.method == "POST":
form = OrderForm(request.POST)
if form.is_valid():
order = form.save(commit=False)
item_selected = form.get('itemname')
order.itemname = item_selected
order.save()
return render(request, 'Reddit_app/order_thankyou.html')
else:
form = OrderForm()
return render(request, 'Reddit_app/order_from_post.html', {"form": form})
finally, the order html code is :
<form method="POST" class="post-form">{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="save btn btn-primary">Submit</button>
</form>
item_selected = form.cleaned_data.get('itemname')
if you want to access data from form you need to access cleaned_data after the is_valid function is invoked
People, please help me :)
I have 2 class :
In first we can sign to the edition - name, surname, phone, mail.
In second we can display form with number edition and users who sign to sth edition.
I want display only 'publish' number edition in template.
In page we can choice edition (drop-down list /multiple), write name etc and save to this edition..
I know I write awfully, but maybe U understand..
models:
class Signup(models.Model):
name = models.CharField(max_length=30, verbose_name='Imię',)
surname = models.CharField(max_length=30, verbose_name='Nazwisko', blank=True, null=True)
phone = models.CharField(max_length=20, verbose_name='Numer telefonu', blank=True, null=True)
mail = models.EmailField(verbose_name="Email", max_length=254, blank=True, null=True)
home = models.CharField(max_length=40, verbose_name='Miejsce zamieszkania', blank=True, null=True)
nr_edition = models.ManyToManyField('Edition', verbose_name='Edycja', blank=True, null=True,)
class Meta:
verbose_name = "Uczestnik"
verbose_name_plural = "Uczestnicy"
def __unicode__(self):
return u'%s %s' % (self.name, self.surname)
class PublishedEditManager(models.Manager):
def get_query_set(self):
return super(PublishedEditManager, self).get_query_set().filter(published=True)
class Edition(models.Model):
name_edit = models.CharField('Nazwa edycji', max_length=100)
slug = models.SlugField('Odnośnik', unique=True, max_length=100)
# new_user = formset_factory(ContactForm)
published = models.BooleanField('Opublikowany', blank=True)
objects = models.Manager()
published_edition = PublishedEditManager()
class Meta:
verbose_name = "Numer edycji"
verbose_name_plural = "Numery edycji"
def __unicode__(self):
return self.name_edit
def get_absolute_url(self):
return u'%s' % self.name_edit
forms
class ContactForm(forms.Form):
name = forms.CharField()
surname = forms.CharField()
phone = forms.CharField()
mail = forms.EmailField()
nr_edition = forms.ModelMultipleChoiceField
def is_valid(self):
vf = forms.Form.is_valid(self)
for f in self.errors:
self.fields[f].widget.attrs.update({'class': 'errorlist'})
return vf
def clean(self):
cleaned_data = super(ContactForm, self).clean()
return cleaned_data
ContactFormSet = formset_factory(ContactForm)
view
def about_alfa(request):
c = {}
c['about_alfa'] = True
c['request'] = request
if request.method == 'POST': # If the form has been submitted...
form = ContactForm(request.POST, request.FILES) # A form bound to the POST data
ContactFormSet = formset_factory(ContactForm)
if form.is_valid(): # All validation rules pass
name = form.cleaned_data['name']
surname = form.cleaned_data['surname']
phone = form.cleaned_data['phone']
mail = form.cleaned_data['mail']
nr_edition = form.cleaned_data['nr_edycji']
id_model = Signup.objects.create(
name=name,
surname=surname,
phone=phone,
mail=mail,
nr_edycji=nr_edition
)
c['form'] = form
c['send']= True
# print sendimage
text = u'Imię: %s \n' \
u'Nazwisko: %s \n' \
u'Telefon: %s \n' \
u'Mail: %s \n' % (name, surname, phone, mail)
html = u'<p>Imię: <strong>%s</strong></p>' \
u'<p>Nazwisko: <strong>%s</strong></p>' \
u'<p>Telefon: <strong>%s</strong></p>' \
u'<p>Mail: <strong>%s</strong></p>' % (name, surname, phone, mail)
sendMailTemplate(['dp#asd.pl'], 'Nowa osoba zapisała się ne Alfe.', text, html, copy=False,
)
return render(request, 'about_alfa.html', c)
else:
c['form'] = form
return render(request, 'about_alfa.html', c)
else:
c['form'] = ContactForm()
return render_to_response('about_alfa.html', c, context_instance=RequestContext(request))
Edit
models
Nothing change
forms
I delete first part and this is result:
class ContactForm(forms.ModelForm):
class Meta:
model = Signup
nr_edition = forms.ModelMultipleChoiceField(queryset=Edition.objects.all())
def save(self):
signup = forms.ModelForm.save(self)
for edition in self.cleaned_data['nr_edition']:
signup.edition_set.add(edition)
def clean(self):
cleaned_data = super(ContactForm, self).clean()
return cleaned_data
ContactFormSet = formset_factory(ContactForm)
view
I delete almost all and :
def about_alfa(request):
c = {}
c['about_alfa'] = True
c['request'] = request
if request.method == 'POST': # If the form has been submitted...
form = ContactForm(request.POST, request.FILES) # A form bound to the POST data
ContactFormSet = formset_factory(ContactForm)
if form.is_valid():
form.save()
return render_to_response('about_alfa.html', c, context_instance=RequestContext(request))
Edit 2
I have no errors but i dont see any field in template (only submit^^).. ?
Use ModelForm with ModelMultipleChoiceField:
class ContactForm(forms.ModelForm):
class Meta:
model = Signup
nr_edition = forms.ModelMultipleChoiceField(queryset=Edition.objects.all())
def save(self):
signup = forms.ModelForm.save(self)
for edition in self.cleaned_data['nr_edition']:
signup.edition_set.add(edition)
And in your view you just save the form:
if form.is_valid():
form.save()
and in template:
<form action="{% url "viewname" %}" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
Edit:
To use formset with ModelForm, you must use modelformset_factory, see docs, not formset_factory
ContactFormSet = modelformset_factory(Signup, form=ContactForm)
Also, you are instantiating ContactForm, you must instead instantiate ContactFormSet with request.POST..
So the view will be like this:
def about_alfa(request):
c = {}
c['about_alfa'] = True
c['request'] = request
ContactFormSet = modelformset_factory(Signup, form=ContactForm)
if request.method == 'POST':
formset = ContactFormSet(request.POST, request.FILES)
if formset.is_valid():
formset.save()
else:
c['form'] = formset
else:
c['form'] = ContactFormSet()
return render_to_response('about_alfa.html', c, context_instance=RequestContext(request))
i am using Django form module to get value and pass it to user profile.
The only problem is that the home_type is a "forms.ChoiceField" but there is no "clean_data" type for the forms.ChoiceField, so how can i get the radio select value and pass it to the user profile module?
the code of module is like this:
class UserProfile(models.Model):
user = models.OneToOneField(User)
name = models.CharField(max_length=30, blank=True)
productNo = models.CharField(max_length=50, blank=True)
location = models.CharField(max_length=50, blank=True)
average_temp = models.CharField(max_length=5, blank=True)
HOME_TYPE = (
('AP', 'Apartment/Condo'),
('SH', 'Single House/Residential'),
('ST', 'Studio'),
('TH', 'Townhouse'),
('MH', 'Moblie Home'),
)
home_type = models.CharField(max_length=1, choices=HOME_TYPE)
and the code of form:
class UserProfileForm(forms.Form):
name = forms.CharField(label="Name", max_length=30, widget=forms.TextInput(attrs={'size': 20,}))
productNo = forms.CharField(label="ProductNo", max_length=50, widget=forms.TextInput(attrs={'size': 20,}))
location = forms.CharField(label="Location", max_length=50, widget=forms.TextInput(attrs={'size': 20,}))
average_temp = forms.CharField(label="Average_Temp", max_length=10, widget=forms.TextInput(attrs={'size': 20,}))
HOME_TYPE = (
('AP', 'Apartment/Condo'),
('SH', 'Single House/Residential'),
('ST', 'Studio'),
('TH', 'Townhouse'),
('MH', 'Moblie Home'),
)
home_type = forms.ChoiceField(label="home_type", widget=forms.RadioSelect(), choices=HOME_TYPE)
In my view.py, the code to deal with the value passing is:
def user_profile_update(request):
if not request.user.is_authenticated():
return HttpResponseRedirect('/keenhome/accounts/login/')
UserProfile = request.user.get_profile()
if request.method == 'POST':
form=UserProfileForm(request.POST)
if form.is_valid():
UserProfile.name = form.cleaned_data["name"]
UserProfile.productNo = form.cleaned_data["productNo"]
UserProfile.location = form.cleaned_data["location"]
UserProfile.average_temp = form.cleaned_data["average_temp"]
#problem happens here:
UserProfile.home_type = form.cleaned_data["home_type"]
UserProfile.save()
return HttpResponseRedirect('/keenhome/accounts/user_profile/')
else:
form = UserProfileForm()
return render_to_response("polls/user_profile_update.html", {'form':form}, context_instance=RequestContext(request))
else:
form = UserProfileForm()
return render_to_response("polls/user_profile_update.html", {'form':form}, context_instance=RequestContext(request))
The only problem is that there is no "clean_data" type for the forms.ChoiceField, so how can i get the radio select value and pass it to the user profile module?
You don't need to write all fields of form again. That's why it's called ModelForm, it should be auto-generated from model:
HOME_TYPE = (
('AP', 'Apartment/Condo'),
('SH', 'Single House/Residential'),
('ST', 'Studio'),
('TH', 'Townhouse'),
('MH', 'Moblie Home'),
)
class UserProfile(models.Model):
user = models.OneToOneField(User)
name = models.CharField(max_length=30, blank=True)
productNo = models.CharField(max_length=50, blank=True)
location = models.CharField(max_length=50, blank=True)
average_temp = models.CharField(max_length=5, blank=True)
home_type = models.CharField(max_length=2, choices=HOME_TYPE)
forms.py:
class UserProfileForm(ModelForm):
class Meta:
model = UserProfile
exclude = (user,)
views.py:
def user_profile_update(request):
if not request.user.is_authenticated():
return HttpResponseRedirect('/keenhome/accounts/login/')
form = UserProfileForm(request.POST or None)
if request.method == 'POST':
if form.is_valid():
form.user = request.user
form.save()
return HttpResponseRedirect('/keenhome/accounts/user_profile/')
return render_to_response("polls/user_profile_update.html", {'form':form}, context_instance=RequestContext(request))
EDIT:
made max_length = 2, thanks #ndpu, excluded user, added user saving in form, thanks #void
class UserProfile(models.Model):
user = models.OneToOneField(User)
.....
class UserProfileForm(ModelForm):
pass
class Meta:
model = UserProfile
exclude = (user,) # you need to exclude user
Now all of this code...:
def user_profile_update(request):
if not request.user.is_authenticated():
return HttpResponseRedirect('/keenhome/accounts/login/')
UserProfile = request.user.get_profile()
if request.method == 'POST':
form=UserProfileForm(request.POST)
if form.is_valid():
UserProfile.name = form.cleaned_data["name"]
UserProfile.productNo = form.cleaned_data["productNo"]
UserProfile.location = form.cleaned_data["location"]
UserProfile.average_temp = form.cleaned_data["average_temp"]
#problem happens here:
UserProfile.home_type = form.cleaned_data["home_type"]
UserProfile.save()
return HttpResponseRedirect('/keenhome/accounts/user_profile/')
else:
form = UserProfileForm()
return render_to_response("polls/user_profile_update.html", {'form':form}, context_instance=RequestContext(request))
else:
form = UserProfileForm()
return render_to_response("polls/user_profile_update.html", {'form':form}, context_instance=RequestContext(request))
would have become:
def user_profile_update(request):
if not request.user.is_authenticated():
return HttpResponseRedirect('/keenhome/accounts/login/')
form = UserProfileForm(request.POST or None)
if form.is_valid():
form = form.save(commit=False)
form.user = request.user# because user is excluded
form.save()
#code
else:
#code
return render_to_response("polls/user_profile_update.html", {'form':form}, context_instance=RequestContext(request))
I think the problem is here:
class UserProfile(models.Model):
#...
home_type = models.CharField(max_length=1, choices=HOME_TYPE)
should be max_length=2:
home_type = models.CharField(max_length=2, choices=HOME_TYPE)