I'm doing a query to get the chocies from a charfield and assign them. But at the moment I want to save the form in my view I am getting this error. What I can do?
ValueError: Cannot assign "'17'": "Con_Transaccioncab.doc" must be a "Adm_Documento" instance.
In the form I retrieve and assign the options to the field
form.py
class Con_MovimientosForm(ModelForm):
class Meta:
model = Con_Transaccioncab
fields = '__all__'
exclude = ['cab_estado']
widgets = {
'emp_id': HiddenInput(),
'per_id': HiddenInput(),
'suc_id': HiddenInput(),
'cab_numero': HiddenInput(),
'cab_estadocon': RadioSelect,
'cab_escambpat': CheckboxInput,
'cab_fecha': DatePickerInput(format=Form_CSS.fields_date_format,
options=Form_CSS.fields_date_opts,
attrs={'value': Form_CSS.fields_current_date}),
}
def __init__(self, *args, **kwargs):
self.AIGN_EMP_ID = kwargs.pop("AIGN_EMP_ID")
self.AIGN_PER_ID = kwargs.pop("AIGN_PER_ID")
# --------------------------------------------------------------------------------------
self.AIGN_OPCIONES = kwargs.pop("AIGN_OPCIONES")
self.PERMISOS = [] # para recuperar los permisos de la tabla
__json_values = json.loads(json.dumps(self.AIGN_OPCIONES))
self.PERMISOS = recuperarPermisos(__json_values, self._meta.model.get_table_name(self._meta.model))
# --------------------------------------------------------------------------------------
super(Con_MovimientosForm, self).__init__(*args, **kwargs)
self.fields['cab_estadocon'].required = False
self.fields['cab_numero'].required = False
# here I am assigned the choices to the field
self.fields['doc'] = ChoiceField(label='Acción: ', choices=self.get_choices(), required=False)
for form in self.visible_fields():
form.field.widget.attrs['placeholder'] = Form_CSS.fields_placeholder + form.field.label.lower()
form.field.widget.attrs['autocomplete'] = Form_CSS.fields_autocomplete
form.field.widget.attrs['class'] = Form_CSS.fields_attr_class
self.helper = FormHelper(self)
self.helper.form_method = 'post'
self.helper.form_id = Form_CSS.getFormID(self)
self.helper.attrs = Form_CSS.form_attrs
self.helper.form_tag = True
self.helper.form_error_title = Form_CSS.form_err_title
self.helper.form_class = Form_CSS.form_class
self.helper.label_class = Form_CSS.fields_label_class
self.helper.field_class = 'col-sm-5'
self.helper.layout = Layout(
Div(
DivHeaderWithButtons(instance_pk=self.instance.pk, remove_delete=True, remove_print=False,
permisos=self.PERMISOS),
Div(
Div(
Div('cab_numero',
'cab_fecha',
'doc', # this is the field of which the error is giving
'cab_observacion',
Div('cab_estadocon', style='pointer-events: none;'),
'per_id',
'suc_id',
'emp_id',
css_class='col-sm'),
Div('cab_beneficia',
'cab_essaldoini',
'cab_escambpat',
'cab_elaborado',
'cab_revisado',
'cab_aprovado',
css_class='col-sm'),
css_class='row'
),
css_class='card-body', id='body_id'
),
css_class='card'
),
Div(
DivGridHeaderWithButtons(instance_pk=self.instance.pk,
grid_opts=get_MovimientosDetForm(self.AIGN_PER_ID, None)),
)
)
def clean(self):
super(Con_MovimientosForm, self).clean()
return self.cleaned_data
# This is the query where I get the choices
def get_choices(self):
all_tipoaux = Adm_DocumentoPeriodo.objects.select_related('doc').filter \
(per=self.AIGN_PER_ID).select_related('doc__mod').filter(doc__mod__mod_codigov='CON').values("doc__doc_id",
"doc__doc_nombre")
DOC = [(int(d['doc__doc_id']), str(d['doc__doc_nombre'])) for d in all_tipoaux]
return DOC
these are the 3 models that I am using for this example.
models.py
class Con_Transaccioncab(models.Model):
ESTADO_CHOICES = [
('S', 'Sin Contabilizar'),
('C', 'Contabilizado'),
('I', 'Incompleto'),
('A', 'Anulado'),
]
cab_id = models.BigAutoField(primary_key=True)
cab_numero = models.BigIntegerField(verbose_name='#')
cab_fecha = models.DateField(verbose_name='Fecha')
cab_estadocon = models.CharField(
max_length=2,
choices=ESTADO_CHOICES,
default="I", verbose_name="Estado")
cab_observacion = models.CharField(max_length=128, blank=True, null=True, verbose_name='Observación')
cab_elaborado = models.CharField(max_length=32, blank=True, null=True, verbose_name='Elaborado por')
cab_revisado = models.CharField(max_length=32, blank=True, null=True, verbose_name='Revisado por')
cab_aprovado = models.CharField(max_length=32, blank=True, null=True, verbose_name='Aprobado por')
cab_beneficia = models.CharField(max_length=32, blank=True, null=True, verbose_name='Beneficiario')
cab_essaldoini = models.BooleanField(verbose_name='Saldos iniciales',default=False)
cab_escambpat = models.BooleanField(verbose_name='Cambio patrimonio',default=False)
doc = models.ForeignKey(Adm_Documento, models.DO_NOTHING, db_column='doc_id', verbose_name="Documento")
per_id = models.ForeignKey(Adm_Periodo, models.DO_NOTHING, db_column='per_id')
suc_id = models.ForeignKey(Adm_Sucursal, models.DO_NOTHING, db_column='suc_id')
emp_id = models.ForeignKey(Adm_Empresa, models.DO_NOTHING, db_column='emp_id')
cab_estado = models.SmallIntegerField(default=True)
class Meta:
managed = False
verbose_name = 'Movimientos'
db_table = 'con\".\"transaccioncab'
unique_together = (('cab_id', 'doc_id', 'per_id', 'suc_id', 'emp_id'),)
class Adm_Documento(models.Model):
class Choices_DocTipo(models.TextChoices):
Ingreso = 'I', _('Ingreso')
Egreso = 'E', _('Egreso')
Transferencia = 'T', _('Transferencia')
EntregaPedido = 'P', _('Entrega pedido')
class Choices_DocMovDebCre(models.TextChoices):
Cheque = 'CHE', _('Cheque')
Deposito = 'DEP', _('Depósito')
NotaCredito = 'NDC', _('Transferencia')
NotaDebito = 'NDD', _('Entrega pedido')
Ninguno = '', _('Ninguno')
doc_id = models.BigAutoField(primary_key=True)
doc_codigov = models.CharField(max_length=32, verbose_name='Código')
doc_nombre = models.CharField(max_length=64, verbose_name='Nombre')
doc_tipo = models.CharField(max_length=1, blank=True, null=True, verbose_name='Tipo',
choices=Choices_DocTipo.choices)
doc_orden = models.SmallIntegerField(verbose_name='Orden')
doc_actcosto = models.BooleanField(verbose_name='Actualiza costo')
doc_movcre = models.CharField(max_length=3, blank=True, null=True, verbose_name='Mov. Crédito',
choices=Choices_DocMovDebCre.choices, default=Choices_DocMovDebCre.Ninguno)
doc_movdeb = models.CharField(max_length=3, blank=True, null=True, verbose_name='Mov. Débito',
choices=Choices_DocMovDebCre.choices, default=Choices_DocMovDebCre.Ninguno)
tcc = models.ForeignKey(Sis_TemplateContabCab, models.DO_NOTHING, blank=True, null=True,
verbose_name=Sis_TemplateContabCab._meta.verbose_name)
mod = models.ForeignKey(Sis_Modulo, models.DO_NOTHING, verbose_name=Sis_Modulo._meta.verbose_name)
emp = models.ForeignKey(Adm_Empresa, models.DO_NOTHING, verbose_name=Adm_Empresa._meta.verbose_name)
doc_estado = models.SmallIntegerField(default=True)
class Meta:
managed = False
db_table = 'adm\".\"documento'
unique_together = (('doc_id', 'emp'), ('doc_codigov', 'emp'))
verbose_name = 'Documento'
verbose_name_plural = 'Documentos'
def __str__(self):
return self.doc_nombre
class Adm_DocumentoPeriodo(models.Model):
dop_id = models.BigAutoField(primary_key=True)
doc = models.ForeignKey(Adm_Documento, models.DO_NOTHING,db_column='doc_id')
per = models.ForeignKey(Adm_Periodo, models.DO_NOTHING,db_column='per_id')
emp = models.ForeignKey(Adm_Empresa, models.DO_NOTHING,db_column='emp_id')
dop_secuencia = models.BigIntegerField(verbose_name='Secuencia')
dop_estado = models.SmallIntegerField(default=True)
class Meta:
managed = False
db_table = 'adm\".\"documento_periodo'
unique_together = (('per', 'emp', 'doc'),)
The error occurs in the view at form.is_valid()
View.py
class Con_MovimientosUpdateView(UpdateView):
model = Con_Transaccioncab
form_class = Con_MovimientosForm
template_name = 'con_movimientos/form.html'
success_url = reverse_lazy('con_man:con_movimientos_list')
error_url = reverse_lazy('con_man:con_movimientos_add')
def dispatch(self, request, *args, **kwargs):
for k in self.kwargs.keys():
self.kwargs[k] = _e.decrypt(self.kwargs[k])
self.object = self.get_object()
return super().dispatch(request, *args, **kwargs)
def get_form_kwargs(self):
kwargs = super(Con_MovimientosUpdateView, self).get_form_kwargs()
kwargs.update({'AIGN_EMP_ID': self.request.session['AIGN_EMP_ID']})
kwargs.update({'AIGN_PER_ID': self.request.session['AIGN_PER_ID']})
kwargs.update({'AIGN_OPCIONES': self.request.session['AIGN_OPCIONES']})
return kwargs
def post(self, request, *args, **kwargs):
r = {'a': 1}
extra_errors = []
form = self.get_form()
if 'SAVE' in request.POST and form.is_valid(): # In this line the error occurs
if 'cab_escambpat' in request.POST and request.POST['es_patri'] == 'false':
return JsonResponse({'__all__': ["Error debe existir almenos una cuenta de patrimonio"]})
else:
try:
df_movDetCuenta = pd.DataFrame(json.loads(request.POST['movimientos_grid']))
df_movDetCuenta["det_desc"].fillna('', inplace=True)
df_movDetCuenta["det_refdoc"].fillna('', inplace=True)
with transaction.atomic():
con_transaccioncab = self.get_object()
for index, row in df_movDetCuenta.iterrows():
if float(row.det_valor) > 0:
cueDet = Con_Transacciondet()
if not pd.isna(row.det_id):
cueDet.det_id = row.det_id
cueDet.det_estado = 0 if row._action == 'E' else 1
else:
cueDet.det_estado = 1
cueDet.cue_id_id = row.cue_id_id
cueDet.cab_id_id = con_transaccioncab.cab_id
cueDet.suc_id = con_transaccioncab.suc_id
cueDet.emp_id = con_transaccioncab.emp_id
cueDet.per_id = con_transaccioncab.per_id
cueDet.doc_id = con_transaccioncab.doc_id
cueDet.det_fecha = con_transaccioncab.cab_fecha
cueDet.det_desc = row.det_desc
cueDet.det_istransf = row.det_istransf
cueDet.det_refdoc = row.det_refdoc
cueDet.det_tipomov = row.det_tipomov
cueDet.det_valor = row.det_valor
cueDet.save()
form.save()
messages.success(request, CRUD_MSG.SAVE)
return JsonResponse(r)
except django.db.models.query_utils.InvalidQuery as e:
extra_errors.append(str(e))
self.object = None
context = self.get_context_data(**kwargs)
context['form'] = form
errors = form._errors.setdefault("__all__", ErrorList())
errors.extend(extra_errors)
return JsonResponse(r)
In Django, ForeigField references the object itself not its id. So calling it doc_id is incorrect and confusing. What you should do is call the field doc. Then setting doc_id would work as you'd expect.
With what you have now you'd need to use doc_id_id to set the actual id which is... you know...
Related
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
I am using django-simple-history to log changes in my models. I have managed to save log of changes, but I always get None on field history_user.
I am following this tutorial.
This is my model:
class Reservation(models.Model):
UNCONFIRMED = 'UNCONFIRMED'
CONFIRMED = 'CONFIRMED'
CANCELED = 'CANCELED'
NO_SHOW = 'NO SHOW'
GO_SHOW = 'GO SHOW'
STATUS_CHOICES = (
(UNCONFIRMED, _('Unconfirmed')),
(CONFIRMED, _('Confirmed')),
(CANCELED, _('Canceled')),
(NO_SHOW, _('No show')),
(GO_SHOW, _('Go show')),
)
booking = models.CharField(max_length=25, verbose_name=_('Booking'))
agency = models.ForeignKey(Agency, on_delete=models.PROTECT, related_name='reservations', verbose_name=_('Agency'))
comment = models.TextField(null=True, blank=True, verbose_name=_('Comment'))
status = models.CharField(max_length=15, choices=STATUS_CHOICES, default=UNCONFIRMED, verbose_name=_('Status'))
confirmation_date = models.DateTimeField(null=True, blank=True, verbose_name=_("Confirmation Date"))
arrival_date = models.DateField(verbose_name=_('Arrival Date'))
departure_date = models.DateField(verbose_name=_('Departure Date'))
confirmation = models.CharField(max_length=15, null=True, blank=True, verbose_name=_('Confirmation Code'))
is_invoiced = models.BooleanField(default=False, verbose_name=_('Is invoiced?'))
euroamerica = models.BooleanField(default=False, verbose_name=_("Is Euroamerica sale"))
user = models.ForeignKey(User, null=True, blank=True, on_delete=models.PROTECT, related_name='reservations')
changed_by = models.ForeignKey(User, null=True, blank=True, on_delete=models.PROTECT)
timestamp = models.DateTimeField(null=True, blank=True, auto_now_add=True)
handle_fee = models.FloatField(null=True, blank=True, verbose_name=_("Handle Fee"))
log = HistoricalRecords(related_name='history')
class Meta:
verbose_name = _('Reservation')
verbose_name_plural = _('Reservations')
permissions = (
('reservation_can_edit', 'Can Edit Reservation'),
('reservation_can_view', 'Can View Reservation'),
('reservation_can_view_history_log', 'Can View Reservation History Log')
)
def __str__(self):
return "[{}]{}".format(self.booking, self.agency)
def clean(self, *args, **kwargs):
if self.id is None:
try:
Reservation.objects.get(booking=self.booking)
except:
pass
else:
raise CustomValidation(_('Booking already exists.'), 'booking', status_code=status.HTTP_400_BAD_REQUEST)
if isinstance(self.arrival_date, str):
raise CustomValidation(_('Arrival date must be a valid date.'), 'arrival_date', status_code=status.HTTP_400_BAD_REQUEST)
if isinstance(self.departure_date, str):
raise CustomValidation(_('Departure date must be a valid date.'), 'departure_date', status_code=status.HTTP_400_BAD_REQUEST)
if self.arrival_date >= self.departure_date:
raise CustomValidation(_('Departure date must be later than Arrival date.'), 'departure_date', status_code=status.HTTP_400_BAD_REQUEST)
# elif self.arrival_date <= timezone.datetime.now().date():
# if self.id == None:
# raise CustomValidation(_('Arrival date must be later than today.'), 'arrival_date', status_code=status.HTTP_400_BAD_REQUEST)
if self.status == 'CONFIRMED' and self.confirmation is None:
raise CustomValidation(_('Must provide a confirmation number.'), 'confirmation', status_code=status.HTTP_400_BAD_REQUEST)
return True
def save(self, *args, **kwargs):
from GeneralApp.models import Parameter
self.booking = self.booking.replace(' ', '')
self.booking = self.booking.upper()
self.full_clean()
if self.confirmation is not None and self.status is not self.CONFIRMED:
if self.pk is not None:
try:
previous_reservation = Reservation.objects.get(id=self.pk)
except:
pass
else:
if previous_reservation.status == self.status and previous_reservation.confirmation != self.confirmation:
self.status = self.CONFIRMED
else:
self.status = self.CONFIRMED
if self.status == self.CONFIRMED and self.confirmation_date is None:
self.confirmation_date = timezone.now()
try:
self.handle_fee = Parameter.objects.get(name="Handle Fee").value
except:
self.handle_fee = None
super(Reservation, self).save(*args, **kwargs)
#property
def _history_user(self):
return self.changed_by
#_history_user.setter
def _history_user(self, value):
self.changed_by = value
I don't know what I am missing to get the user logged.
EDIT
Here is where I save Reservation:
def save_reservation(self, reservation_data, user, pk):
try:
reservation_to_save = models.Reservation.objects.get(booking=pk)
except:
raise CustomValidation(_("There is not such reservation {}".format(pk)), 'id', status.HTTP_400_BAD_REQUEST)
reservation_to_save.booking = reservation_data['booking']
reservation_to_save.agency = models.Agency.objects.get(id=reservation_data['agency'])
reservation_to_save.comment = reservation_data.get('comment', None)
reservation_to_save.status = reservation_data.get('status', 'UNCONFIRMED')
reservation_to_save.arrival_date = reservation_data['arrival_date']
reservation_to_save.departure_date = reservation_data['departure_date']
reservation_to_save.confirmation = reservation_data.get('confirmation', None)
reservation_to_save.is_invoiced = reservation_data.get('is_invoiced', False)
reservation_to_save.euroamerica = reservation_data.get('euroamerica', False)
reservation_to_save.save()
return reservation_to_save
According to the documentation you have to add HistoryRequestMiddleware to your middleware in settings.py
Like so:
MIDDLEWARE = [
# ...
'simple_history.middleware.HistoryRequestMiddleware',
]
This at least was the solution in my case.
If you don't want to use this middleware you can set the user manually, see this.
in models.py:
class Projects(models.Model):
# 项目名称
pro_name = models.CharField('项目名称',max_length=50)
# 项目内容
# content = models.CharField('项目内容',max_length=200)
content = models.TextField('项目内容', max_length=200)
# 外键
person = models.ForeignKey(Person, on_delete=models.CASCADE)
# 金额
sum_money = models.IntegerField('项目金额',default=0)
# 付款
payed_money = models.IntegerField('已付金额',default=0)
# 欠钱
owe_money = models.IntegerField('未付金额',default=0)
# 是否欠钱
is_debt = models.BooleanField('是否欠账',default=True)
# 发布日期
pub_date = models.DateTimeField('保存日期',default=timezone.now,)
def was_published_recently(self):
return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
def __str__(self):
return self.pro_name
class Meta:
verbose_name = '项目'
verbose_name_plural = '项目'
admin screen capture:
when I changed the 'payed_money(已付金额:)' the 'owe_money(未付金额:)' = sum_money - payed_money, and if sum_money == payed_money the is_debt = False
what should I do? rewrite save() mehtod?
class Projects(models.Model):
# 项目名称
pro_name = models.CharField('项目名称',max_length=50)
...
class Meta:
verbose_name = '项目'
verbose_name_plural = '项目'
def save(self, *args, **kwargs):
if not self.pk:
# 新增 add
if self.payed_money != 0:
self.owe_money = self.sum_money - self.payed_money
if self.owe_money <= 0:
self.is_debt = False
else:
# 修改 change
this = Projects.objects.get(id=self.id)
if this.payed_money != self.payed_money:
self.owe_money = self.sum_money - self.payed_money
if self.owe_money <= 0:
self.is_debt = False
return super(Projects, self).save(*args, **kwargs)
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
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.