Send mail from django form wizard - python

I have any models and the view to generate a form wizard, once the user submit the last form, I want the app send a confirmation email, the current user's mail is in the native Django model, how I can access to his email? and how I can access to "curso" name too? thanks for your help.
models.py
class Datos_Basicos (models.Model):
user = models.OneToOneField(User)
tipo_identificacion = models.CharField(max_length=25)
identificacion = models.CharField(max_length=20,primary_key='True')
telefono = models.CharField(max_length=10)
celular = models.CharField(max_length=11)
class Curso(models.Model):
curso = models.CharField(max_length=15)
fk_programa = models.ForeignKey(Programa, verbose_name="programa")
class Inscripcion(models.Model):
fecha = models.DateField(default = datetime.datetime.now)
fk_subsede = models.ForeignKey(Subsede, verbose_name="sede")
fk_curso = models.ForeignKey(Curso, verbose_name="curso")
class Inscrito(models.Model):
fk_datos_basicos = models.OneToOneField(Datos_Basicos, verbose_name="datos basicos")
fk_inscripcion = models.OneToOneField(Inscripcion, verbose_name="curso", null=False)
forms.py
class Datos_basicos_form(forms.ModelForm):
tipo_identificacion = forms.ChoiceField(choices=IDENTIFICACION_CHOICES)
class Meta:
model = Datos_Basicos
fields = ['tipo_identificacion', 'identificacion', 'telefono', 'celular']
class Inscrito_form(forms.Form):
genero = forms.ChoiceField(choices=GENEROS_CHOICES)
fecha_nacimiento = forms.DateField(widget=extras.SelectDateWidget(years=ANIOS_CHOICES))
grupo_etnico = forms.ChoiceField(choices=GRUPO_ETNICO_CHOICES)
condicion = forms.ModelChoiceField(queryset=Condicion.objects.all())
condicion_medica = forms.CharField(max_length=200)
eps = forms.CharField(max_length=100)
espacio_geografico = forms.ChoiceField(choices=ESPACIO_GEOGRAFICO_CHOICES)
barrio = forms.ModelChoiceField(queryset=Barrio.objects.order_by('barrio'))
direccion = forms.CharField(max_length=50)
jornada_estudio = forms.ChoiceField(choices=JORNADA_ESTUDIO_CHOICES)
class Inscripcion_form(forms.ModelForm):
class Meta:
model = Inscripcion
exclude = ['fecha']
views.py
from formtools.wizard.views import SessionWizardView
class InscritoWizard(SessionWizardView):
template_name = "inscripcion.html"
def done(self, form_list, **kwargs):
forms_data = self.process_form_data(form_list)
forms_data[1]['user'] = self.request.user ### current user
forms_data[2]['edad'] = hoy.year - forms_data[2]['fecha_nacimiento'].year - ((hoy.month, hoy.day) < (forms_data[2]['fecha_nacimiento'].month, forms_data[2]['fecha_nacimiento'].day))
inscripcion = Inscripcion.objects.create(**forms_data[0])
datos_basicos = Datos_Basicos.objects.create(**forms_data[1])
forms_data[2]['fk_datos_basicos'] = datos_basicos
forms_data[2]['fk_inscripcion'] = inscripcion
Inscrito.objects.create(**forms_data[2])
--->send_mail('Subject here', 'Here is the message.','from#example.com',['to#example.com'], fail_silently=False)
return render_to_response('gracias.html', {'forms_data': forms_data})
def process_form_data(self, form_list):
data = [form.cleaned_data for form in form_list]
return data

In the form wizard methods, you can access the logged in user with self.request.user, therefore you can get their email with self.request.user.email.

Related

Call one serializer's update() method from another serilaizer's create() method

I have 2 serializers serializer_1 and serializer_2 which are both model serilizer i want to execute update method of serializer_1 from create method of serializer_2 how can i achieve that?
class serializer_1(serializers.ModelSerializer):
date = serializers.DateTimeField(required=False, allow_null=True)
ispublic = serializers.BooleanField(allow_null=False)
details_api_url = serializers.SerializerMethodField()
dispute_types = OtherSerializer(many=True, required=False, write_only=True)
nature_of_dispute_list = serializers.SerializerMethodField()
plaintiff = OtherSerializer(many=True, required=False, write_only=True)
defendant = OtherSerializer(many=True, required=False, write_only=True)
claims_rep = OtherSerializer(many=True, required=False, write_only=True)
class Meta:
model = Media
fields = "__all_"
def update(self, instance, validated_data):
date = validated_data.pop('close_out_date', None)
plaintiff_data = validated_data.pop('plaintiff', [])
defendant_data = validated_data.pop('defendant', [])
claims_rep_data = validated_data.pop('claims', [])
is_summary_public_previous = instance.is_summary_public
obj = super().update(instance, validated_data)
return obj
class serializer_2(serializers.ModelsSerializer):
class Meta:
model = Fedia
fields = "__all__"
def create(self, validated_data):
request = self.context['request']
**serilizer_1_data** = validated_data.pop('serialzer_1_data', None)
is_final = validated_data.get('is_final')
serializer_1_object = Media.objects.create(**serializer_1_data)
if is_final:
**Call Serializer_1 Update method**
I have access to date,plaintiff etc mentioned under serializer_1 in create method of serilizer_2 through serilizer_1_data

Editing Django formset data creating new records instead of updating

Please Help!
I am trying to update a group of formsets that are related the main form (Project Information) by the main forms pk. The create form works fine, but I am finding it extremely difficult to implement the update version.
It's the save as an update part that I can't figure out for the formsets. The main form updates the database correctly. The formsets just create new records instead of updating the existing ones. I do not know how to instance the formsets.
Here the code.
view.py
#login_required
def edit_project(request):
SampleInformationFormSet = formset_factory(SampleInformationForm, extra=1)
DissolutionMethodsFormSet = formset_factory(DissolutionMethodsForm, extra=1)
form = ProjectInformationForm(request.POST or None)
si_formset = SampleInformationFormSet(request.POST or None, prefix='si')
d_formset = DissolutionMethodsFormSet(request.POST or None, prefix='d')
if request.method == 'POST':
form = ProjectInformationForm(request.POST or None)
si_formset = SampleInformationFormSet(request.POST or None, prefix='si')
d_formset = DissolutionMethodsFormSet(request.POST or None, prefix='d')
pi_pk = ''
p = ''
if form.is_valid():
pi_pk = form.cleaned_data['hd']
p = ProjectInformation.objects.get(pk=pi_pk)
form = ProjectInformationForm(request.POST, instance=p)
form.save() # This form saves correctly
for si_form in si_formset:
si_form.save() # I do not know how to attach an instance to these formsets
for d_form in d_formset:
d_form.save()
messages.success(request, 'Your project has been updated!')
return redirect('edit_project')
else:
pass
form = ProjectInformationForm(request.POST or None)
si_formset = SampleInformationFormSet(request.POST or None, prefix='si')
messages.warning(request, 'There was an error saving your form.')
study_id_select = list(
ProjectInformation.objects.values('dissolution_study_id', 'id').filter())
context = {'form': form, 'si_formset': si_formset, 'd_formset': d_formset, 'study_id_select': study_id_select}
return render(request, 'main/edit_project.html', context)
models.py I'm just going to include part of three of the seven models to keep this a little shorter.
class ProjectInformation(models.Model):
username = models.ForeignKey(User, on_delete=models.CASCADE)
compound_code = models.CharField(max_length=60)
product_type = models.ForeignKey(ProductType, on_delete=models.CASCADE)
main_component = models.CharField(max_length=100)
class SampleInformation(models.Model):
sample_index = models.CharField(max_length=30)
sample_type_purpose = models.ForeignKey(SampleTypePurpose, on_delete=models.CASCADE)
specification_number = models.CharField(max_length=20, blank=True, null=True)
project = models.ForeignKey(ProjectInformation, on_delete=models.CASCADE, blank=True, null=True)
class DissolutionMethods(models.Model):
number_of_methods = models.IntegerField(default=1,
validators=[MaxValueValidator(10), MinValueValidator(1)],
blank=True, null=True)
dissolution_method_index = models.CharField(max_length=10)
project = models.ForeignKey(ProjectInformation, on_delete=models.CASCADE, blank=True, null=True)
forms.py
class ProjectInformationForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['hd'] = forms.CharField(widget=forms.HiddenInput, required=False)
class Meta:
model = ProjectInformation
fields = '__all__'
class SampleInformationForm(forms.ModelForm):
class Meta:
model = SampleInformation
fields = '__all__'
Please help if you can. This project has been a trial by fire and the flames are hot!
Finally solved it myself.
#login_required
def edit_project(request):
SampleInformationFormSet = formset_factory(SampleInformationForm, extra=1)
DissolutionMethodsFormSet = formset_factory(DissolutionMethodsForm, extra=1)
form = ProjectInformationForm(request.POST or None)
si_formset = SampleInformationFormSet(request.POST or None, prefix='si')
d_formset = DissolutionMethodsFormSet(request.POST or None, prefix='d')
if request.method == 'POST':
form = ProjectInformationForm(request.POST or None)
si_formset = SampleInformationFormSet(request.POST or None, prefix='si')
d_formset = DissolutionMethodsFormSet(request.POST or None, prefix='d')
pi_pk = ''
p = ''
if form.is_valid():
pi_pk = form.cleaned_data['hd']
p = ProjectInformation.objects.get(pk=pi_pk)
form = ProjectInformationForm(request.POST, instance=p)
form.save()
si = p.sampleinformation_set.all() # All the Methods related to the instance
d = p.dissolutionmethods_set.all()
si_cnt = 0
for si_form in si_formset:
if si_form.is_valid():
update = si_form.save(commit=False)
update.pk = si[si_cnt].pk
update.save()
si_cnt += 1
d_cnt = 0
for d_form in d_formset:
if d_form.is_valid():
update = d_form.save(commit=False)
update.pk = d[d_cnt].pk
update.save()
d_cnt += 1

Manage ModelManyToMany request in views.py

I have a ModelManyToMany selector in my html.
(I can't post images so, here is the url to image: https://i.stack.imgur.com/HDhde.png)
I want to catch the user's selections with my POST method in my views.py
views.py
class userPageView(TemplateView):
template_name = 'user.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['edit_profile_form'] = EditProfileForm(prefix='edit')
return context
def post(self, request, *args, **kwargs):
edit_name = request.POST.get('edit-name')
edit_two_factors_auth = request.POST.get('edit-two_factors_auth')
edit_coins = request.POST.get('edit-coins')
if request.method == "POST":
if 'profileButton' in request.POST:
if edit_name and (edit_name != request.user.name):
request.user.name = edit_name
request.user.save()
print(edit_coins)
return render(request, 'user.html')
models.py
class Usuario(AbstractUser):
name = models.CharField(max_length=12, help_text="The name must be between 2 and 12 characters")
email = models.EmailField(max_length=60, unique=True, help_text="The email must be between 5 and 30 characters")
password = models.CharField(max_length=78)
change_password_code = models.CharField(blank=True,max_length=15)
activated = models.BooleanField(default=False)
activated_code = models.CharField(default="",max_length=15)
ip = models.CharField(blank=True,max_length=15)
last_login = models.DateField(default=now)
wallets = models.ManyToManyField(Wallet)
coins = models.ManyToManyField(Coin)
avatar = models.CharField(blank=True,default="bitcoin.png",max_length=15)
delete_code = models.CharField(default="",max_length=9,blank=True)
two_factors_auth = models.BooleanField(default=False)
two_factors_auth_code = models.CharField(default="",max_length=12,blank=True)
fingerprint = models.CharField(max_length=64,blank=True)
The print in my views.py only returns me the last selection, but not all the set of choices that the user has done.
I want to save all coins selections by the users in his coins field
you must change this line
edit_coins = request.POST.get('edit-coins')
to
edit_coins = request.POST.getlist('edit-coins')
and its works. after that edit_conis is a list contain all items user selected.

How to map foreign key when serializing POST data?

I'm trying to map a foreign key to POST data when creating a new object through a serializer. There are two foreign keys in the object, one is serializing perfectly, the other is creating an error.
Model:
class Event(models.Model):
owner = models.ForeignKey('auth.User', related_name='owner', blank=True)
date = models.DateField('eventdate')
time = models.TimeField('eventtime', default=now)
eventtype = models.ForeignKey(EventType, related_name='eventtype', blank=True)
# duration = models.DurationField()
location = models.CharField(max_length=200, blank=True)
attenders = models.ManyToManyField(User, related_name='attenders')
invited = models.ManyToManyField(User, related_name='invitedlist')
View:
class EventMixin(RetrieveUpdateDestroyAPIView, CreateAPIView):
serializer_class = EventSerializer
def get_queryset(self):
return Event.objects.all()
def partial_update(self, request, *args, **kwargs):
request['owner'] = request.user
sname = request['eventtype']
request['eventtype'] = EventType.objects.filter(sname=sname)
json_str = json.dumps(self.request.data)
data = json.loads(json_str)
try:
invited = list(data['toInvite'])
for i in invited:
for j in User.objects.filter(username=i):
invite = EventInvite(invited=j, sender=request.user, event=self.get_object())
invite.save()
self.get_object().invited.add()
except KeyError:
pass
return super(EventMixin, self).partial_update(request, *args, **kwargs)
def create(self, request, *args, **kwargs):
new = {}
new['owner'] = request.user.__dict__
new['date'] = request.data['date']
new['time'] = request.data['time']
new['location'] = request.data['location']
sname = request.data['eventtype']
new['eventtype'] = EventType.objects.get(sname=sname).__dict__
json_str = json.dumps(self.request.data)
data = json.loads(json_str)
serializer = EventMixinSerializer(data=new)
with open('/tmp/log.txt', 'w+') as f:
f.write(str(serializer.is_valid()))
f.write(str(serializer.validated_data))
f.close()
serializer.is_valid();
serializer.save()
try:
invited = list(data['toInvite'])
for i in invited:
for j in User.objects.filter(username=i):
invite = EventInvite(invited=j, sender=request.user, event=self.get_object())
invite.save()
self.get_object().invited.add()
except KeyError:
pass
Serializer:
class EventMixinSerializer(serializers.ModelSerializer):
owner = UserSerializer(read_only=True)
eventtype = EventTypeSerializer()
attenders = FriendsListingField(read_only=True)
invited = FriendsListingField(read_only=True)
class Meta:
model = Event
fields = ('owner', 'eventtype', 'date', 'time', 'location', 'id', 'attenders', 'invited')
def create(self, validated_data):
owner = validated_data.pop('owner')
owner = owner.instance
eventtype = validated_data.pop('eventtype')
eventtype = eventtype.instance
event = Event.objects.create(owner=owner, eventtype=eventtype, **validated_data)
event.save()
return event
Error when owner field present:
False
{'owner': OrderedDict([('username', ['A user with that username already exists.'])])}
Result when UserSerializer(read_only=True) (pretty much diabling it):
True
OrderedDict([('eventtype', OrderedDict([('lname', 'Swimming'), ('sname', 'SWM'), ('category', '1')])), ('date', datetime.date(2015, 12, 22)), ('$
(Notice the event type data in the result)
Thanks!
You need to remove the validators from UserSerializer.
Assuming UserSerializer is a User ModelSerializer it'll extract the unique constraint on the User.username from the Model and your validation will fail.
To work this around you'll need to remove the UniqueValidator by overriding the validators list for the username field of the UserSerializer

Django - How to work with multiple ModelForm's in the same form?

I've 4 models that I need to store data at once. For that I'm thinking using ModelForms.
I've tested with 2 ModelForm's at the same time but it is not working. Here is the code.
Model:
class Main(models.Model):
section = models.ForeignKey(Section)
user = models.ForeignKey(User)
title = models.CharField(max_length=250)
date_inserted = models.DateTimeField(auto_now_add=True)
date_last_update = models.DateTimeField(auto_now=True)
def __unicode__(self):
return self.title
# To order in the admin by name of the section
class Meta:
ordering = ['date_inserted']
class BicycleAd(models.Model):
main = models.ForeignKey(Main)
bicycleadtype = models.ForeignKey(BicycleAdType)
bicycleaditemkind = models.ForeignKey(BicycleAdItemKind) # MPTT Model
bicycleadcondition = models.ForeignKey(BicycleAdCondition)
country = models.ForeignKey(GeonamesCountry)
city = models.ForeignKey(GeonamesLocal)
date_inserted = models.DateTimeField(auto_now_add=True)
date_last_update = models.DateTimeField(auto_now=True)
# To order in the admin by name of the section
class Meta:
ordering = ['date_inserted']
Forms:
class MainForm(forms.ModelForm):
class Meta:
model = Main
exclude = ('user', 'section')
class BicycleAdForm(forms.ModelForm):
class Meta:
model = BicycleAd
exclude = ('main', 'bicycleadtype', 'bicycleaditemkind', 'bicycleadcondition', 'city')
View:
def submit_data_entry_view(request):
form_main = MainForm(request.POST)
form_bicyclead = BicycleAdForm(request.POST)
return render_to_response('app/submit_data_entry.html', {'form_main': form_main, 'form_bicyclead': form_bicyclead}, context_instance=RequestContext(request))
Template:
<form method="post" action="">
{{form_main}}
{{form_bicyclead}}
</form>
At the end I only get the"form_bicyclead" outputed in the browser? How can I get the two forms at once?
Best Regards,
are you using submit_data_entry_view to render forms too? shouldn't it be like -
def submit_data_entry_view(request):
if request.method == 'POST': #form submit
form_main = MainForm(request.POST)
form_bicyclead = BicycleAdForm(request.POST)
#now process and save the form
return <whatever_you_want>
elif request.method == 'GET': #first time rendering the form
form_main = MainForm()
form_bicyclead = BicycleAdForm()
return render_to_response('app/submit_data_entry.html', {'form_main': form_main, 'form_bicyclead': form_bicyclead}, context_instance=RequestContext(request))

Categories