Django Form getting invalid - django

I am newbie to Django. I have some troubles with forms after moving into new verison. Following,
1, The model
class UserProfileDetails(models.Model):
user = models.OneToOneField(User)
profilePicture = models.ImageField('Profile Picture',upload_to='static/ProfilePic/', null=True,blank=True)
def __str__(self):
return self.user.username
2, The form
class imageUploadForm(forms.ModelForm):
class Meta:
model= UserProfileDetails
fields = ['user','profilePicture']
3, And finally the view function
def upload_pic(request):
current_user = request.user
if request.method == 'POST':
form = imageUploadForm(request.POST, request.FILES)
if form.is_valid():
pic = form.cleaned_data['profilePicture']
m = UserProfileDetails(user= current_user.id,profilePicture=pic)
m.save()
else:
raise NotImplemented("What if the user doesn't have an associated profile?")
return HttpResponseRedirect(reverse('polls:profile'))
This code worked with Django 1.8. But after porting to Django 1.10.4, the form is getting invalid. I believe, the problem is with OneToOneField.
IMP: Also, i am using pinax account app for account management.
Why this form is getting invalid?

When you submit the form, it doesn't seem as though a correct input has been given for both fields (user and profile picture). My guess is that you aren't sending through the user in the form which means it is invalid. So you are only uploading the image.
You do not need to have 'user' in the form fields attribute as you already access that in the view with 'request.user'. So remove the 'user' field from the form.
Also, to make sure it is correct, change 'user=current_user.id' to 'user=current_user' so you are match instance with instance rather than instance with id.

Related

How to link two forms (wagtail form and django form) with a foreign key?

I'm using a django form in conjunction with a wagtail form. The django form will record some fields that will be on any form of this type: name, email and the wagtail form will record extra data defined by the form page creator specific to that instance.
I've overloaded the serve method to capture both sets of data and I can process both forms, but I'm stuck when trying to add the logic to relate the form contents to each other so that when one submission set is deleted, the other set will be as well. I think what I need is a foreign key.
The following code fails at form_submission.event_submission = a.id where I'd like to take the id from the wagtail form submission and add that as a foreign key to the django form, so that when the wagtail form portion is deleted, the other is deleted as well, and so that I can have a usable link between the two form submissions.
def serve(self, request, *args, **kwargs):
if request.method == 'POST':
form = EventSignupForm(request.POST)
wagtail_form = self.get_form(request.POST, request.FILES, page=self, user=request.user)
if form.is_valid() and wagtail_form.is_valid():
a = self.process_form_submission(wagtail_form)
form_submission = form.save(commit=False)
form_submission.event_submission = a.id
form_submission.save()
return self.render_landing_page(request, form_submission, *args, **kwargs)
else:
form = EventSignupForm()
wagtail_form = self.get_form(page=self, user=request.user)
context = self.get_context(request)
context['form'] = form
context['wagtail_form'] = wagtail_form
return TemplateResponse(
request,
self.get_template(request),
context
)
The form submission class and django model form looks like this. I think the ForeignKey I have in the Model isn't right, but I don't know. Any help?
class EventFormSubmission(AbstractFormSubmission):
cancellation_id = models.CharField(max_length=7)
class EventSignup(models.Model):
"""
A model to contain signup info for an event: name, email.
"""
event_submission = models.ForeignKey(EventFormSubmission, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
email = models.EmailField()
I solved this by adding the extra fields I wanted (name, email) to the EventFormSubmission and then using a regular django form (not a ModelForm) to collect these pieces of information.

Different ways to save form values to the database

I have started learning Django recently using a Udemy course. While going through the course instructor asked to save values from a Form to database.
After searching on the internet I figured out how to put form values into database and everything is working fine. Below is my views.py and forms.py files.
forms.py
class FormName(forms.Form):
fname = forms.CharField( label="First Name")
lname = forms.CharField(label="Last name:")
email = forms.EmailField()
verify_email = forms.EmailField(label='Verify Email:')
def clean(self):
all_clean_data = super().clean()
email = all_clean_data['email']
vmail = all_clean_data['verify_email']
if email != vmail:
raise forms.ValidationError("Check the emails")
views.py
def signup(request):
form = forms.FormName()
if request.method == 'POST':
form = forms.FormName(request.POST)
if form.is_valid():
post = User()
post.fname=request.POST.get('fname')
post.lname=request.POST.get('lname')
post.email=request.POST.get('email')
post.save()
return render(request,'third_app/greet.html')
else:
return render(request,'third_app/oops.html',{'form':form})
return render(request, 'third_app/signup.html',{'form':form})
Now coming to question, the instructor is using Meta class to store the form values to the database. Below are his forms.py and views.py files. I am curious about what the difference is between my method and the instructor's.
forms.py
class FormName(forms.ModelForm):
class Meta():
model = User
fields = 'all'
views.py
def signup(request):
form = forms.FormName()
if request.method == 'POST':
form = forms.FormName(request.POST)
if form.is_valid():
form.save(commit=True)
return render(request,'third_app/greet.html')
else:
return render(request,'third_app/oops.html',{'form':form})
return render(request, 'third_app/signup.html',{'form':form})
Thanks.
The Django docs explain this very well. It's what is known as a ModelForm:
If you’re building a database-driven app, chances are you’ll have forms that map closely to Django models. For instance, you might have a BlogComment model, and you want to create a form that lets people submit comments. In this case, it would be redundant to define the field types in your form, because you’ve already defined the fields in your model.
For this reason, Django provides a helper class that lets you create a Form class from a Django model.
So, to answer your question, your method uses a regular form (forms.Form) where you define the form fields, perform validation and then save each field individually in your view. When using form.ModelForm, field validation and saving is taken care of for you. Seeing as you have already defined what your fields are, the ModelForm uses this to perform the validation. The save() method conveniently saves each field to the database.

Extending User model with one to one field- how to set user instance in view

I am trying to extend the user model using a one to one relationship to a UserProfile model. I added some boolean fields and in the view I am trying to use those fields as permissions.
Here is my model:
class UserProfile(models.Model):
user = models.OneToOneField(User)
FirstName = models.CharField(max_length=25)
LastName = models.CharField(max_length=25)
ProximityAccess = models.BooleanField(default=True)
NewProxAccess = models.BooleanField(default=False)
def __unicode__(self):
return self.user.username
and here is the view I am trying to use:
#login_required
def NewProx(request):
if UserProfile.NewProxAccess:
if request.method == 'POST':
form = ProxForm(request.POST)
if form.is_valid():
ProxPart_instance = form.save(commit=True)
ProxPart_instance.save()
return HttpResponseRedirect('/proximity')
else:
form = ProxForm()
return render(request, 'app/NewProx.html', {'form': form})
else:
raise PermissionDenied
I don't get any error messages but it does not work as intended. I was hoping that if the user profile had NewProxAccess set to False it would raise the PermissionDenied but it doesn't. I have the admin module wired up and I can select or deselect the checkbox for that field but it has no effect. If I comment out the rest I can get it to show the Permission Denied error so it has to be in the view (I think). I think I am missing a line the establishes the logged in user as the user instance so we can check to see if the user has the permission or not. I know there are a ton of ways to do this and there is probably a better way but for the sake of learning, what is it that I am missing for this to work?
Thanks
Scott
As you want to check access for particular profile but not UserProfile model you need to do:
if request.user.userprofile.NewProxAccess:
# your code
As a note: according to PEP8 best practices you should use camelCase only for naming Classes. For attrs, functions use underscore: my_function

django form use excluded field

with django 1.5.1 I try to use the django form for one of my models.
I dont want to add the "user" field (Foreignkey) somewhere in the code instead of letting the user deceide whoes new character it is.
My Code:
Model:
class Character(models.Model):
user = models.ForeignKey(User)
creation = models.DateTimeField(auto_now_add=True, verbose_name='Creation Date')
name = models.CharField(max_length=32)
portrait = models.ForeignKey(Portrait)
faction = models.ForeignKey(Faction)
origin = models.ForeignKey(Origin)
The form:
class CreateCharacterForm(forms.ModelForm):
class Meta:
model = Character
fields = ['name', 'portrait', 'faction', 'origin']
The view:
def create_character(request, user_id):
user = User.objects.get(id=user_id)
if request.POST:
new_char_form = CreateCharacterForm(request.POST)
if new_char_form.is_valid():
new_char_form.save()
return HttpResponseRedirect('%s/characters/' % user_id)
else:
return render_to_response('create.html',
{'user': user, 'create_char':new_char_form},
context_instance=RequestContext(request))
else:
create_char = CreateCharacterForm
return render_to_response('create.html',
{'user': user, 'create_char': create_char},
context_instance=RequestContext(request))
I have tried to use a instance to incluse the userid already. i've tried to save the userid to the form before saving it, or changing the save() from my form.
I keep getting the error that character.user cant be null
I have to tell that im pretty new to django and im sure one way or another it should be possible
Can someone please help me out?
Its explained well in document model form selecting fields to use
You have to do something like this in your view
...
if request.POST:
new_char_form = CreateCharacterForm(request.POST)
if new_char_form.is_valid():
#save form with commit=False
new_char_obj = new_char_form.save(commit=False)
#set user and save
new_char_obj.user = user
new_char_obj.save()
return HttpResponseRedirect('%s/characters/' % user_id)
else:
...

Username already exists, when want to update userprofile in django

Whenever I try try to update a userprofile on django powered web, I get the error: "username already exists, please provide another one." I am trying to get it to recognize the authenticated user. Although every other thing works, it will not update until I specify a new username.
views.py
#login_required
def editprofile(request):
registeredmember = request.user.get_profile()
if request.method == 'POST':
userprofile_edit = RegistrationForm(request.POST, instance = registeredmember)
if userprofile_edit.is_valid():
userprofile_edit.save()
return HttpResponseRedirect('/profile/')
else:
userprofile_edit = RegistrationForm(instance = registeredmember)
return render_to_response('carloan/editprofile.html', {'userprofile_edit': userprofile_edit}, context_instance=RequestContext(request))
You have to exclude the username field when you are Editing the profile.
Something like this in your RegistrationForm.
class RegistrationForm(forms.form):
#other code
class Meta:
exclude = ['username',]
You can add multiple field names which you don't want to be included in the form