I try to insert data in user model into other model by one to one relationship. In specific, I want insert username,email and password attributes of User into other models.In Addtional, I intend to create both User model and other model in one form. So, I override the save method in modelform. It works partially and be able to insert data in both models and databases, except throw a UNIQUE constraint failed: auth_user.username error.
In models.py
class Staff(models.Model):
yes_or_no = ((True, 'Yes'),(False, 'No'))
male_or_female = ((True,'Male'),(False,'Female'))
user = models.OneToOneField(User, unique=True)
gender = models.BooleanField(default = True, choices = male_or_female)
birthday = models.DateField(default =None,blank = False, null = False)
created = models.DateTimeField(default=datetime.now, blank=True)
authorized = models.BooleanField(default=False,choices = yes_or_no)
store_id = models.ForeignKey(Store,default=1)
#property
def name(self):
return self.user.username
#property
def email(self):
return self.user.email
#property
def password(self):
return self.user.password
#property
def first_name(self):
return self.user.first_name
#property
def last_name(self):
return self.user.last_name
def __str__(self):
return self.user.username
In forms.py
class StaffForm(forms.ModelForm):
name = forms.CharField(max_length=100)
email= forms.EmailField(max_length=100, required=True)
password = forms.CharField(max_length=50)
store_id = forms.ModelChoiceField(queryset = Store.objects.all(),empty_label="--------") # select values ?
first_name = forms.CharField(required = True,max_length=100)
last_name = forms.CharField(required = True,max_length=100)
class Meta:
model = Staff
fields = ('gender','birthday','authorized','store_id')
widgets = {'authorized':forms.RadioSelect,
'gender':forms.RadioSelect,
'birthday':SelectDateWidget(years=range(date.today().year-50,date.today().year))
}
def save(self,*args,**kwargs):
Staff = super(StaffForm,self).save(commit=False)
user = User.objects.create(
username=self.cleaned_data['name'],
first_name=self.cleaned_data['first_name'],
last_name = self.cleaned_data['last_name'],
email= self.cleaned_data['email'])
user.set_password(self.cleaned_data['password'])
if self.cleaned_data['authorized']:
user.is_staff = True
Staff.user = user
Staff.save()
In views.py
#login_required(login_url='/dataInfo/login/')
def createstaff(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = StaffForm(request.POST or None)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
form.save()
return HttpResponseRedirect('/dataInfo/staff_view/')
# if a GET (or any other method) we'll create a blank form
else:
form = StaffForm()
return render(request, 'dataInfo/create_staff.html', {'form': form})
Related
I am trying to create an address book website where logged in user is able to fill in a form and store contact information. I was able to implement the login and logout functionality. But the problem is that I am not able to set the username to current logged in user. Here is what I have implemented so far:
Models.py
class UserProfileInfo(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE,primary_key=True)
#additional
def __str__(self):
return self.user.usernname
class UserContacts(models.Model):
current_user = models.ForeignKey(User,on_delete=models.CASCADE)
first_name = models.CharField(max_length = 150)
last_name = models.CharField(max_length = 150)
phone_number = models.CharField(max_length = 150)
email_address = models.CharField(max_length = 150)
street_address = models.CharField(max_length = 350)
def __str__(self):
return '{}'.format(self.first_name)
Forms.py
class UserForm(forms.ModelForm):
password = forms.CharField(widget = forms.PasswordInput())
class Meta():
model = User
fields = ('username','email','password')
class UserContactForm(forms.ModelForm):
class Meta():
model = UserContacts
fields = "__all__"
views.py:
#login_required
def new_contact(request):
form = UserContactForm()
current_user = request.user.get_username()
user = User.objects.filter(username=current_user).first()
output = UserContacts.objects.filter(current_user_id=user.id).first()
if request.method == "POST":
form = UserContactForm(request.POST)
if form.is_valid():
form.save(commit=True)
return index(request)
else:
print('Error Form Invalid')
return render(request,'basic_app/contact.html',{'form':form})
Here is how the output looks like when the logged in user tries to enter contact information details:
Updating contact screenshot. As you can see the current user has to select his username to fill out the contact information.
How to overcome this and by default set the username in the form to the current logged in user
Change your UserContactForm to include an extra perameter in __init__, and set the initial value on the user field:
class UserContactForm(forms.ModelForm):
class Meta():
model = UserContacts
fields = "__all__"
def __init__(self, *args, **kws):
# To get request.user. Do not use kwargs.pop('user', None) due to potential security hole
self.user = kws.pop('user')
super().__init__(*args, **kws)
self.fields['user'].initial = self.user
Then change you view to add in the request.user to the form construction:
#login_required
def new_contact(request):
form = UserContactForm(user=request.user)
current_user = request.user.get_username()
user = User.objects.filter(username=current_user).first()
output = UserContacts.objects.filter(current_user_id=user.id).first()
if request.method == "POST":
form = UserContactForm(request.POST, user=request.user)
if form.is_valid():
form.save(commit=True)
return index(request)
else:
print('Error Form Invalid')
return render(request,'basic_app/contact.html',{'form':form})
You could probably remove the:
current_user = request.user.get_username()
user = User.objects.filter(username=current_user).first()
output = UserContacts.objects.filter(current_user_id=user.id).first()
I am using the same form for profile_edit and create_profile functionality. It is updating the multi-choice values in the profile_edit page but does not create in create_profile.
Below is the form code in forms.py
class ProfileForm(ModelForm):
full_name = forms.CharField(required=True)
current_position = forms.CharField(required=True)
about_me = forms.Textarea(attrs={'required':True})
topic_name = forms.ModelMultipleChoiceField(Topic.objects.all())
class Meta:
model = Profile
fields =(
"full_name",
"current_position",
"about_me",
"topic_name",
)
Below is the views.py for profile creation
def create_profile(request, user_id):
if request.method == "POST":
form = ProfileForm(request.POST)
if form.is_valid():
form = form.save(commit=False)
user = get_object_or_404(User, id=user_id)
form.user = user
print(form.topic_name.all()) # Prints empty queryset
form.save()
return redirect("profile_view", user_id=user_id)
else:
context = {"form": form}
return render(request, "profile/create_profile.html", context)
else:
form = ProfileForm()
context = {
"form": form
}
return render(request, "profile/create_profile.html", context)
Below is Model.py
class Topic(models.Model):
topic = models.CharField(max_length=12)
def __str__(self):
return self.topic
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True,)
full_name = models.CharField(max_length=60, null=True)
current_position = models.CharField(max_length=64, null=True)
about_me = models.TextField(max_length=255, null=True)
topic_name = models.ManyToManyField(Topic)
def __str__(self):
return self.full_name
Both create_profile and edit_profile templates are exactly the same.
It saves everything except Multichoice field.
When you do save(commit=False),
you need to use mymodelform.save_m2m() below save(commit=True) on your ModelForm,
because many to many relationships cannot be saved without an ID.
see this docs
so in your views.py
if form.is_valid():
profile = form.save(commit=False)
user = get_object_or_404(User, id=user_id)
profile.user = user
profile.save()
form.save_m2m()
return redirect("profile_view", user_id=user_id)
I am trying to create a search form, Where admin can search users and then deactivate their profiles, if it is the right account.
tried function based views and then class based views. It shows the profile in function based views but doesn't update it. and in class based view it wouldn't even show the profile.
models.py
class User(AbstractBaseUser):
objects = UserManager()
email = models.EmailField(verbose_name='email address', max_length=255, unique=True,)
type = models.CharField(max_length = 50, choices = type_choices)
name = models.CharField(max_length = 100)
department = models.CharField(max_length = 100, null = True, blank = True, choices = department_choices)
active = models.BooleanField(default=True)
staff = models.BooleanField(default=False) # a superuser
admin = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['type']
forms.py
class SearchForm(forms.Form):
email = forms.EmailField(required=True)
views.py
#method_decorator(login_required, name='dispatch')
class adminDeleteProfileView(LoginRequiredMixin, View):
def render(self, request):
return render(request, 'admin/view_account.html', {'form': self.form})
def form_valid(self, form):
self.form = SearchForm(request.POST)
print('im here', form.cleaned_data.get('email'))
User.objects.filter(email = form.cleaned_data.get('email')).update(active = False)
#print('Donot come here')
def get(self, request):
self.form = SearchForm()
return self.render(request)
#login_required
def admin_deactivate_profile_view(request):
error_text = ''
if request.method == 'POST':
print('here')
user_email = request.POST.get('email')
try:
print('Deactivating',user_email, 'Account.')
profile = User.objects.filter(email = user_email).first()
if request.POST.get('delete'):
User.objects.filter(email = user_email).update(active = False)
messages.success(self.request, 'Profile Updated!')
except Exception as e:
print(e)
messages.success(self.request, 'There was an error!')
return render(request, "admin/delete_profile.html", {'profile':profile})
simple query .
user=User.objects.get(email="user#email.com")
user.activate=false
user.save()
I try to save two forms in registration. I can see the auth form save but the second form is not pass .is_valid(). Could you please let me know what is wrong?
Models.py
class School(models.Model):
id = models.IntegerField(primary_key=True)
Name = models.CharField(max_length=50, null=False)
Domain = models.CharField(max_length=50, null=False)
Mascot = models.ImageField(null=True, upload_to='mascot')
def delete(self, *args, **kwargs):
self.Mascot.delete()
super(School, self).delete(*args, **kwargs)
def __str__(self):
return self.Name
class HeepooUser(models.Model):
user = models.OneToOneField(User)
phone = models.CharField(max_length=15, null=True)
allow_phone = models.BooleanField(default=False)
school_id = models.IntegerField()
date_join = models.DateTimeField(auto_now_add=True)
forms.py
class UserForm(forms.ModelForm):
email = forms.EmailField(max_length=50, required=True)
password = forms.CharField(widget=forms.PasswordInput())
class Meta:
model = User
fields = ('email', 'password')
class RegisterForm(forms.ModelForm):
school_id = forms.ModelChoiceField(queryset=School.objects.all())
phone = forms.CharField(max_length=15, min_length=10, required=False)
class Meta:
model = HeepooUser
fields = ('phone', 'school_id')
views.py
def register(request):
registered = False
if request.method == 'POST':
user_form = UserForm(request.POST)
profile_form = RegisterForm(request.POST)
if user_form.is_valid() and profile_form.is_valid():
user = user_form.save(commit=False)
user.set_password(user.password)
user = user_form.save()
profile = profile_form.save(commit=False)
profile.user = user
profile = profile_form.save()
registered = True
else:
return HttpResponse('Wrong access1')
else:
user_form = UserForm()
profile_form = RegisterForm()
return render(request, "register.html", {
'user_form': user_form,
'profile_form': profile_form,
'registered': registered,
})
I try to save email and password to auth_user and school_id and phone to separate table.
All the best!
tested your code and what I've encountered when submitting a form is
school_id value must be an integer
I'm suggesting to set school_id/school to be a foreignKey of the School model
class HeepooUser(models.Model):
user = models.OneToOneField(User)
phone = models.CharField(max_length=15, null=True)
allow_phone = models.BooleanField(default=False)
school_id = models.ForeignKey(School)
date_join = models.DateTimeField(auto_now_add=True)
so that we could just do the forms like this
class RegisterForm(forms.ModelForm):
class Meta:
model = HeepooUser
exclude = ('allow_phone', 'user')
also I think you don't need to specify the form fields for UserForm since by default django user only requires a password, username, and email
The problem is with how binary ANDs work. If user_form.is_valid() returns False, the "if" statement marks the whole statement as False without needing to evaluate profile_form.is_valid(). Therefore, profile_form.is_valid() never gets called and it's errors dict will not get populated. Unfortunately, django's form is_valid() does more than just return a boolean and has the side effect of populating that errors dict.
if user_form.is_valid() and profile_form.is_valid():
...
One thing you might be able to do is something like this:
user_valid = False
if user_form.is_valid():
user_valid = True
profile_valid = False
if profile_form.is_valid():
profile_valid = True
if user_valid and profile_valid:
... do something
The above ensures that both forms get processed. There might be a better way to express it, but that's the idea.
I want to save the database attendance data daily of each user,
but my no error no saved why? please help me
this is my full code below:
this is my views.py:
def staffs(request):
args = {}
args.update(csrf(request))
args['staffs'] = User.objects.all()
return render_to_response("staffs.html", args)
def staffdetail(request, user_id=1):
user = get_object_or_404(User, pk=user_id)
return render_to_response("staffdetail.html",
{"user": User.objects.get(id=user_id) })
def attendance(request, user_id):
if request.method == "POST":
attendance = Attendance_data(user = request.user.id)
form = AttendancekForm(request.POST, instance = attendance)
if form.is_valid():
form.save()
return HttpResponseRedirect('/articles/get/%s' % user.id)
else:
form = AttendanceForm()
return render_to_response('attendance.html', context_instance = RequestContext(request, {'form': form}))
def leave_work(request, user_id):
if request.method == "POST":
leave_work = Leave_work(user = request.user.id)
form = Leave_workForm(request.POST, instance = leave_work)
if form.is_valid():
form.save()
return HttpResponseRedirect('/articles/get/%s' % user.id)
else:
form = Leave_workForm()
return render_to_response('leave.html', context_instance = RequestContext(request, {'form': form}))
So,i'm also add my models.py and forms.py here
this is my models.py:
class User(models.Model):
user_name = models.CharField(max_length=255)
first_kana = models.CharField(max_length=255)
last_kana = models.CharField(max_length=255)
employee_number = models.CharField(blank=True, max_length=22)
created_at = models.DateTimeField(auto_now_add=True)
def __unicode__(self):
return self.user_name
class Attendance_data(models.Model):
user_name = models.CharField(max_length=255)
employee_number = models.CharField(blank=True)
def __unicode__(self):
return self.user_name, employee_number
class Leave_work(models.Model):
user_name = models.CharField(max_length=255)
employee_number = models.CharField(blank=True, max_length=22)
def __unicode__(self):
return self.user_name, employee_unmber
this is my forms.py:
class ArticleForm(forms.ModelForm):
class Meta:
model = User
fields = ('user_name','first_kana', 'last_kana', 'employee_number')
user_name = forms.CharField( label="name",error_messages={'required': ''})
first_kana = forms.CharField(label="firstname",error_messages={'required': ''})
last_kana = forms.CharField(label="lastname",error_messages={'required': ''})
employee_number = forms.CharField(label="number", required=False)
class Attendance_dataForm(forms.ModelForm):
class Meta:
model = Attendance_data
fields = ('user_name','employee_number')
user_name = forms.CharField(label="name", error_messages={'required': ''})
employee_number = forms.CharField(label="number",error_messages={'required': ''})
class Leave_workForm(forms.ModelForm):
class Meta:
model = Leave_work
fields = ('user_name', 'employee_number')
user_name = forms.CharField(label="name", error_messages={'required': ''})
employee_number = forms.CharField(label="number", error_messages={'required': ''})
You are doing a lot of wrong thing in your views. If you look at your model Attendence_data, it has two fields user_name and employee_number. so its constructor would accept two arguments, user_name and employee_number or any other fields that are set not to be NULL and have no default value, so passing request.user.id to the its constructor would not make it a valid object. Same is the case with Leave_work model. So if you need to do this, you need to overload the default constructor.
But seems like you are not being able to understand the basic concepts of how Django works so I'd suggest you to go trough this tutorial as this will clear a lot of basic concepts.