How to take boolean field input from HTML into my Django model? - python

I have used Django forms for creating users and I extended the default User model by adding a boolean field, so I defined a new form for it. But I couldn't take input from HTML form to this boolean field. Shall I change my HTML form code?
Following are my code samples:
models.py
# accounts.models.py
from django.db import models
from django.contrib.auth.models import User
class SpecialUser(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
flag = models.BooleanField()
def __str__(self):
return self.title
forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from django.forms.widgets import CheckboxInput
from .models import SpecialUser
class RegisterForm(UserCreationForm):
email = forms.EmailField()
class Meta:
model = User
fields = ["username", "email", "password1", "password2"]
class SuperUserForm(forms.ModelForm):
class Meta:
model = SpecialUser
fields = ['flag']
widgets = {
'flag': CheckboxInput(attrs={'class': 'flag'}),
}
views.py
def register(request):
if request.method == 'POST':
form = RegisterForm(request.POST)
sp_form = SuperUserForm(request.POST)
if form.is_valid() and sp_form.is_valid():
user = form.save()
sp_form = sp_form.save(commit=False)
sp_form.user = user
sp_form.save()
messages.success(request, 'Account created!')
return redirect('login')
else:
form = RegisterForm()
sp_form = SuperUserForm()
messages.warning(request, 'Your account cannot be created.')
return render(request, 'register.html', {'form': form})
HTML form code:
<form method="post" class="form-group">
{% csrf_token %}
{{ form|crispy }}
<label for="flag">Special User: </label>
<input id="flag" class="flag" type="checkbox" name="flag">
<button type="submit" class="btn btn-success">Sign up</button>
</form>

In your views.py you're creating a local variable for a SpecialUser form, sp_form, that is neither loaded into the context data nor templated in the HTML form code.
You can load sp_form into the context data by adding it to the context dict passed to render(). This will allow the template to see the variable. For example:
return render(request, 'register.html', {'form': form, 'sp_form': sp_form})
And then you can render it in the template. For example, underneath the main form:
{{ form|crispy }}
{{ sp_form|crispy }}

For starters this is generally not how you would want to extend the user model in a Django application. You would want to inherit from AbstractUser and add your fields to that model and run migrations. At least in this case, that would be ideal, then you could simply define the field on your RegisterForm.fields and let {{ form|crispy }} render the form for you. Naturally, you could call form.save() and move on with your life.
To clarify why this may not be working, it is generally not good practice to render your own fields for a form unless absolutely necessary. If you insist on doing it this way, note that Django prefixes the id with id_ so in your case it would be <label for="id_name">...</label> and <input id="id_flag" ...

Related

how can I customize auto generated django form?

I've created a form on Django app with its builtin forms class.
here is my forms.py file.
# import form class from django
from dataclasses import field
from django import forms
from .models import #MYMODEL#
class myForm(forms.ModelForm):
class Meta:
model = #MYMODEL#
fields = "__all__"
and my view function in views.py
def index(request):
context = {}
form = myForm(request.POST or None, request.FILES or None)
if form.is_valid():
form.save()
context['form'] = form
return render(request, "index.html", context)
and finally the page (index.html) that shows the form
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Kaydet">
</form>
So, what I need to do is to set custom input types like text or select box since the auto-generated form includes only text inputs.
You can use Widgets.
This is an example:
class myForm(forms.ModelForm):
class Meta:
model = #MYMODEL#
fields = "__all__"
widgets = {
'category': forms.Select(attrs={"class": "form-control"}),
'title': forms.TextInput(attrs={"class": "form-control"}),
'description': forms.Textarea(attrs={"class": "form-control"}),
}

Dynamically add field to a form python django

I want to have a Django form in which a user can add multiple stop_name,stop_longitude,stop_latitude using the Add more button inside. Let's suppose a user has 3 stop_names so he will have to click on the Add more twice. And on each add more above fields will populate again.
I am new to Django so I need some help.
This is my model
class SupplyChainStops(models.Model):
ingredient = models.ForeignKey(Ingredients, null=True, on_delete=models.CASCADE)
stop_name = ArrayField(models.CharField(max_length=1024, null=True, blank=True))
stop_longitude = ArrayField(models.CharField(max_length=500, null=True, blank=True))
stop_latitude = ArrayField(models.CharField(max_length=500, null=True, blank=True))
Okey using formset factory i very straight forward and simple to render multiple fields for user to fill in their information. First of all you would need to create forms.py in your project and then import django's formset_factory in forms. We would do something like so:
from django.forms import formset_factory
from .models import SupplyChainStops
# Here we are creating a formset to handle the maniplations of our form to
# have extra field by using the extra parameter to formset_factory
# and also we can add a delete function to allow users to be able to delete
Formset = formset_factory(SupplyChainStops, fields=[' stop_name',' stop_longitude','stop_latitude'], extra=4, can_delete=True)
# I have set the formset to give us an extra field of four and enable users
# to delete
Now we are going to work on the view to handle our formset.
from django.views.generic.edit import FormView
from .forms import Formset
class formsetView( FormView):
template_name = 'formset.html'
form_class = Formset
success_url = '/'
In our template we will do something like this .
<form method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Add">
</form>
Doing this in a function base view
from .forms import Formset
def formset_view(request):
if request.method == 'POST':
formset = Formset(request.POST,)
if formset.is_valid():
formset.save()
else:
formset = ()
return render (request, 'formset.html',{'formset':formset})
In your HTML Template
<form method="post">{% csrf_token %}
{{ formset.as_p }}
<input type="submit" value="Add">
</form>

Unable to add data to databse from models forms django

I am trying to send data from django forms to backend sqlite3. But I am unable to do so. I am not also getting any error or warning that help me to sort it out.
Here is models.py file
from django.db import models
GENDER_CHOICES = [
('Male', 'M'),
('Female', 'F')]
class upload(models.Model):
name = models.CharField(max_length=100)
gender = models.CharField(max_length=10, choices=GENDER_CHOICES)
phone = models.CharField(max_length=50,null=True)
email= models.EmailField(max_length=50,null=True)
file=models.FileField(upload_to='uploads/')
def __str__(self):
return self.name
here is forms.py file
from django.forms import ModelForm
from .models import upload
class uploadForm(ModelForm):
class Meta:
model = upload
fields = ['name', 'gender', 'phone', 'email','file']
Here is view.py file
from django.shortcuts import render
from .forms import uploadForm
from django.shortcuts import render
def home(request):
if request.method == 'POST':
form = uploadForm()
if form.is_valid():
form=form.save()
return HttpResponseRedirect('/')
else:
form = uploadForm()
return render(request,'home.html',{'print':form})
I am unable to understand where is the issue
This is how template file look like
<form method="post">
{% csrf_token %}
{{ print.as_p }}
<input type="submit" value="Submit">
</form>
EDIT
This issue is with FileField, I removed it, and it start saving in django database. What I want is to save file in media folder and other data in database
I also added enctype="multipart/form-data" in form
I don't think your actually sending anything to the database.
Where is says form = uploadForm() you need state you want the posted data to be sent. so this needs to be form = uploadForm(request.POST) it should then work I believe. Also when saving the form, remove the form=form.save() and leave it as form.save()
Try it out and let us know?
Solution to my post
For handling files, I need to add encryption type to my form as
enctype="multipart/form-data"
Once I added that, to access the files I should use request.FILES along with request.POST
So now I have this home function in views.py file
def home(request):
if request.method == 'POST':
form = uploadForm(request.POST,request.FILES)
if form.is_valid():
form.save()
return HttpResponseRedirect('/')
else:
form = uploadForm()
return render(request,'home.html',{'print':form})
and my template form looks like
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ print.as_p }}
<input type="submit" value="Submit">
</form>
Credit : https://youtu.be/Rr1-UTFCuH4?t=244

login form keeps telling my username already exists django

So I am trying to make a login form for a django website using a forms.py file to generate a form in my html. I have already made a registration form using the same methods and that works fine but for some reason my login form keeps working like a registration form and saying that my username already exists. i assume it is just a litle mistake but I can't figure out what it is exactly.
forms.py
from django.contrib.auth.models import User
from django import forms
class LoginForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput)
class Meta:
model = User
fields = ['username', 'password']
models.py
class LoginFormView(View):
form_class = LoginForm
template_name = 'intranet/login_form.html'
def get(self, request):
form = self.form_class(None)
return render(request,self.template_name,{'form': form})
def post(self,request):
form = self.form_class(request.POST)
if form.is_valid():
username = request.POST.get['username']
password = request.POST.get['password']
user = authenticate(username=username,password=password)
if user is not None:
if user.is_active:
login(request,user)
return redirect('werknemers_list')
return render(request, self.template_name, {'form': form})
login_form.html
<h1>Log in</h1>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="log in" />
</form>
urls.py
from django.conf.urls import url
from intranet import views
urlpatterns = [
url(r'^$', views.LoginFormView.as_view(), name='login'),
url(r'^registreer$', views.UserFormView.as_view(), name='registreer')]
You shouldn't use a ModelForm for this. That will always call the model validation, which in this case checks for username uniqueness.
Use a standard Form class instead.

Django form.is_valid() not validating

I can't seem to get my form to validate with .is_valid()
The associated View
def edit_social_media(request, user_id):
#verify a user is allowed to access the page
# user is saving the form
if request.POST:
form = SocialMediaForm(request.POST)
if form.is_valid():
...
return HttpResponseRedirect(reverse(users.profile,
args = (request.user.id,)))
# displaying the initial form
else:
try:
form = SocialMediaForm(instance = SocialMedia.objects.get(user = request.user))
except SocialMedia.DoesNotExist:
form = SocialMediaForm()
return render_to_response('users/edit_social_media.html', {'form': form, 'user' : user},
context_instance = RequestContext(request))
Forms.py
class SocialMediaForm(forms.ModelForm):
class Meta:
model = SocialMedia
fields = {'twitter', 'facebook', 'linkedin'}
the template
<form method="post" action=''>
{% csrf_token %}
<div class="form-col-left">
<p>
{{ form.as_p }}
</p>
</div>
<div class="submitbutton">
<input type="submit" class="green button" value="Save Social Media Settings" />
</div>
</form>
The model
from django.db import models
from django.contrib.auth.models import User
class SocialMedia(models.Model):
class Meta:
app_label = 'dashboard'
#the user associated with the data
user = models.ForeignKey(User)
#Twitter, Facebook, and Linkedin pages
twitter = models.URLField("Twitter")
facebook = models.URLField("Facebook")
linkedin = models.URLField("Linkedin")
Some help would be greatly appreciated. I'm rather new to django so I've been missing some of the smaller nuances. I've found some similar issues on stackoverflow related to bound vs unbound forms, but from reading the documentation I think I properly bound the data to the form.
Since this is a ModelForm it would help seeing the actual Model that this form is using, the SocialMedia class. Also I am not sure what you mean by not getting it to validate but I am assuming that the is_valid() method returns False.
My guess is that the method returns False because you are not setting the user on the form. In the POST dictionary you don't have the user or user_id. Add the following line before the "if form.is_valid()" statement:
form.instance.user = self.request.user
Hope this works.

Categories