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>
Related
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" ...
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
I want a django form which is an instance of a User and get an html form as constitued by radio buttons to activate or deactivate a permission.
A html code of this kind is expected at the end:
<div class="form-group">
<label for="change_user">Can edit user:</label>
<div class="labeled" id="change_user">
<input class="with-gap" name="change_user_False" type="radio" id="change_user_False" value="False">
<label for="change_user_False">No</label>
<input class="with-gap" name="change_user_True" type="radio" id="change_user_True" value="True" checked="">
<label for="change_user_True">Yes</label>
</div>
</div>
The example permission here will be "change_user" and the goal is to handle all the process in a clean django form. I do not know what is the most appropriate way...
Use on a simple form and manage everything in the clean function by passing in parameter a User object.
from django import forms
class PermissionForm(forms.Form):
change_user = forms.ChoiceField(widget=forms.RadioSelect, choices=((True, 'No'), (False, 'Yes')), required=True)
def __init__(self, *args, **kwargs):
self.fields['change_user'].initial = select_user.has_permission('auth.change_user ')
def clean(self, select_user):
if self.cleaned_data['change_user']:
select_user.permissions.add('change_user')
Or use a form of the User instance:
from django.contrib.auth.models import User
from django import forms
class ProfileForm(forms.ModelForm):
class Meta:
model = User
fields = []
widget = ...
But how to generate a widget in radioselect on a permission and catch errors when returned data wrong ?
You can resolve your question using Django UpdateView with a ModelForm like this example (See the comments in order to understand what's going on):
forms.py:
from django import forms
from YOUR_APP_NAME import models
class UserPermissionsForm(forms.ModelForm):
change_user = forms.ChoiceField(
widget=forms.RadioSelect,
choices=[(True, 'Yes'), (False, 'no')],
required=True # It's required ?
)
class Meta:
model = models.YOUR_MODEL_NAME
fields = ('change_user',) # I'll use only one field
views.py:
from django.views.generic import UpdateView
from django.urls import reverse_lazy
from django.contrib import messages
from django.contrib.auth.models import Permission
from YOUR_APP_NAME import models, forms
class UserPermissionView(UpdateView):
model = models.YOUR_MODEL_NAME
template_name = 'user_permission.html' # Your template name
form_class = forms.UserPermissionsForm
initial = {} # We'll update the form's fields by their initial values
def get_initial(self):
"""Update the form_class's fields by their initials"""
base_initial = super().get_initial()
# Here we'll check if the user has the permission of 'change_user'
user_has_permission = self.request.user.user_permissions.filter(
codename='change_user'
).first()
base_initial['change_user'] = True if user_has_permission else False
return base_initial
def form_valid(self, form):
"""
Here we'll update the user's permission based on the form choice:
If we choose: Yes => Add 'change_user' permission to the user
No => Remove 'change_user' permission from the user
"""
change_user = form.cleaned_data['change_user']
permission = Permission.objects.get(codename='change_user')
if change_user == 'True':
self.request.user.user_permissions.add(permission)
# Use django's messaging framework
# We'll render the results into the template later
messages.success(
self.request,
'Updated: User [{}] Can change user'.format(self.request.user.username)
)
else:
self.request.user.user_permissions.remove(permission)
messages.success(
self.request,
'Updated: User [{}] Cannot change user'.format(self.request.user.username)
)
return super().form_valid(form)
def get_success_url(self):
"""
Don't forget to add your success URL,
basically use the same url's name as this class view
"""
# Note here, we'll access to the URL based on the user pk number
return reverse_lazy('user_permissions', kwargs={'pk': self.request.user.pk})
urls.py:
from django.urls import path
from YOUR_APP_NAME import views
urlpatterns = [
path(
'client/<int:pk>/', # Access the view by adding the User pk number
views.UserPermissionView.as_view(),
name='user_permissions'
),
... # The rest of your paths
]
And finally the template:
user_permissions.html:
{% if messages %}
{% for message in messages %}
{{ message }}
{% endfor %}
<br><br>
{% endif %}
<div>User: {{ user.username }}</div>
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<button type='submit'>Submit</button>
</form>
And here are some screenshots of the flow of this solution:
And of course, you can check if the add/remove actions of the permission under the Django Admin Panel.
I am building a web application on django. As part of this, I have created one html form like following:
<form method="post" action="/voting/add_state/">{% csrf_token %}
State name:<br>
<input type="text" name="state_name"><br>
<input type="submit" value="Submit">
</form>
In models.py I have added unique constraint validation on name like following:
class State(models.Model):
name = models.CharField(max_length=200, unique=True)
vote_counted = models.BooleanField(default=False)
So for duplicate name, it throws a unique constraint error which I would like to capture in the template. Can anyone please give any suggestion.
Create a form based on your model
#forms.py
from django import forms
from .models import State
class StateForm(forms.ModelForm):
class Meta:
model = State
fields = ('name',)
now use this form on your views
#views.py
from django.views.generic import FormView
from .forms import StateForm
class MyView(FormView):
template_name = 'template.html'
form_class = StateForm
success_url = '/my-url-to-redirect-after-submit/'
template.html
<form method="post">
{% csrf_token %}
Name
{{ form.name }}
{{ form.name.errors }}
<input type="submit" value="Create">
</form>
Django has Form processing built in. Django has "Model Forms", which automatically render the form for your model. If you pass it through the view and reference it in the context it will automatically generate the html for you, but if you would like more control over what is rendered in the template then you can reference the form attributes that Django Model Form produces.
I strongly suggest working within the framework Django provides to you for building forms; it provides a lot of boilerplate code for building, validating and abstracting forms and is especially competent for simple forms like these.
Here is an example:
models.py
class State(models.Model):
name = models.CharField(max_length=200, unique=True)
vote_counted = models.BooleanField(default=False)
forms.py
class StateForm(forms.ModelForm):
model = State
fields = (name,)
views.py
from django.views.generic.edit import FormView
class StateForm(FormView):
template_name = 'state_form.html'
form_class = StateForm
success_url = '/thanks/'
state_form.html (example of auto generated form)
{{ form }}
state_form.html (example of custom form)
<form action="/" method="post">
{% csrf_token %}
{{ form.errors }}
{% for field in form %}
<input type="{{ field.type }}" name='{{ field.name }}' class="submit" value="{{ field.value}}">
{% endfor %}
<input type="submit" name='submit" value="Submit">
</form>
References:
Django Forms:
https://docs.djangoproject.com/en/1.9/topics/forms/
Django Model Forms: https://docs.djangoproject.com/en/1.9/topics/forms/modelforms/
Django Generic Views:
https://docs.djangoproject.com/en/1.9/ref/class-based-views/generic-editing/#django.views.generic.edit.FormView
You could create a form for State model and create the validator, so if the user try with a duplicate name, the form raise a message something like this:
models.py
class State(models.Model):
name = models.CharField(max_length=200, unique=True)
vote_counted = models.BooleanField(default=False)
forms.py
def unique_name(value):
exist = State.objects.filter(name=value)
if exist:
raise ValidationError(u"A state with the name %s already exist" % value)
class StateForm(forms.Form):
name = forms.CharField(label=('Name:'), validators=[unique_name])
Then you just need to render the StateForm in the template.
I am newbie in python and django and I am facing difficulty in storing various fields of html page into database.
E.g, I have a html page which contains 5 fields and one submit button . On submitting the form, I want all values from html form should be stored in table of the given database.
Please help me in this.
models.py
from django.contrib.auth.models import User
from django.db import models
class AllocationPlan(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=50)
data = models.CharField(max_length=4096)
total = models.DecimalField(max_digits=10, decimal_places=2)
forms.py
from django import forms
from django.forms import ModelForm
from app_name.models import AllocationPlan
class AllocationPlanForm(ModelForm):
class Meta:
model = AllocationPlan
views.py
from django.shortcuts import render
from app_name.forms import AllocationPlanForm
def add(request):
if request.method == 'POST':
form = AllocatinPlanForm(request.POST)
if form.is_valid():
form.save()
return render(request, 'page.html', {
'form': AllocationPlanForm()
})
page.html
<form method="post">{% csrf_token %}
{% for field in form %}
{{field}}
<input type="submit" value="Submit"/>
{% endfor %}
</form>
You should approach this from the angle of models, which map the model's attributes to database fields and can handily be used to create a form. This is called Object-Relational Mapping.
Start by creating (or modifying) models.py in your app's folder, and declare the model there (Essentially the fields you want to be stored). As mentioned, see Django's tutorials for creating forms and model-form mapping.