Django - Iterate through postdata from ModelMultipleChoiceField - django

I am creating a form which will allow a user to send an email to multiple people (students).
I have used ModelMultipleChoiceField to create checkboxes for each user, however I'm not sure how to deal with the data that gets posted.
Here's my view so far:
if request.method == 'POST':
subject = request.POST['subject']
message = request.POST['message']
email = EmailMessage(subject, message, 'from#example.com',
recipient_addresses)
email.send()
else:
students = Student.objects.exclude(email='')
form = StudentListForm(students=students)
The form just posts the ID numbers of the selected recipients. Do I have to filter Student objects like this:
Student.objects.filter(pk__in=request.POST['students'])
Or is there a 'better' way?
Any advice would be appreciated.
Thanks

You're missing most of the point of using a form, which is to rely on it for validation and data conversion, as well as simply showing fields in HTML.
if request.method == 'POST':
form = StudentListForm(data=request.POST)
if form.is_valid():
subject = form.cleaned_data['subject']
message = form.cleaned_data['message']
recipients = form.cleaned_data['recipients']
recipient_addresses = [r.email for r in recipients]
email = ...
Basically, you should always access form.cleaned_data instead of request.POST.

Related

Why the Django extended user model is not able to show pre-populated data in while updating the fields?

I have written a program to update the User default fields(email with the help of UserCreationForm) and Extended User models(DOB, country etc). Below is the function:
#login_required(login_url="/login/")
def editUserProfile(request):
if request.method == "POST":
form = UserProfileUpdateForm(request.POST, instance=request.user) # default user profile update
obj = UserProfile.objects.get(user__id=request.user.id) # custom User fields.
form1 = UserProfileForm(request.POST or None, instance=obj)
if form.is_valid() and form1.is_valid():
obj.Photo = form1.cleaned_data['Photo']
obj.dob = form1.cleaned_data['dob']
obj.country = form1.cleaned_data['country']
obj.State = form1.cleaned_data['State']
obj.District = form1.cleaned_data['District']
obj.phone = form1.cleaned_data['phone']
form.save()
form1.save()
messages.success(request, f'updated successfully')
return redirect('/profile1')
else:
messages.error(request, f'Please correct the error below.')
else:
form = UserProfileUpdateForm(instance=request.user)
form1 = UserProfileForm(instance=request.user)
return render(request, "authenticate\\editProfilePage.html", {'form': form, 'form1': form1})
With the help of above method I am able to update the user data. However, the issue is when I click on the "update" button on my profile page the next page that I get to enter new data to the fields doesn't come with pre-populated data. i.e, the "email" field has the pre-populated data, but the custom fields like (country, dob, state) are blank, ideally it they should have existing data showing to the user after the user click on the "update" button from the profile page.
Any idea. I hope I was able to explain. Please let me know if any other query(s).
Thank you
You are sending the same form:
form = UserProfileUpdateForm(instance=request.user)
form1 = UserProfileUpdateForm(instance=request.user)
email and the custom fields are in 2 separate forms.
2nd solution:
Try:
default_data_profile = UserProfileForm.objects.get(user=obj)
form1 = UserProfileForm(initial = default_data_profile, instance=obj)

Why won't my text posts save, it worked before?

My text posts were working before adding a notification feature but now they aren't, I have a debug print but instead of seeing the post object, I'm seeing the user that posted it. I haven't changed anything other than getting the post id, timesince and the notify function, I've used the exact same method with my picture and video posts and they work fine, so it doesn't make sense to me. I've got a debug print in the notification function to make sure the post type and id have been passed correctly and those indeed show the id and type
views.py
#login_required()
def text_post(request):
if request.method == "POST":
form = TextPostForm(request.POST)
if form.is_valid():
t_post = form.save(commit=False)
t_post.author = request.user
t_post.save()
id = t_post.id
time = timesince
print(t_post) # t_post shows the user instead of the post
followers = list(request.user.followers.all())
notify(followers,
request.user,
f"{request.user.username} posted {time}",
id,
'text'
)
print(t_post)
#redirect to last page
return redirect('home')
else:
form = TextPostForm()
post_type = 'text'
return render(request, 'create_post.html', {'form': form, 'post_type': post_type})
forms.py
class TextPostForm(forms.ModelForm):
class Meta:
model = TextPost
fields = ('description','privacy', 'categories')

Django: send emails to users

I have a list of users with their email adress (only for Staff members), I am trying to send a form to the user.
When I use i.email, I get this error: "to" argument must be a list or tuple
When I use ['i.email'] I don't receive the message.
urls.py
path('users/<int:id>/contact', views.contactUser, name='contact_user'),
views.py
def contactUser(request, id):
i = User.objects.get(id=id)
if request.method == 'POST':
form = ContactUserForm(request.POST)
if form.is_valid():
message = form.cleaned_data['message']
send_mail('Website administration', message, ['website#gmail.com'], ['i.email'])
return redirect('accounts:users')
else:
form = ContactUserForm()
return render(request, 'accounts/contact_user.html', {'form': form, 'username': i})
I am using SendGrid. I have a 'contact us' form which is similar to contactUser and it works fine.
['i.email'] should be [i.email]

Django initial value for MultiChoice Field ignored for ModelForm

this is my first post here and I am very new to Django but I just can't seem to find a solution for this problem... I've searched stackoverflow and google but nothing seems to work for me...
I have a wine-app and want to be able to add and remove wines from the user's stock. In the list of wines the user can choose a wine to add and the ID of this wine is passed in the POST data. Since the data is getting lost after the first time the view is rendered I saved the ID in a cookie, which is working, but the problem is when I work with ModelForm de user has to select the foreign key for the user and for the wine, which is bad, so I tried to make it hidden and set the Fk_user and Fk_wine after the user choose the number of bottles to be added but before validation. Here's the problem after google everyone suggested I should use the "initial" and pass that to the form, but this is clearly not working because if I make the fields visible in the form I can see that it is not preselected...
viewy.py:
def addStockView(request):
wineId = request.POST.get('addStock')
if 'addStock' in request.POST:
wine = get_object_or_404(Wine, idwine=int(wineId))
userId = request.user.id
user = get_object_or_404(AuthUser, id=userId)
if request.method == 'POST':
#wineIdNew = request.COOKIES.get('wineIdToAdd')
#wineNew = get_object_or_404(Wine, idwine=wineIdNew)
form = StockForm(request.POST, initial={'fk_wine': wineNew.idwine, 'fk_auth_user': user.id})
if form.is_valid():
form.save()
return redirect('home')
else:
form = StockForm(initial={'fk_wine': wine.id,
'fk_auth_user': user.id})
response = render(request, 'addToStock.html', {'form': form})
response.set_cookie('wineIdToAdd', wineId)
return response
forms.py:
class StockForm(forms.ModelForm):
#fk_wine = ModelChoiceField(queryset=Wine.objects.all(),
# widget=HiddenInput())
#fk_auth_user = ModelChoiceField(queryset=AuthUser.objects.all(),
# widget=HiddenInput())
class Meta:
model = UserWineStock
fields = ['fk_auth_user', 'fk_wine', 'number']
can anyone help me with this..?
Yes, initial data is ignored when a form is bound to submitted data.
Instead of using initial here, you should exclude those two fields from the form and set them on the created object:
form = StockForm(request.POST)
if form.is_valid():
item = form.save(commit=False)
item.fk_wine = wine
item.fk_auth_user = request.user
item.save()
return redirect('home')
(Also, please don't call your fields things like fk_auth_user. Just call it user.)

Populate Django form from 3rd party POST with different field names

My Django app will be handling post data from a 3rd party payment processor. I would like to use a Django form to sanitize and deal with this data, but the POST variables have names that are not valid names for Django form fields. How can I re-map these to my form?
So, I have a form:
class PayResponseForm(forms.Form):
status = forms.Charfield()
message = forms.CharField()
avs_code = forms.CharField(max_length=1)
And the post I get from the 3rd part site looks like:
request.POST['FinalStatus']
request.POST['MErrMsg']
request.POST['avs-code']
How do I map these post variable to my form fields? Will it cause problems if, in my view, I just do something like request.POST['status'] = request.POST['FinalStatus']?
You can create your own dict for form init:
if request.method == 'POST':
if need_to_convert_post(request):
post = {
'field1': None,
'field2': None,
'field3': None,
}
post['field1'] = request.POST.get('SomeOtherField1', None)
else:
post = request.POST
form = Form1(post)
else:
form = Form1()
and detect when you need to change post:
def need_to_convert_post(request):
if 'uniqueCheckField' in request.POST:
return True
return False
For tidyness, you could use request.POST['status'] = request.POST.pop('FinalStatus'), otherwise it's perfectly fine to use your approach.