Sending an SMS to each group based on form selection(s) - python

So I have an SMS app working perfectly with a Django form. I have an sqlite table "Employees" and each employee has one relationship of either "dcare," "admin," or "recreation". In my form, I used a radio button to select one of these relationships and the messages are sent to those employees...no problem there. The issue is when I switched it from a radio button to a multiple choice widget.
So I am having trouble finding the appropriate language/syntax of "For each group selected, send the SMS to each person in that group."
Views.py below
def contact(request):
if not request.user.is_authenticated():
return HttpResponseRedirect('/')
else:
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
client = twilio.rest.TwilioRestClient('xxxx', 'xxxx')
recipients = employees.objects.filter(group__contains=cd['togroup'])
#check to see which group is selected
if cd['togroup'] != "everyone":
for recipient in recipients:
client.messages.create(body=cd['message'],to=recipient.phone_number, from_='+xx')
return HttpResponseRedirect('/contact/thanks/')
else:
#if "everyone" is selected, change recips to all
recipients = employees.objects.all()
for recipient in recipients:
client.messages.create(body=cd['message'], to=recipient.phone_number, from_='+xxxx')
return HttpResponseRedirect('/contact/thanks/')
else:
form = ContactForm()
return render(request, 'contact_form.html', {'form':
form})

Assuming cd['togroup'] returns an array of selected choices e.g. ['dcare', 'recreation']. From your flow (For each group selected, send the SMS to each person in that group.), I would do:
for to_group in cd['togroup']:
recipients = employees.objects.filter(group=to_group)
for recipient in recipients:
client.messages.create(body=cd['message'],to=recipient.phone_number, from_='+xx')

Related

form initials do not show

i am trying to set the form initials for the sender field as the logged in user, and it does not show. i removed the if request method statement and adjusted the indentaion and the initials showed. I am stuck, i believe the form is supposed to have that request method statement. i've gone through the documentation and it says the post method binds the data and submits, but there isn't any data when the page is refreshed or newly loaded. what could be wrong?
views.py
def transfer(request):
profile = Profile.objects.get(user=request.user)
if request.method == "POST":
form = TransferForm(request.POST,initial={"sender": profile})
if form.is_valid():
print(form)
form.save()
sender = models.sendcoins.objects.get(sender=request.user.profile)
profile2 = Profile.objects.get(username=receiver)
user_wallet = wallet.objects.get(owner=profile)
print(receiver)
temp = sender # NOTE: Delete this instance once money transfer is done
receiver = models.wallet.objects.get(owner=profile2) # FIELD 1
transfer_amount = sender.amount # FIELD 2
sender = models.wallet.objects.get(owner=profile) # FIELD 3
# Now transfer the money!
sender.balance = sender.balance - transfer_amount
receiver.balance = receiver.balance + transfer_amount
# Save the changes before redirecting
sender.save()
receiver.save()
temp.delete() # NOTE: Now deleting the instance for future money transactions
else:
return(HttpResponse("form is not valid"))
else:
form = TransferForm()
return render(request, "sendcoins.html", {"form": form})

how to use context_processor properly in django

Here I am trying to redirect to another page if the form is submitted successfully but this code is not working properly .The code saves the form data sends the email , everything is fine but the problem is while redirecting to another page if the form succeed. The error I get is:
Django Version: 2.0.6
Exception Type: ValueError
Exception Value:
dictionary update sequence element #0 has length 0; 2 is required
context_processor.py
def volunteer_page2(request):
volunteer = Volunteer.objects.all().order_by('date')
if request.method == 'POST':
form = VForm(request.POST or None)
if form.is_valid():
name = form.cleaned_data['name']
email = form.cleaned_data['email']
message = "{0} with email address {1} has sent you new message \n\n{2}".format(name, email, form.cleaned_data['message'])
form.save(commit = False)
try:
send_mail(name, message, 'appname <settings.EMAIL_HOST_USER>', ['myemail'])
except:
return HttpResponse('Invalid header found')
form.save()
messages.success(request, 'Success')
return redirect('volunteer_page')
else:
messages.error(request, "Sorry try again")
else:
form = VForm()
return {'volunteer': volunteer, 'form':form}
views.py
def about_page(request):
about = About.objects.all().order_by('date')
banner = Banner.objects.all()
testimonial = Testimonial.objects.order_by('-pk')[0:2]
nav = Nav.objects.all()
footer = Footer.objects.all()
latest_event2 = Events.objects.order_by('-pk')[0:2]
context = {
'about': about,
'testimonial': testimonial,
'footer':footer,
'banner': banner,
'nav': nav,
'latest_event2': latest_event2,
}
return render(request, 'myapp/about.html', context)
settings.py
'myapp.context_processor.volunteer_page2'
Django's context processor should always return dictionary. In your code you are returning HttpResponse also. This is problem.

2 forms, 1 view, 2 SQL tables in Django

I'm struggling to understand how to submit data from two django forms into two separate database tables from the same view. I only want one submit button. While this question got me closer to the solution, I'm getting errors and the data is not writing to the database. I think this code actually checks the two forms against each other instead of submitting both forms in one go. Any ideas?
Here's what I've tried:
For one form --> one table. This works, so it's a start.
# views.py
def BookFormView(request):
if request.method == 'POST':
form = BookForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect("/books/")
else:
form = BookForm()
return render(request, 'books/createbooks.html',
{'form' : form})
However, when I add this form in from forms.py to get the subsequent views.py I get local variable 'book_form' referenced before assignment. That's usually an easy global-vs-local variable issue to fix, but I don't know what it means in this case.
def BookFormView(request):
if request.method == 'POST':
if 'book' in request.POST:
book_form = BookForm(request.POST, prefix='book')
if book_form.is_valid():
book_form.save()
return HttpResponseRedirect("/books/")
bookdetailsform = BookDetailsForm(prefix='bookdetails')
elif 'bookdetails' in request.POST:
bookdetailsform = BookDetailsForm(request.POST, prefix='bookdetails')
if bookdetailsform.is_valid():
bookdetailsform.save()
return HttpResponseRedirect("/books/")
book_form = BookForm(prefix='book')
else:
book_form = BookForm(prefix='book')
bookdetailsform = BookDetailsForm(prefix='bookdetails')
return render(request, 'books/createbook.html',
{'book_form' : book_form,
'bookdetailsform': bookdetailsform})
Based on the question's comments:
def BookFormView(request):
if request.method == 'POST':
book_form = BookForm(request.POST, prefix='book')
bookdetailsform = BookDetailsForm(request.POST, prefix='bookdetails')
if book_form.is_valid() and bookdetailsform.is_valid():
book_form.save()
bookdetailsform.save()
return HttpResponseRedirect("/books/")
else:
book_form = BookForm(prefix='book')
bookdetailsform = BookDetailsForm(prefix='bookdetails')
return render(request, 'books/createbook.html',
{'book_form': book_form, 'bookdetailsform': bookdetailsform})
I think the problem is that when a user submits a bookdetails post request,
it will be handled under if 'book' in request.POST: condition. Why?
because string bookdetails contains string book, no matter the type of request they do, it will be handled with if book in request.POST: condition.
I believe fixing that if condition problem is the first step.

submitting two forms one after another

I am working on my first django webaite, I am trying to submit two forms one after the other.
Here is the views.py :
def home(request):
import json
if request.method == 'POST':
form = MajorForm(request.POST)
if form.is_valid():
url = 'http://www.mysite.com:8082'
dataout = {'my':'data'}
headers = {'content-type':'application/json'}
r = requests.post(url,data=json.dumps(dataout),headers=headers)
return collector(request)
else:
return HttpResponse("thnx")
else:
form = MajorForm()
return render(request,'index.html',{'form':form})
def collector(request):
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
return HttpResponse("thanx")
else:
return HttpResponse("not valid")
else:
form = ContactForm();
return render(request,'collector.html',{'form':form})
So the first view calls the second view. The first form works fine, and the second form is also displayed fine, but submitting the second form does not work at all ( I was never able to get to form.is_valid path). Maybe this entire approach of calling one view from another is not correct? What would be the right one?
Please indent your code correctly. Also you are missing an else in the collector function when the request.method is not POST.

Get Django Auth "User" id upon Form Submission

I currently have a model form that submits an entered domain to the db.
The problem I'm encountering is, I need to save the currently logged in user's ID (PK from the django.auth table) when a domain is submitted to satisfy a PK-FK relationship on the db end.
I currently have:
class SubmitDomain(ModelForm):
domainNm = forms.CharField(initial=u'Enter your domain', label='')
FKtoClient = User.<something>
class Meta:
model = Tld #Create form based off Model for Tld
fields = ['domainNm']
def clean_domainNm(self):
cleanedDomainName = self.cleaned_data.get('domainNm')
if Tld.objects.filter(domainNm=cleanedDomainName).exists():
errorMsg = u"Sorry that domain is not available."
raise ValidationError(errorMsg)
else:
return cleanedDomainName
and views.py
def AccountHome(request):
if request.user.is_anonymous():
return HttpResponseRedirect('/Login/')
form = SubmitDomain(request.POST or None) # A form bound to the POST data
if request.method == 'POST': # If the form has been submitted...
if form.is_valid(): # If form input passes initial validation...
domainNmCleaned = form.cleaned_data['domainNm'] ## clean data in dictionary
clientFKId = request.user.id
form.save() #save cleaned data to the db from dictionary`
try:
return HttpResponseRedirect('/Processscan/?domainNm=' + domainNmCleaned)
except:
raise ValidationError(('Invalid request'), code='300') ## [ TODO ]: add a custom error page here.
else:
form = SubmitDomain()
tld_set = request.user.tld_set.all()
return render(request, 'VA/account/accounthome.html', {
'tld_set':tld_set, 'form' : form
})
The problem is it gives me an error of: (1048, "Column 'FKtoClient_id' cannot be null"), very odd thing happening, for the column FKtoClient, its trying to submit: 7L instead of 7(the PK of this user's record). Any ideas?
If someone can please help, I would really appreciate it
Firstly, remove FKtoClient from your form. You need to set the user in your view where you can yes the request object. It's not possible to set an attribute on the form that automatically sets the current user.
When instantiating your form, you can pass a tld instance which already has the user set.
def AccountHome(request):
# I recommend using the login required decorator instead but this is ok
if request.user.is_anonymous():
return HttpResponseRedirect('/Login/')
# create a tld instance for the form, with the user set
tld = Tld(FKtoClient=request.user)
form = SubmitDomain(data=request.POST or None, instance=tld) # A form bound to the POST data, using the tld instance
if request.method == 'POST': # If the form has been submitted...
if form.is_valid(): # If form input passes initial validation...
domainNm = form.cleaned_data['domainNm']
form.save() #save cleaned data to the db from dictionary
# don't use a try..except block here, it shouldn't raise an exception
return HttpResponseRedirect('/Processscan/?domainNm=%s' % domainNm)
# No need to create another form here, because you are using the request.POST or None trick
# else:
# form = SubmitDomain()
tld_set = request.user.tld_set.all()
return render(request, 'VA/account/accounthome.html', {
'tld_set':tld_set, 'form' : form
})
This has an advantage over #dm03514's answer, which is that you can access the user within form methods as self.instance.user if required.
If you want to Require that a user be logged in to submit a form, you could do something like:
#login_required # if a user iS REQUIRED to be logged in to save a form
def your_view(request):
form = SubmitDomain(request.POST)
if form.is_valid():
new_submit = form.save(commit=False)
new_submit.your_user_field = request.user
new_submit.save()
You can get the logged in user from the request object:
current_user = request.user

Categories

Resources