Python/Django - radiobutton with submit button instead of buttons - django

I have a Django application where I want to have a setting: if the email is sent automatically or manually. What I have works, but not in the style that I want it.
At the moment I have 2 buttons where you can click them and the setting is set to what you want. But what I would want is radio buttons, that are also already checked or unchecked, depending on the setting.
What I have now is:
model.py
class AutoSendMail(models.Model):
auto = models.BooleanField(default=False)
manual = models.BooleanField(default=True)
send_type = (
('manual', 'MANUAL'),
('auto', 'AUTO')
)
type = models.CharField(max_length=6, choices=send_type, default="manual")
forms.py
CHOICES = [('manual', 'MANUAL'),
('auto', 'AUTO')]
class SendMailSetting(ModelForm):
class Meta:
model = AutoSendMail
fields = ['auto', 'manual', 'type']
widgets = {
"manual": forms.RadioSelect(attrs={'class': 'form-control'}),
"auto": forms.RadioSelect(attrs={'class': 'form-control'}),
'type': forms.ChoiceField(choices=CHOICES, widget=forms.RadioSelect)
}
views.py
class AutoSendView(generic.TemplateView):
template_name = 'core/mailbox/autoSendMail.html'
context_object_name = 'autosend'
extra_context = {"mailbox_page": "active"}
form_class = SendMailSetting
def post(self, request, *args, **kwargs):
if request.POST.get('manual'):
logger.info("Set to: manual email send")
AutoSendMail.objects.filter(pk=1).update(auto=True,
manual=False,
type="manual")
elif request.POST.get('auto'):
logger.info("Set to auto email send")
AutoSendMail.objects.filter(pk=1).update(auto=True,
manual=False,
type="auto")
return HttpResponseRedirect(self.request.path_info)
autoSendMail.html
<form class="card" action="" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<div class="card-body">
<h3 class="card-title">Update Mail Settings</h3>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label class="form-label">Send E-mail</label>
<button type="radio" name="manual" value="manual" class="btn btn-primary">Manual</button>
<button type="radio" name="auto" value="auto" class="btn btn-primary">Automated</button>
</div>
</div>
</div>
</div>
</form>
Currently it looks like this:
And I would like it to look more like this:
At the moment I'm only using a POST request, and I guess, to inform the user I also need to use a GET request, but I can't get it to work. Also I'm now not using the form, I tried to use it in different ways but I can't get the result I want..
Can someone help me?

You had created a modelForm but you are not using it here. Anyway for basic method you can try below method
<input type="radio" name="update_type" value="manual">Manual</input>
<input type="radio" name="update_type" value="auto">Automated</input>
<button type="submit" class="btn btn-primary">Submit</button>
views.py
def post(self, request, *args, **kwargs):
update_type = request.POST.get('update_type'):
if update_type == 'manual':
"update db with manual to true"
else:
"update the db with auto to true"

Related

Django M2M Form

i try to do checkboxes in form for M2M field, but have this error, have no idea how to fix it. Google didn't help me, i tried.
When i render objects as list, i can select few objects and save it, so problem is not in views.py ,but it doesn't work with checkboxes.
My code:
forms.py
class CheckoutForm(forms.ModelForm):
class Meta:
model = Checkout
fields = ('dishes', 'user')
def __init__(self, *args, **kwargs):
super(CheckoutForm, self).__init__(*args, **kwargs)
self.fields["dishes"].widget = CheckboxSelectMultiple()
self.fields["dishes"].queryset = Dish.objects.all()
so only way that i can see an form error:
render form fields - send a empty form - put back {{ form.as_p }} - i can see an error "field is required"
page.html
<form class="p-2" action="{% url 'make_order' %}" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<select name="user">
<option value="{{ user.id }}">{{ user }}</option>
</select>
<div
class="row row-cols-1 row-cols-md-5 g-2"
style="margin-left: -40px"
>
{% for dish in dishes %}
<div class="col">
<div class="card" style="width: 14rem">
<img
class="card-img-top"
style="width: 220px; height: 240px"
src="{{ dish.image.url }}"
alt="Card image cap"
/>
<div class="card-body">
<h5 class="card-title">{{ dish.name }}</h5>
<p class="card-text">Description: {{ dish.description }}</p>
<p class="card-text">Ingredients: {{ dish.ingredients }} g</p>
<p class="card-text">Serving size: {{ dish.serving_size }} g</p>
<p class="card-text">Price: {{ dish.price }} UAH</p>
<input
type="checkbox"
class="btn btn-primary"
name="dishes"
id="{{ dish.id }}"
value="{{ dish.id }}"
/>Add to cart
</div>
</div>
</div>
{% endfor %}
<input type="submit" value="ADD" class="btn btn-primary" />
</form>
views.py
class OrderView(LoginRequiredMixin, CreateView):
model = Checkout
template_name = "food_order/make_order.html"
form_class = CheckoutForm
success_url = "/order/"
login_url = "/login/"
raise_exception = True
def form_valid(self, form):
print('i am here')
instance = form.save(commit=False)
instance.user = self.request.user
instance.save()
dishes = form.cleaned_data["dishes"]
for dish in dishes:
dish, created = Dish.objects.get_or_create(name = dish)
dish.save()
instance.dishes.add(dish)
instance.save()
print(instance.dishes)
print(instance)
form.save_m2m()
return super(OrderView, self).form_valid(form)
def get_context_data(self, **kwargs):
context = super(OrderView, self).get_context_data(**kwargs)
context["dishes"] = Dish.objects.all()
context["orders"] = Checkout.objects.all()
return context
I don't think you need to be tinkering with __init__ here when setting the widget. It may be overwriting your values for a modelform.
Try:
class CheckoutForm(forms.ModelForm):
class Meta:
model = Checkout
fields = ('dishes', 'user',)
widgets = {'dishes': forms.CheckboxSelectMultiple() }
This should work as m2m fields have the ModelMultipleChoiceField by default. If you want to make it all explicit, you can go with:
class CheckoutForm(forms.ModelForm):
dishes = forms.ModelMultipleChoiceField(
queryset=Dish.objects.all(),
widget=forms.CheckboxSelectMultiple,
)
class Meta:
model = Checkout
fields = ('dishes', 'user',)
If you are formatting the checkboxes by hand
make sure they have name="dishes" (assuming dishes is the name of the field in your Checkout model) and value="<the dish id>"
You may also need to grab the values submitted with request.POST.getList('dishes'), otherwise you will ony get one value submitted

I am trying to get POST request but django response with GET request

I am trying to get the post request and i have tried everything it is still getting me get requests.
Please Help.
I have tried using that i saw in other problems displayed here. but it is not working for me.
{% csrf_token%}
Item name
{{form.item_name}}
Quantity
{{form.quantity}}
<div class="form-group">
<label for="address">Address</label>
{{form.address}}
</div>
<div class="modal-footer d-flex justify-content-center">
<button type="submit" id="submit" class="btn btn-success" data-dismiss="modal" >Donate</button>
</div>
</form>
This is my view file
#this is my view
#login_required(login_url='loginPage')
def home(request):
form = DonateForm()
print(request.user.id)
get_user = user_info.objects.get(id=request.user.id)
print('Inside Home View')
print(get_user)
print(request)
if request.method == 'POST':
form = DonateForm(request.POST)
print('Inside Home Page')
if form.is_valid():
print('Form is valid!!')
user = form.save()
Donate.objects.create(user_name = user,item_name=form.cleaned_data['item'],quantity=form.cleaned_data['itemquantity'])
else:
messages.add_message(request,messages.INFO,'Your details are Incorrect!!')
else:
print('No Post Request!!')
return render(request,'donate/home.html',{'form':form,'get_user':get_user})
Here is my Models.py
class Donate(models.Model):
user_name = models.ForeignKey(user_info,on_delete=models.CASCADE)
item_name = models.CharField(max_length=30,null=False , blank=False, default ="None")
quantity = models.IntegerField(null=False,blank=False,default=0)
address = models.CharField(max_length=100 , null=False , blank= False, default="None")
def __str__(self):
return f"{self.user_name.user.username} donated {self.item_name}"
Please try to add the method in the <form>, like this:
<form method="post" action="#">
{% csrf_token %}
......
<button type="submit" id="submit" class="btn btn-success" data-dismiss="modal" >Donate</button>
</form>

How to Add Subscribe option in a Django Website

I am trying to add a subscribe to newsletter option on a django website. When a visitor enters
a valid email address it will be stored in the database. The subscription form is part of the base.html template.
All other templates of the website extend this template. I wish to implement this in a DRY way.
This is how I am trying to do it :
forms.py :
from dataclasses import fields
from django import forms
from . models import Subscribers, MailMessage
class SubcribersForm(forms.ModelForm):
class Meta:
model = Subscribers
fields = ['email', ]
views.py :
def base(request):
if request.method == 'POST':
form = SubcribersForm(request.POST)
if form.is_valid():
form.save()
return redirect('/')
else:
form = SubcribersForm()
context = {'form': form}
return render(request, 'base.html', context)
The template: base.html
<form method = "POST" class="signup-form form-inline justify-content-center pt-3">
{% csrf_token %}
<div class="form-group">
<label class="sr-only" for="semail">{{context}}</label>
<input type="email" id="semail" name="semail1" class="form-control mr-md-1 semail" placeholder="Enter email">
</div>
<button type="submit" class="btn btn-primary">Subscribe</button>
</form>
models.py :
class Subscribers(models.Model):
email = models.EmailField(null=True)
date = models.DateTimeField(auto_now_add=True)
def __str__self(self):
return self.email
In the backend, I can see that the Subscribers table has been created. However, when I enter any email address from the home
page and click subscribe button it does not store it in the database. What could be the issue here?
It could be that you have no action declared in your form. Assuming you have a url like this:
path('add-subscriber/', base, name='base'),
...your form would need a way to call it upon submit, like this:
<form method = "POST" action="{% url 'base' %}" class="signup-form form-inline justify-content-center pt-3">
{% csrf_token %}
<div class="form-group">
<label class="sr-only" for="semail">{{context}}</label>
<input type="email" id="semail" name="semail1" class="form-control mr-md-1 semail" placeholder="Enter email">
</div>
<button type="submit" class="btn btn-primary">Subscribe</button>
</form>

how to save many to many field using django custom forms

how can i save many courses to the student table .I want to keep my design like this.This code is not saving the many to many field(courses) through AddStudentForm.It returns an error with courses variable.If i used CharField instead of ManyToManyField in models for courses then the code works perfectly,but when i use ManyToManyField then it is not working.
it throws courses when i used form.errors .If i didn't use form.errors then it doesn't give any error neither saves the data.
how can i save many courses to the student table .I want to keep my design like this.This code is not saving the many to many field(courses) through AddStudentForm.It returns an error with courses variable.
models.py
class Course(models.Model):
title = models.CharField(max_length=250)
price = models.IntegerField(default=0)
duration = models.CharField(max_length=50)
def __str__(self):
return self.title
class Student(models.Model):
name = models.CharField(max_length=100)
courses = models.ManyToManyField(Course)
email = models.EmailField()
image = models.ImageField(upload_to='Students',blank=True)
def __str__(self):
return self.name
forms.py
class AddStudentForm(forms.ModelForm):
# courses = forms.ModelMultipleChoiceField(widget=forms.CheckboxSelectMultiple, queryset=Course.objects.all())
class Meta:
model = Student
fields = ['name','courses','email','image']
def __init__(self, *args, **kwargs):
super(AddStudentForm, self).__init__(*args, **kwargs)
self.fields["courses"].widget = CheckboxSelectMultiple()
self.fields["courses"].queryset = Course.objects.all()
views.py
def addstudent(request):
courses = Course.objects.all()
if request.method == 'POST':
form = AddStudentForm(request.POST,request.FILES)
if form.is_valid():
student = form.save(commit=False)
course = form.cleaned_data['courses']
student.courses = course
student.save()
# student.courses.add(course)
# student.save_m2m()
# student.courses.set(course) # this method also didn't helped me
messages.success(request, 'student with name {} added.'.format(student.name))
return redirect('students:add_student')
else:
# messages.error(request,'Error in form.Try again')
return HttpResponse(form.errors) # this block is called and returns courses
else:
form = AddStudentForm()
return render(request,'students/add_student.html',{'form':form,'courses':courses})
add_student.html
<form action="{% url 'students:add_student' %}"
method="post"
enctype="multipart/form-data">
{% csrf_token %}
<div class="form-group">
<h5>Full Name <span class="text-danger">*</span>
</h5>
<div class="controls">
<input type="text" name="name" class="form-
control" > </div>
</div>
<div class="form-group">
<h5>Courses<span class="text-danger">*</span>
</h5>
<div class="controls">
{% for course in courses %}
<input name ="courses" type="checkbox" id="course-
{{course.id}}" value="{{course.title}}">
<label for="course-{{course.id}}">{{course.title}}
</label>
{% endfor %} # i think the problem is here.
</div>
</div>
<div class="form-group">
<h5>Email <span class="text-danger">*</span></h5>
<div class="controls">
<input type="text" name="email" class="form-
control" required> </div>
</div>
</div>
<div class="form-group">
<h5>Image <span class="text-danger">*</span></h5>
<div class="controls">
<input type="file" name="image" class="form-control" > </div>
</div>
<div class="text-xs-right">
<button type="submit" class="btn btn-info">Add</button>
</div>
</form>
You need to save first before you can assign m2m, the system needs the primary key of the Student model before it can insert into the m2m table.
if form.is_valid():
student = form.save(commit=False)
course = form.cleaned_data['courses']
student.save()
# this will save by itself
student.courses.set(course)

Django form error message showing despite selecting something from dropdown

I have a Django model which is:
class Account(models.Model):
name = models.CharField(max_length=50, blank=True)
number = models.CharField(max_length=16, blank=True)
I'd like to create a form where user can select an existing account's phone number from a dropdown list. So in forms.py, I have:
class AccountSelectForm(forms.Form):
phone_num_err_msgs = {'required': "You must select a phone number to send this message."}
phone_number = forms.CharField(required=True, error_messages=phone_num_err_msgs)
selected_group_ids = forms.CharField(required=True, widget=forms.HiddenInput)
launch_datetime = forms.CharField(required=True)
In views.py, I have:
class AccountSelectView(LoginRequiredMixin, FormView):
template_name = 'campaigns/send.html'
form_class = AccountSelectForm
success_url = reverse_lazy('campaigns:taskq_list')
def get_context_data(self, **kwargs):
data = super(AccountSelectView, self).get_context_data(**kwargs)
data['groups'] = Group.objects.all()
data['campaign'] = Campaign.objects.get(id=self.request.GET['cam_id'])
data['accounts'] = Account.objects.all()
return data
def form_valid(self, form):
# If we insert pdb, we never reach here
#import pdb
#pdb.set_trace()
data = form.cleaned_data
campaign_id = self.request.GET['cam_id']
# ... do other form validation stuff here
return super(ConversationSendView, self).form_valid(form)
In send.html, I have:
<form action="" method="post">
{% csrf_token %}
<!-- A couple of other fields to collect user input -->
<div class="form-group">
<p><b>Step 3: Select aphone number to send the message FROM:</b></p>
{{ form.phone_number.errors }}
<select id="phone" style="width: 380px;">
<option value="">--------</option>
{% for a in accounts %}
<option value="{{ a.id }}">{{ a.number }}</option>
{% endfor %}
</select>
<div class="page-btns">
<input type="submit" class="btn btn-primary" value="Send Message to Selected Group(s)" />
</div>
</form>
But despite selecting the entry from the dropdown list (and all other required forms) before submitting, I keep seeing the phone_num_err_msgs on the HTML page [please see the screenshot here].
Is there something that I'm missing? Where (which file) can I import pdb and see why it is returning an error? I'm new to Django, so this is very likely a silly mistake/overlook. Thanks in advanced for the answers!
There are a few things wrong here. The immediate cause is that you are missing name="phone_number " in your select tag, so the browser is not sending any data for that element.
But it is not clear why you are constructing that element manually anyway. Rather than defining a CharField and ignoring it, you should be using a ModelChoiceField, which will automatically give you a select box with all the accounts in.
class AccountSelectForm(forms.Form):
...
phone_number = forms. ModelChoiceField(queryset=Account.objects.all())
...
{{ form.phone_number.errors }}
{{ form.phone_number }}