models.py:
from django.db import models
from django.contrib.auth.models import User as BaseUser
CHOICE_GENDER = ((1, 'Male'), (2, 'Female'))
class Location(models.Model):
city = models.CharField(max_length=75)
country = models.CharField(max_length=25)
def __str__(self):
return ', '.join([self.city, self.state])
class Users(BaseUser):
user = models.OneToOneField(BaseUser, on_delete=models.CASCADE)
gender = models.IntegerField(choices=CHOICE_GENDER)
birth = models.DateField()
location = models.ForeignKey(Location)
class Meta:
ordering = ('user',)
forms.py:
from django.contrib.auth.forms import UserCreationForm
from django import forms
from .models import Users, Location
class LocationForm(forms.ModelForm):
class Meta:
model = Location
fields = '__all__'
class RegistrationForm(UserCreationForm):
class Meta:
model = Users
fields = ('username', 'email', 'first_name', 'last_name', 'gender', 'birth', 'location')
views.py:
def signup(request):
if request.method == "POST":
reg_form = forms.RegistrationForm(request.POST)
loc_form = forms.LocationForm(request.POST)
if loc_form.is_valid():
reg_form.location = loc_form.save()
if reg_form.is_valid():
reg_form.save()
return redirect('./')
reg_form = forms.RegistrationForm()
loc_form = forms.LocationForm()
return render(request, 'signup.html', {'loc_form': loc_form, 'reg_form': reg_form})
I can't manage to make this work, it gives location - This field is required error. I've tried every combination in views.py, and it never passed the reg_form.is_valid() command due to that reason. Can anybody help me in this? Thanks in advance!
SOLVED: views.py new, working code:
def signup(request):
if request.method == "POST":
reg_form = forms.RegistrationForm(request.POST)
loc_form = forms.LocationForm(request.POST)
if reg_form.is_valid():
reg = reg_form.save(commit=False)
if loc_form.is_valid():
reg.location = loc_form.save()
reg.save()
return redirect('./')
reg_form = forms.RegistrationForm()
loc_form = forms.LocationForm()
return render(request, 'signup.html', {'loc_form': loc_form, 'reg_form': reg_form})
Removing location from RegistrationForm fields tuple should stop the behavior.
Since you are using a separate form for Location, you shouldn't populate location field using RegistrationForm.
Related
I'm using Django's CreateView in order to fill a form and I want some of the fields to be automatically filled in, looking for ides how I could that. the fields that I want to be filled in automatically are company, recruiter and date
this is what the views file looks like:
class CreateNewJobForm(CreateView):
model = Job
fields = (
'title', 'company', 'recruiter', 'job_type', 'work_from', 'description', 'city', 'address', 'title_keywords',
'date_created')
template_name = 'create_new_job_form.html'
success_url = '/job_created_successfully'
def form_valid(self, form):
form.instance.recruiter = self.get_name()
return super(CreateNewJobForm, self).form_valid(form)
and this is what the models file looks like:
class Recruiter(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, primary_key=True)
name = models.CharField(max_length=255)
company = models.ForeignKey(Company, on_delete=models.RESTRICT, related_name='recruiters')
email = models.EmailField(max_length=255)
phone_number = models.CharField(max_length=15, blank=True)
Something like that should work just fine :
def form_valid(self, form):
form.instance.user = self.request.user # assuming you want the current login user to be set to the user
return super(CreateNewJobForm, self).form_valid(form)
It is just an example but in short you can access attributes of your model by accessing the instance of your form like that form.instance.yourfield
Automatically assign the value
We can assign a value without showing this in the form. In that case, you remove the company, recruiter, and date_created fields from the fields, and fill these in in the form_valid method:
from django.contrib.auth.mixins import LoginRequiredMixin
class CreateNewJobForm(LoginRequiredMixin, CreateView):
model = Job
fields = ('title', 'job_type', 'work_from', 'description', 'city', 'address', 'title_keywords')
template_name = 'create_new_job_form.html'
success_url = '/job_created_successfully'
def form_valid(self, form):
recruiter = form.instance.recruiter = self.request.user.recruiter
form.instance.company_id = recruiter.company_id
return super().form_valid(form)
for the date_created, you can work with the auto_now_add=True parameter [Django-doc] of the DateTimeField:
class Job(models.Model):
# …
date_created = models.DateTimeField(auto_now_add=True)
Provide an initial value
We can also provide an initial value for the form by overriding the .get_initial() method [Django-doc]:
from django.contrib.auth.mixins import LoginRequiredMixin
from django.utils.timezone import now
class CreateNewJobForm(LoginRequiredMixin, CreateView):
model = Job
fields = ('title', 'job_type', 'work_from', 'description', 'city', 'address', 'title_keywords', 'company', 'recruiter', 'date_created')
template_name = 'create_new_job_form.html'
success_url = '/job_created_successfully'
def get_initial(self):
recruiter = self.request.user.recruiter
return {
'recruiter': recruiter,
'company': recruiter.company,
'date_created': now()
}
Can someone help me with code for forms.py views.py and urls?
views.py
def PasswordRecover(request):
if request.method=='POST':
form=UserGet(request.POST)
user= form.save(commit=False)
if(user.is_active):
return redirect('password_reset/security',pk=user.pk)
else:
form = UserGet()
return render(request, 'passwordreset.html', {'form':form})
def Security(request):
return HttpResponse('what do we add here??')
forms.py:
class UserGet(forms.ModelForm):
class Meta:
model = CustomUser
fields = ('username',)
urls.py:
from django.urls import path
from . import views
app_name='users'
urlpatterns = [
path('signup/', views.SignUp.as_view(), name='signup'),
path('password_reset',views.PasswordRecover,name='password_recovery'),
path('password_reset/security',views.Security,name='SecurityRecover'),
]
Error I am getting:
Exception Value:The CustomUser could not be created because the data didn't validate.
custom user Model:
class CustomUser(AbstractUser):
# First/last name is not a global-friendly pattern
name = models.CharField(blank=True, max_length=255)
MALE = 'M'
FEMALE = 'F'
GENDER_CHOICES=(
(MALE,'Male'),
(FEMALE,'Female'),
)
gender = models.CharField(max_length=1,choices=GENDER_CHOICES,default=MALE)
bio = models.CharField(max_length=255,blank=True)
DOG = 'DOG'
PHONE = 'PHONE'
USER_QUESTIONS = (
(DOG, 'Dog'),
(PHONE, 'Phone'),
)
user_questions = models.CharField(max_length=255,choices=USER_QUESTIONS, default=DOG)
answer = models.CharField(max_length=255,blank=True)
def __str__(self):
return self.email
Signup view:
class SignUp(generic.CreateView):
form_class = CustomUserCreationForm
success_url = reverse_lazy('login')
template_name = 'signup.html'
forms.py:
from django import forms
from django.contrib.auth.forms import UserCreationForm, UserChangeForm, UsernameField
from .models import CustomUser
class CustomUserCreationForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
model = CustomUser
fields = ('username', 'email', 'gender', 'user_questions', 'answer')
class CustomUserChangeForm(UserChangeForm):
class Meta:
model = CustomUser
fields = UserChangeForm.Meta.fields
This are my files. I don't know how do I proceed further
Answer for your error :
Before saving [user= form.save(commit=False)] the form you must validate the form.
Something like this :
if form.is_valid():
user= form.save(commit=False)
else:
render(request, 'passwordreset.html', {'form':form})
Suggestion regarding your security question query:
I think you can have two fields in CustomUser model, one for security question (Maybe based on options ?) and another one for user answer. Then based on your logic you can implement it in view. Or let me know your logic if you need my help there also.
I'm new in Django and I'm trying to pre fill one of the fields of my form with a slug.
I'm getting the slug from another model. I'm not using ForeignKey because that shows me a list with my objects and I want to save in the form the same slug that I'm using in the url.
Maybe I'm not thinking this right. What should I do?
Thank you!
This are my models:
from django.db import models
class Thing(models.Model):
name = models.CharField(max_length=255,)
rut = models.CharField(max_length=12, blank= True)
cel = models.CharField(max_length=12, blank= True)
slug = models.SlugField(unique=True)
class Control(models.Model):
id_p = models.SlugField()
pa = models.CharField(max_length=3,)
My forms
from django.forms import ModelForm
from collection.models import Thing, Control, Medicamento
class ThingForm(ModelForm):
class Meta:
model = Thing
fields = ('name', 'rut','cel','pet',)
class ControlForm(ModelForm):
class Meta:
model = Control
exclude = ['id_p']
This is what I'm doing in the views
def add_control(request, slug):
thing = Thing.objects.get(slug=slug)
form_class = ControlForm
form_class(initial={'id_p':thing})
if request.method == 'POST':
form = form_class(request.POST)
if form.is_valid():
form.save()
return redirect('thing_detail', slug=thing.slug)
else: form = form_class()
return render(request, 'things/control.html', {
'thing': thing,
'form': form,
})
So, I figure it out!
In views.py, after " if form.is_valid():"
I put this:
prev = form.save(commit=False)
prev.id_p = thing.slug
prev.save()
In that way I put the data in the excluded field before I commit the form.
models.py:
from django.db import models
from django.contrib.auth.models import User as BaseUser
CHOICE_GENDER = ((1, 'Male'), (2, 'Female'))
class Location(models.Model):
city = models.CharField(max_length=75)
country = models.CharField(max_length=25)
def __unicode__(self):
return ', '.join([self.city, self.state])
class Users(BaseUser):
user = models.OneToOneField(BaseUser, on_delete=models.CASCADE)
gender = models.IntegerField(choices=CHOICE_GENDER)
birth = models.DateField()
location = models.ForeignKey(Location)
class Meta:
ordering = ('user',)
forms.py:
from django.contrib.auth.forms import UserCreationForm
from django import forms
from .models import Users, Location, CHOICE_GENDER
class LocationForm(forms.ModelForm):
city = forms.CharField(max_length=75)
country = forms.CharField(max_length=25)
class Meta:
model = Location
fields = ('city', 'country',)
class RegistrationForm(UserCreationForm):
email = forms.CharField(max_length=75)
first_name = forms.CharField(max_length=30)
last_name = forms.CharField(max_length=30)
gender = forms.ChoiceField(choices=CHOICE_GENDER)
birth = forms.DateField()
location = LocationForm()
class Meta:
model = Users
fields = ('username', 'email', 'first_name', 'last_name', 'gender', 'birth')
def save(self, commit=True):
user = super(RegistrationForm, self).save(commit=False)
user.email = self.cleaned_data['email']
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.gender = self.cleaned_data['gender']
user.birth = self.cleaned_data['birth']
if commit:
user.save()
return user
This code in forms.py doesn't work. It doesn't save LocationForm due to these errors:
country - This field is required.
city - This field is required.
I've certainly did something wrong here, but I don't know exactly what. I admit that I've jumbled the code in forms.py, especially in the save method for RegistrationForm because I don't know how to properly invoke the creation of another form and how to make a connection between two of them. I searched the Internet but I couldn't find precise info about that, so I tried to improvise but I've failed, unfortunately.
Could someone help me with this? Thanks in advance!
UPDATE: views.py (currently):
def signup(request):
if request.method == "POST":
reg_form = RegistrationForm(request.POST)
loc_form = LocationForm(request.POST)
if reg_form.is_valid() and loc_form.is_valid():
location = loc_form.save()
reg_form.cleaned_data['location_id'] = location.id
registration = reg_form.save()
else:
pass
else:
reg_form = RegistrationForm()
loc_form = LocationForm()
return render(request, 'signup.html', {'loc_form': loc_form, 'reg_form':reg_form})
I've also modified forms.py but I still got the error from above.
Instead of using LocationForm inside RegistrationForm you can handle them seprately in your views.py it will result in a cleaner code and easy to handle.
if request.method == "POST":
reg_form = RegistrationForm(request.POST)
loc_form = LocationForm(request.POST)
if reg_form.is_valid() and loc_form.is_valid():
# since in your case they are dependent on each other
# save location form and get location object
location = loc_form.save()
# now you can use it in your reg_form
reg_form.cleaned_data['location_id'] = location.id
registration = reg_form.save()
else:
# no need to handle this case only for explanation
# use the forms, with valid post data initialized
# at the start of current if block
pass
else:
# create new forms for location and registration
reg_form = RegistrationForm()
loc_form = LocationForm()
return render(request, 'signup.html', {'loc_form': loc_form, 'reg_form':reg_form})
You can read here more on how to handle more than one nested forms in django docs.
I have 2 class from my model
class APPLICANT_DATA(models.Model):
FIRST_NAME= models.CharField(max_length=20)
LAST_NAME= models.CharField(max_length=20)
MIDDLE_NAME= models.CharField(max_length=20)
and
class Applicant_status(models.Model):
fkey = models.ForeignKey(APPLICANT_DATA)
COMMENTS = models.CharField(max_length=100, null=True)
date_of_app = models.DateTimeField(auto_now_add=True, blank=True)
how do i make my 'Applicant_status' to populate whenever a data in 'APPLICANT_DATA' is inserted?
Here is my views.py
def save_page(request):
form = application_form(request.POST)
if request.method == 'POST':
if form.is_valid():
emails = form.cleaned_data['EMAIL']
mail = EmailMessage("Your activation and application code is: asdasd, do not show this to anyone", to=[emails])
mail.send()
cde = form.save(commit=False)
applicant_status.objects.create(fk=cde.id)
cde.save()
return HttpResponseRedirect('verify')
else:
form = application_form()
return render(request, 'frontend/apply.html', {'form': form})`
EDIT: My forms.py
from django.forms import ModelForm
from django import forms
from .models import APPLICANT_DATA
from django.core.exceptions import ValidationError
from django.core.validators import RegexValidator
class application_form(ModelForm):
FIRST_NAME = forms.CharField( max_length=20, label = ("First Name"),
. . .
class Meta:
model = APPLICANT_DATA
fields = ('FIRST_NAME', 'LAST_NAME', 'MIDDLE_NAME', )
error is (1048, "Column 'fkey' cannot be null")
Sorry if this was a newbie question
Use django signals to achieve this. https://docs.djangoproject.com/en/1.8/topics/signals/
Or you can manually save Applicant_Status with fk set to Application_Data you have just received in your view.