local variable referenced before assignment django error - python

This is my view.py and when i have a form which when i submit with the required fields it gives an appropriate output but when i don't input anything in the form and click submit i get an error saying "local variable 'researcher' referenced before assignment".
Also i want to know how do i keep my form data saved on the destination page
def about_experiment(request,ex_link_name):
if request.method == 'POST':
form = AboutHelp(request.POST)
if form.is_valid():
researcher = form.cleaned_data['researcher']
study = form.cleaned_data['study']
else:
form = AboutHelp()
return render(request, 'about_experiment.html', {'researcher': researcher, 'study': study})
my form on the source page is
<form action="{% url 'lazer.views.about_experiment' exp.link_name %}" method="POST" name="form">
{% csrf_token %}
<label>Researcher Name(s):<input type="text" name="researcher">
<lable>Study Summary<textarea rows="10" cols="50" placeholder="here you go" maxlength="500" class="form-control" name="study"></textarea>
<br>
<input type = "submit" value="Submit" class="btn btn-primary" />
</form>
My destination page where the form outputs are present
<h4> Name : {{ researcher }} </h4><br>
<h4> Summary : {{ study }} </h4>

in else part of views.py you mentioned researcher variable in render method that is producing this error.
so please add
researcher = None
before if statement
and also add
study = None
that will also create same error
forms.py
from django import forms
from .models import AboutHelp
class AboutHelpForm(forms.ModelForm):
class Meta:
model = AboutHelp
fields = '__all__'
views.py
def about_experiment(request,ex_link_name):
researcher = None
study = None
form = AboutHelpForm(request.POST or None)
if request.method == 'POST':
if form.is_valid():
form.save()
return render(request, 'about_experiment.html', {'researcher': researcher, 'study': study})

researcher and study are not assignment if request method is not POST and form is not valid. You should define this variable before if statement:
def about_experiment(request,ex_link_name):
researcher = ''
study = ''
if request.method == 'POST':
...

Related

Request attributes

I have a page, and there are 3 types of button(apple,banana, orange), by clicking the first button, a form comes up to get information. The first button should send information to the apple Model, the banana button should send information to the banana Model and so orange!
here is my models.py:
from django.db import models
class Apple(models.Model):
first_name = models.CharField(max_length=100)
class Banana(models.Model):
first_name = models.CharField(max_length=100)
class Orange(models.Model):
first_name = models.CharField(max_length=100)
my forms.py:
from django import forms
class Fruit(forms.Form):
first_name = forms.CharField(max_length=100)
my views.py:
def fruitForm(request):
form = Fruit()
if request.method == 'POST' & request.id == 'apple':
form = Fruit(request.POST)
if form.is_valid():
Apple.objects.create(**form.cleaned_data)
elif request.method =='POST' & request.id =='orange':
form = Fruit(request.POST)
if form.is_valid():
Orange.objects.create(**form.cleaned_data)
elif request.method =='POST' & request.id =='banana':
form = Fruit(request.POST)
if form.is_valid():
Banana.objects.create(**form.cleaned_data)
return render(request, 'main/home.html', {'form':form})
my home.html:
<button class='btn btn-primary' data-target='#orange'> Add </button>
<form action=# method="POST" id = "orange">
{% csrf_token %}
{{ form.as_p }}
</form>
well, when I try go to main page (where the buttons are), I got this error:
'WSGIRequest' object has no attribute 'id'.
request doesn't have the id attribute, right? So, How can I get specific data to save in relative model?
You can add a name to a submit input, the value is the text content of the button so cannot really be used for this
<form>
<input type="submit" class="btn btn-primary" name="orange" value="Add">
<input type="submit" class="btn btn-primary" name="apple" value="Add">
</form>
This value will then be one of the keys in the post data
if 'orange' in request.POST:
pass
elif 'apple' in request.POST:
pass
The attributes of the POST request body come from the name attributes of the form inputs. So one way to handle this, if you want to keep your view function the same, is to add a hidden field to each form that distinguishes which model it should update:
<form action=# method="POST" id = "orange">
{% csrf_token %}
<input type="hidden" name="id" value="orange" />
{{ form.as_p }}
</form>
And similarly for the other 2 forms.
(This isn't the only way to solve this problem. You could, for example, have a variable in your URL which specifies which model to use. Then you could check its value in your view function. This requires a bit more work though, including changing your urls.py.)

WEIRD Django AuthenticationForm Behaviour

I have, all day, tried to figure this out but I can't really see where the problem is coming from.
I have a Django AuthenticationForm that seems to be submitting data somehow but not getting validated.
forms.py:
class LoginForm(AuthenticationForm):
username = forms.CharField(widget=forms.TextInput(attrs={'name': 'username'}))
password = forms.CharField(widget=forms.PasswordInput(attrs={'name': 'password'}))
views.py:
def index(request):
template = 'myapp/login.html'
if request.method == "POST":
print request.POST #prints QueryDict with its data
reg = LoginForm(request.POST or None)
if reg.is_valid():
return HttpResponse('Success: Form is valid!')
else:
return HttpResponse('Error: Form not valid')
loginform = LoginForm()
context = {'loginform':loginform}
return render(request, template, context)
HTML:
<form method="post" action=".">
{% csrf_token %}
<h2>Sign in</h2>
<p class="text-danger">{{loginform.errors}}</p>
{{ loginform.as_p }}
<button name = "signin" type="submit" value="0">Sign in</button>
</form>
The print request.POST in my views.py prints QueryDict: {u'username': [u'yax'], u'csrfmiddlewaretoken': [u'r8y1PaVNjxNWypdzP
MaFe1ZL7IkE1O7Hw0yRPQTSipW36z1g7X3vPS5qMMX56byj'], u'password': [u'sdfdsfsddfs']
, u'signin': [u'0']} but the reg.is_valid() keeps returning false.
EDIT:
I have also tried printing out reg.errors but it doesn't print out anything.
Try making the following change:
reg = LoginForm(data=request.POST)
AuthenticationForm is slightly different in that it needs the data argument.
Also note that you should test it with actually valid username and password combinations (that correspond to an existing user), since AuthenticationForm checks for that as well.

django_countries does not display in the form on template

I used {{ form }} as seen here
template.html
<h4>Change your details</h4><br>
<form id="edit_form" method='post'>
{% csrf_token %}
{{ form }}
<div class='section group'>
<input id="update_details_button" type='submit' class='btn btn-primary wide' value='Change'/>
</div>
</form>
views.py
def user_view(request, is_admin):
user = request.user
form = myForm()
if request.method == 'POST' and is_admin:
form = myForm(request.POST)
if form.is_valid():
data = form.cleaned_data
user.name = data['name']
user.country = data['country']
user.save()
messages.success(request, 'You have successfully updated your details.')
return render(request, 'mysite/user.html', {
'user': user,
'is_admin': is_admin,
'form': form,
})
My form is as followed
class myForm(forms.Form):
name = forms.CharField(
label="Name",
widget=forms.TextInput(attrs={'placeholder': 'Name'}))
country = CountryField(blank_label='(select country)')
def __init__(self, *args, **kwargs):
super(myForm, self).__init__(*args, **kwargs)
The name field displayed fine on the page but there's no sign of the CountryField, could someone point out the error? The code compiled fine and gives no error while server is running.
CountryField is a model field, not a form field. You're supposed to add it to your user model, in which case a modelform based on that model will automatically generate a country field. Since it looks like you have actually added a field called country to the User model, that's where you should be using CountryField.
However, for reference, to do it manually on a non-model form is slightly more complicated:
from django_countries import widgets, countries
class myForm(forms.Form):
country = forms.ChoiceField(widget=CountrySelectWidget, choices=countries)
In fact it's simpler: https://pypi.org/project/django-countries/#custom-forms
from django_countries.fields import CountryField
class MyForm(forms.Form):
country = CountryField(blank=True).formfield()
If you have installed django_country and it added in installed app than no need to make it from just use like this
{% load countries %}
<select name="country">
{% countries %}
<option value="{{ code }}">{{ name }}</option>
{% endcountries %}
</select>

Django - How to pass a User object to a form in views.py

I am new to django, and have been tying to pass a User object to a ModelForm and then validate it. That is adding the User object as a ForeignKey to a Note object in the end, where the ModelForm is a Meta of the class Note.
My forms.py:
class NoteForm(ModelForm):
class Meta:
model = Note
My views.py:
def addNote(request):
if request.method == 'POST':
user = User.objects.get(username=request.POST['user'])
model_form = NoteForm(request.POST, request.FILES, user)
if model_form.is_valid():
model_form.save()
return HttpResponseRedirect(reverse('index'))
return HttpResponse('De indtastede data er ikke gyldige')
return render(request, 'studies/uploadfile.html')
My template.html:
<form enctype="multipart/form-data" method="post" action="/notes/add/">
Note Title: <input type="text" name="name" /> <br />
Select Note: <input type="file" name="note" /> <br />
<input type="hidden" name="user" value="{{ user.id }}">
<input type="submit" value="submit" />
{% csrf_token %}
</form>
I have tried using the request.user, since im trying to get the current user logged on and adding that user as the ForreignKey.
Any help will be appreciated, beforehand thanks.
I'm not sure what the point is of wanting to send it to the template. You have it in the view both before and after validation, after all: better to deal with it there.
The thing to do is to exclude the user field from the form definition, then set it manually on save:
class NoteForm(ModelForm):
class Meta:
model = Note
exclude = ('user',)
if request.method == 'POST':
model_form = NoteForm(request.POST, request.FILES)
if model_form.is_valid():
note = model_form.save(commit=True)
note.user = request.user
note.save()
return...
Also note that your view never sends any validation errors to the template, and your template doesn't show errors or the invalid values that the user has entered. Please follow the structure set out in the documentation.
You can extend the save method of the form,
def save(self, user):
note = super(NoteForm, self)
note.user = user
note.save()
return note
Also your view must be in this structure:
from django.shortcuts import render
from django.http import HttpResponseRedirect
def contact(request):
if request.method == 'POST': # If the form has been submitted...
form = ContactForm(request.POST) # A form bound to the POST data
if form.is_valid(): # All validation rules pass
# Process the data in form.cleaned_data
# ...
# note: NoteForm.save(request.user)
return HttpResponseRedirect('/thanks/') # Redirect after POST
else:
form = ContactForm() # An unbound form
return render(request, 'contact.html', {
'form': form,
})
(copied from https://docs.djangoproject.com/en/dev/topics/forms/)
Look here https://docs.djangoproject.com/en/1.2/ref/templates/api/#subclassing-context-requestcontext

Allow user to change its picture. Django

In my app I allow users to have a profile picture. And I would like them to be able to change it. Surprisingly, I didn't find anything on how to accomplish that.
Here is what I tried:
models.py
class UserProfile(FacebookProfileModel):
user = models.OneToOneField(User)
profilepic = models.ImageField(upload_to="profilepics/", default="blabla.jpg")
my html:
<form method='post' action='{%url myproject.views.changes %}>
<div class="controls">
<input type="file" name="image">
</div>
<input type="submit">
</form>
my view:
def changes(request):
if 'image' in request.POST:
image = request.POST.get('image')
userprofile.profilepic.url = image
userprofile.save()
When I do that, I get the following error message:
'AttributeError at /my/site/
can't set attribute'
Any idea on how I could accomplish that? Thank you
Make sure you request a UserProfile object first, then
Looks like you should use
image = request.FILES['image']
userprofile.profilepic = image
instead of
image = request.POST.get('image')
userprofile.profilepic.url = image
See This example, the views.py section, as Jake said
You need to include enctype="multipart/form-data" in your form. Here is an example of how to update an ImageField:
first the update_form.html:
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="save btn btn-default">Update</button>
</form>
Then the form:
from django.contrib.auth import get_user_model
class EditProfile(UserChangeForm):
class Meta:
model = get_user_model()
fields = ('email', 'name', 'avatar')
And finally the view:
def user_edit(request):
if request.method == 'POST':
form = EditProfile(request.POST, instance=request.user)
if form.is_valid():
form.save()
if request.FILES.get('avatar', None) != None:
try:
os.remove(request.user.avatar.url)
except Exception as e:
print('Exception in removing old profile image: ', e)
request.user.avatar = request.FILES['avatar']
request.user.save()
return redirect('user:profile', id=request.user.id)
else:
form = EditProfile(instance=request.user)
return render(request, 'user/user-edit.html', {'form': form})

Categories