Boolean field not saving in Django form - python

I have a form with radio buttons and text fields. When I submit the form, the boolean field does not get created in the record. The boolean field is supposed to be updated via the radio buttons. What could be the issue here?
Here is the relevant part of my forms.py file:
CHOICES = (
(1,'yes'),
(0,'no')
)
class ServiceForm(forms.ModelForm):
one_time_service = forms.ChoiceField(required = True, choices = CHOICES, widget=forms.RadioSelect())
class Meta:
model = Service
fields = ('one_time_service')
This is my models.py one_time_service field
one_time_service = models.BooleanField(default=False)
This is my views.py:
def create(request):
if request.POST:
form= ServiceForm(request.POST)
if form.is_valid():
service_obj = form.save(commit=False)
service_obj.user_id = request.user.id
service_obj.save()
return render_to_response('services/service_created.html',
{'service': Service.objects.get(id=service_obj.id)})
else:
form = ServiceForm()
args= {}
args.update(csrf(request))
args['form'] = form
return render_to_response('services/create_service.html', args )
Edit: Here is my create_service.html
<form action="/services/create" method="post" enctype="multipart/form-data">{% csrf_token %}
<ul>
{{form.as_p}}
</ul>
<input type="submit" name="submit" value="Create Service">
</form>

I have no idea if this is the problem, but the line:
fields = ('one_time_service')
is wrong. That's not a single element tuple, that's a string with parens around it. Add a comma to make it a tuple:
fields = ('one_time_service',)
Edit: also, form.save() does not update any database records -- it creates a new one! That may be your problem.

Related

Updating one to one model using form in Django

I am very new to Python and Django and am stuck with this problem , which I think should be very simple to solve.
model.py
class UserDetails(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
billingAddress = AddressField(related_name='+',blank =True ) # Used django-address https://pypi.org/project/django-address/
shippingAddress = AddressField(related_name='+',blank =True)
forms.py
class AddressForm(forms.ModelForm):
class Meta:
model = UserDetails
exclude = ['user']
views.py
def address(request):
form = AddressForm(request.POST or None)
if request.method == 'POST' and form.is_valid():
zipCode = request.POST.get("ZipCode","")
form = AddressForm(data=request.POST)
detailForm = form.save(commit = False)
detailForm.user = request.user
baddressDict = {'raw':request.POST.get("billingAddress","")+", " + zipCode, 'postal_code': zipCode,}
saddressDict = {'raw':request.POST.get("shippingAddress","")+", " + zipCode, 'postal_code': zipCode,}
detailForm.billingAddress = baddressDict
detailForm.shippingAddress = saddressDict
detailForm.save()
else:
form = AddressForm()
return render(request,'showcase/address.html',{'form': form})
address.html
<form action="." method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="text" name="ZipCode" value="Vip Code" >
<input type="submit" value="Submit" >
</form>
What I am trying to do it update the shipping & Billing address for current user.
The first time I am doing this it works but the second time it gives
UNIQUE constraint failed: showcase_userdetails.user_id
which obviously is cause it trying to add another row in the DB.
How do i make sure it updates and not insert?
Thanks,
Gourav
Quite simply, you have to pass an existing instance of your model:
def edit_address(request):
user = request.user
try:
address_instance = UserDetail.objects.get(user=user)
except UserDetail.DoesNotExist:
address_instance = None
if request.method == 'POST':
form = AddressForm(request.POST, instance=address_instance)
if form.is_valid():
details = form.save(commit=False)
# You should really let the form takes care of all this,
# and you should DEFINITLY NOT use unsanitized data from
# request.POST - the whole point of forms is to make sure
# your user inputs are properly sanitized...
details.user = request.user
# etc
else:
# passing it for the GET part too so the user
# can see the already existing data (if any)
form = AddressForm(instance=address_instance)
return render(request,'showcase/address.html',{'form': form})

Retrieve variable from instance of Django form

I have a Django form NameForm. I am attempting to iterate over an array of values and, for each value, have an option to display the same form. The only thing that should change with the form submission should be the associated value to which the form is displayed next to.
This becomes much clearer with an example. For some array [1,2,3] we should display:
We can then click on any open form icon, fill out the NameForm form. The resultant information, including the form_id (in this case 1, 2, or 3) should be returned to forms.py. How can I fetch the form_id variable from an instance of NameForm in index.py?
My (hacky) attempt can be found below. The problem is I don't know how to access the form_id variable I created in the NameForm object.
forms.py
class NameForm(forms.Form):
form_id = None
your_name = forms.CharField(label='Your name', max_length=3)
views.py
def index(request):
if request.method == 'POST':
form = NameForm(request.POST)
form_id = form.form_id # The problem line, as form_id is always None
if form.is_valid():
return HttpResponse( \
' '.join((str(form.cleaned_data['your_name']),form_id ))\
) #Throws TypeError as can't join None and string
else:
forms = []
vals = [1,2,3]
for val in vals:
form = NameForm()
form.form_id = val
forms.append(form)
return render(request, 'post/index.html', {'forms': forms})
index.html
{%for form in forms%}
{{form.form_id}}
<button class="button" onclick="openForm()">Open Form</button>
<div class="myForm">
<form class="form-container" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit">
<button class="button" onclick="closeForm()">Cancel</button>
</form>
</div>
</br>
{%endfor%}
In Django Form or Django Model, when you set a field's value to None, it is assumed that you want to ignore said field. This is helpful when creating a model that inherits from another model and you want to remove some unnecessary fields.
If you want to set value for a field on Form creation, you should pass it into __init__ method. E.g:
class NameForm(forms.Form):
form_id = forms.IntegerField(widget=forms.HiddenInput())
your_name = forms.CharField(label='Your name', max_length=3)
def __init__(self, form_id, *args, **kwargs):
self.fields['form_id'].initial = form_id
Alternatively, instead of overriding the __init__ method, you can set an initial value for form_id when you create an instance of NameForm. For example:
vals = [1,2,3]
forms = [NameForm(initial={'form_id': val}) for val in vals]

Pass Foreignkey from User Input to DB

I'm trying to have user input the data and store into DB and map with the other data.
Model:
class Code(models.Model):
name = models.CharField(max_length=4, default=None, blank=True, unique=True)
Within the Model, there is another class
class Pull(models.Model):
code_pull = models.ForeignKey(Code, on_delete=models.SET_NULL, null=True)
How to display to call in the Form and View, so that data is pass when user input the data in the input field.
Form
class Code_Form(forms.ModelForm):
class Meta:
model = Code
fields = ('name',)
class Pull_Form(forms.ModelForm):
class Meta:
model = Pull
fields = ('code_pull', 'data1', 'prefix',)
#Inital Value is NULL
def __init__(self, *args, **kwargs):
super(Pull_Form, self).__init__(*args, **kwargs)
self.fields['code_pull'].queryset = CODE.objects.none()
if 'code_pull' in self.data:
c = self.data.get('code_pull')
self.fields['code_pull'].queryset = CODE.objects.filter(name=c)
#print(self.fields['code_pull'].queryset)
I updated the code for the FORM, so that it initial the value from the CODE_form, Still Error, as the code field is empty
Here is the VIEW:
def InputData(request, *args, **kwargs):
form = Pull_Form(request.POST or None)
if request.method == 'POST':
if form.is_valid():
data_add = form.save(commit=False)
data_add.code = form.cleaned_data['code_pull']
data_add.save()
messages.success(request, 'Successfully')
else:
messages.error(request, form.errors)
return render(request, template_name, {'form': form })
ERROR: Not able to add the data as the field for the code is not selected when submitting the form.
ERROR CODE: code - Select a valid choice. That choice is not one of the available choices.
{{ messages }}
<form id="form1" class="post-form" role=form method="POST" action=".">{% csrf_token %}
<input id="code_pull" class="form-control" type="text" maxlength="4" required></input>
<label for="code_pull">Code</label>
<button type="submit" class="btn">Save</button>
</form>
Thank you for the help in advance.
Django forms use the name attribute in HTML controls to capture form data.
<input id="code" name="code" class="form-control" type="text" maxlength="4" required></input>
I only added name="code". this should make it work.

Django - custom registration form (errors, unique email and admin)

first of all, I am new in programming with Django. Here is what I have:
The <form> inside my register.html template:
<form method='POST' action='/accounts/register/'>
{% csrf_token %}
{% for field in form %}
{{ field.label_tag }}{{ field }} {{field.help_text}} {{field.errors}{}
<br/>
{% endfor %}
<input type='submit' value='Register' />
</form>
This is inside my forms.py
class MyRegistrationForm(UserCreationForm):
email = forms.EmailField(required=True)
first_name = forms.CharField(required = True)
last_name = forms.CharField(required = True)
password1 = forms.RegexField(widget=forms.PasswordInput,
regex = r'[\w+]{8,}',
label = 'New password',
help_text = "Must be strong!",
error_messages = {'required' : "ASDASDA",
'invalid' : "ZZZZZ"}
)
password2 = forms.RegexField(widget=forms.PasswordInput,
regex = r'[\w+]{8,}',
label = 'Re-enter password',
)
class Meta:
model = User
fields = ('last_name', 'first_name', 'username', 'email', 'password1', 'password2')
def save(self, commit = True):
user = super(MyRegistrationForm, 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']
if commit:
user.save()
return user
This is inside my views.py
def User_Register_View(request):
if request.method == 'POST':
form = MyRegistrationForm(request.POST)
if form.is_valid():
form.save()
register_success = "Account successfuly created!"
return render(request,'index.html', locals())
args = {}
args.update(csrf(request))
args['form'] = MyRegistrationForm()
return render(request,'accounts/register.html',args)
My questions are the following:
{{field.errors}} is not working. No errors are printed. If I let all the fields of the form empty, and I click 'Register', no error is rendered.
If I add another field to this forum, "gender" as a CharField, will it create a column inside my DB for gender? ( I am working with the default sqlite3)
Is there a simple way to modify my code and make the 'User' field optional and, instead, make the 'Email' field be unique and required?
In the state in which my code is, where can I check for the unique property of my email in the DB? Is it inside my views.py, just before form.save() ?
Thank you. Let me know if you have any questions
def User_Register_View(request):
if request.method == 'POST':
form = MyRegistrationForm(request.POST)
if form.is_valid():
form.save()
register_success = "Account successfuly created!"
return render(request,'index.html', locals())
else:
form = MyRegistrationForm() # An unbound form
args = {}
args['form'] = form
return render(request,'accounts/register.html',args)
{{field.errors}} now showing because you are not returning the validated form instance if validation failed. You always return a new instance of MyRegistrationForm. See above example.
adding fields to forms will not affect your db since only models maps to db tables
& 4. You need custom user model to do so, see here for example on how to do it

Django ImageField not rendering ClearableFileInput

Starting to beat my head against the wall...perhaps I am missing something simple.
models.py
class GFImage(models.Model):
image = models.ImageField(upload_to = 'uploads', null=True, blank=True)
views.py
def addImage(request):
errors = []
if request.method == 'POST':
form = ImageForm(request.POST, request.FILES)
if form.is_valid():
form.save()
urlRedirect = "/home"
return redirect(urlRedirect)
else:
form = ImageForm()
return render(request, "/add_image.html", {'form': form})
forms.py
class ImageForm(ModelForm):
class Meta:
model = GFImage
add_image.html
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<input type = "submit" value = "Submit">
</form>
Whatever I do, my form will not use the ClearableFileInput widget. It should default automatically, but even assigning it in the form's META will not work. What else could be blocking Django from using the clearable widget?
The ClearableFileInput will only display the clear checkbox when there's an initial file selected. Looking at your form, it looks like a a new form without initial data, so the checkbox won't be displayed.
def render(self, name, value, attrs=None):
.. snip ..
if value and hasattr(value, "url"):
template = self.template_with_initial
substitutions['initial'] = format_html(self.url_markup_template,
https://github.com/django/django/blob/5fda9c9810dfdf36b557e10d0d76775a72b0e0c6/django/forms/widgets.py#L372

Categories