I'm working with Django Forms in order to create a new object, but I'm having problems with it. It all renders OK, but when I submit the Form, an error is raised:
"AttributeError at /rutinas/nueva_rutina
'DiaForm' object has no attribute 'ejercicios'"
I've tried many possible solutions I read here, but they didn't work. I think the problem is with the M2M relationship, but it can also be for processing two forms at a time. Here are my files
models.py
class Ejercicio(models.Model):
id = models.AutoField(primary_key=True)
nombre = models.CharField(max_length=30, default='')
descripcion = models.TextField(default='')
gif = models.ImageField(default='')
def __str__(self):
return self.nombre
class Rutina(models.Model):
id = models.AutoField(primary_key=True)
nombre = models.CharField(max_length=30, default='')
def __str__(self):
return self.nombre
class Dia(models.Model):
ejercicios = models.ManyToManyField(Ejercicio)
rutina = models.ForeignKey(Rutina, on_delete=models.CASCADE)
forms.py
class RutinaForm(forms.ModelForm):
class Meta:
model = Rutina
fields = '__all__'
labels = {
'nombre': _('Nombre')
}
class DiaForm(forms.ModelForm):
ejercicios = forms.ModelMultipleChoiceField(queryset=Ejercicio.objects.all())
class Meta:
model = Dia
fields = ['ejercicios']
labels = {
'ejercicios': _('Ejercicios')
}
views.py
def nueva_rutina_view(request):
if request.method == "POST":
form = RutinaForm(request.POST)
dia_form_1 = DiaForm(request.POST)
dia_form_2 = DiaForm(request.POST)
dia_form_3 = DiaForm(request.POST)
if form.is_valid() and dia_form_1.is_valid() and dia_form_2.is_valid() and dia_form_3.is_valid():
rutina = form.save(commit=False)
dia1 = dia_form_1.save(commit=False)
dia2 = dia_form_2.save(commit=False)
dia3 = dia_form_3.save(commit=False)
rutina.save()
dia1.rutina = rutina
dia2.rutina = rutina
dia3.rutina = rutina
dia1.ejercicios = dia_form_1.ejercicios
dia2.ejercicios = dia_form_2.ejercicios
dia3.ejercicios = dia_form_3.ejercicios
dia1.save()
dia2.save()
dia3.save()
return redirect(historial_rutinas_view)
else:
form = RutinaForm()
dia_form_1 = DiaForm()
dia_form_2 = DiaForm()
dia_form_3 = DiaForm()
return render(request, 'rutinas/nueva-rutina.html', {'form': form, 'dia_form_1': dia_form_1, 'dia_form_2': dia_form_2, 'dia_form_3': dia_form_3})
Related
i am new to this, any recommendations are accepted, my main problem is that i have some foreign keys that are getting assigned in my database.
As you can see the last 4 models are related to the patient model through a Foreign Key, these are the fields that are not getting assigned in my project.
Models
class Patient(models.Model):
Codigo = models.CharField(max_length=20,default=None,null=False)
Nombres = models.CharField(max_length=100,null=False)
Apellidos = models.CharField(max_length=100,null=False)
Fecha_Nacimiento = models.DateField()
Numero_Telefonico = models.CharField(max_length=200,default=' ')
Email = models.CharField(max_length=256,unique=True,blank=True,default=' ')
Genero = models.ForeignKey(Gender,on_delete=models.DO_NOTHING,default=None,null=True)
Nacionalidad = models.ForeignKey(Nationality,on_delete=models.DO_NOTHING,default=None,null=True)
Estado_Civil = models.ForeignKey(CivilStatus,on_delete=models.DO_NOTHING,null=True)
Ocupacion = models.CharField(max_length=200)
Lugar_de_Procedencia = models.CharField(max_length=200)
Lugar_de_Residencia = models.CharField(max_length=200)
def __str__(self):
return self.Nombres + ' ' + self.Apellidos
class MedicalInfo(models.Model):
Expediente = models.CharField(max_length=500,blank=True)
Sangre = models.ForeignKey(BloodType,on_delete=models.DO_NOTHING,default=None,null=True)
Peso = models.FloatField()
Estatura = models.FloatField()
Alergia = models.ForeignKey(Allergies,on_delete=models.CASCADE,default=None,null=True)
Observacion = models.CharField(max_length=500,default= ' ',null=True)
Paciente = models.OneToOneField(Patient,on_delete=models.CASCADE,default=None,blank=True,null=True)
class InsuranceInfo(models.Model):
Seguro = models.ForeignKey(InsuranceCompany,on_delete=models.DO_NOTHING, default=None,blank=True,null=True)
Tipo_de_Poliza = models.ForeignKey(Policy,on_delete=models.DO_NOTHING,default=None,blank=True,null=True)
Numero_Poliza = models.IntegerField(default=None,blank=True,null=True)
Vencimiento = models.DateField(default=None,blank=True,null=True)
Paciente = models.OneToOneField(Patient,on_delete=models.CASCADE,default=None,blank=True,null=True)
class Relatives(models.Model):
Parentesco = models.ForeignKey(Family_relation, on_delete=models.DO_NOTHING,default=None,blank=True,null=True)
Nombre = models.CharField(max_length=100,blank=True)
Apellido = models.CharField(max_length=100,blank=True)
Telefono = models.CharField(max_length=100,blank=True)
Correo = models.EmailField(blank=True)
Nacimiento = models.DateField(blank=True,null=True)
Pariente = models.OneToOneField(Patient,on_delete=models.CASCADE,default=None,blank=True,null=True)
def __str__(self):
return self.Nombre + ' ' + self.Apellido
class Background(models.Model):
Padecimiento = models.CharField(max_length=200)
Control = models.CharField(max_length=200)
Medicamento = models.CharField(max_length=500)
Paciente = models.OneToOneField(Patient,on_delete=models.CASCADE,default=None,blank=True,null=True)
These are my forms, you can see that i exluded the 'Paciente' or 'Pariente' field (depending on the name of the model) in some of them because i want to assigned that field a value through a view which i will show you above the forms section.
Forms
class PatientForm(forms.ModelForm):
class Meta:
model = Patient
fields = '__all__'
widgets = {
'Fecha_Nacimiento': DateInput()
}
class RelativesForm(forms.ModelForm):
class Meta:
model = Relatives
exclude = ('Pariente',)
widgets = {
'Nacimiento': DateInput()
}
class MedicalInfoForm(forms.ModelForm):
class Meta:
model = MedicalInfo
exclude = ('Paciente',)
class InsuranceInfoForm(forms.ModelForm):
class Meta:
model = InsuranceInfo
exclude = ('Paciente',)
class BackgroundForm(forms.ModelForm):
class Meta:
model = Background
exclude = ('Paciente',)
This is the view i was talking about, in here i attempted to create a view containing all those forms and show it as one, the 'Patient' i created i this form is the one i want to assign to the field i excluded in the forms, that's why i excluded it because i wanted to assigned it manually, this is my attempt, i don't know what i am doing wrong or is missing. Any recommendations or solutions are accepted. Thanks!
Views
def PatientFormView(request):
if request.method == 'POST':
patientinfo = PatientForm(data=request.POST)
medicalinfo = MedicalInfoForm(data=request.POST)
insuranceinfo = InsuranceInfoForm(data=request.POST)
backgroundinfo = BackgroundForm(data=request.POST)
first_relative = RelativesForm(data=request.POST)
if patientinfo.is_valid() and medicalinfo.is_valid() and backgroundinfo.is_valid() and insuranceinfo.is_valid() and first_relative.is_valid():
patient = patientinfo.save()
patient.save()
medicalinfo.save(commit=False)
medicalinfo.Paciente = patient
medicalinfo.save()
backgroundinfo.save(commit=False)
backgroundinfo.Paciente = patient
backgroundinfo.save()
insuranceinfo.save(commit=False)
insuranceinfo.Paciente = patient
insuranceinfo.save()
first_relative.save(commit=False)
first_relative.Pariente = patient
first_relative.save()
return HttpResponseRedirect(reverse('patients'))
else:
patientinfo = PatientForm()
medicalinfo = MedicalInfoForm()
insuranceinfo = InsuranceInfoForm()
backgroundinfo = BackgroundForm()
first_relative = RelativesForm()
return render(request,'patients/patient_form.html',context={'patientinfo':patientinfo,'backgroundinfo':backgroundinfo,'first_relative':first_relative,'medicalinfo':medicalinfo,'insuranceinfo':insuranceinfo})
You are trying to update form instances. Change them as:
insurance = insuranceinfo.save(commit=False)
insurance.Paciente = patient
insurance.save()
Apply this approach to other models.
I have an app that creates modelForms dynamically based on models. These forms must be dynamically loaded on the template.
I need to write a function in my view that gets all the forms from forms.py or gets a specific form by it's name. Something similar to get_models(appName) and get_model(AppName, modelName) but for forms instead of models.
How can I write it and where should I write it?
in Registery or in forms or somewhere else?
Here is my code:
Models.py
class PrimaryInfo(models.Model):
Name = models.CharField(max_length=200, blank=False, null=True) #required. Must be filled by user
Surname = models.CharField(max_length=200, blank=False, null=True)
DateOfBirth = models.DateField('date of birth', blank=False, null=True)
<Some Other fields>
...
def calculateAge(self):
if not self.DateOfBirth is None:
thisYear = timezone.now().date().year
return thisYear - self.DateOfBirth.year
pass
<some other functions>
...
#Here come all the related tables
class Jobs(models.Model):
Rel = models.ForeignKey(PrimaryInfo, on_delete=models.CASCADE)
Job = models.CharField(max_length=200)
Age = models.IntegerField(default=0)
Country = models.CharField(max_length=200)
def __str__(self):
return self.Job
<some other related models>
....
My View:
def detail(request, personId):
appName = urls.app_name
tablesPrefix = appName + '_'
person = PrimaryInfo.objects.get(pk = personId)
peopledbModels = apps.get_models(appName)
fieldsList = []
relatedModels = []
relationshipsDic = {}
formsFileName = "write.py"
parentModelForms = []
# identify which models are parent and which ones are relationships. makes a dictionary (Of string, list) for the results.
for m in peopledbModels:
if m._meta.db_table.startswith(appName):
fields = m._meta.get_fields()
for fld in fields:
if fld.is_relation:
if fld.many_to_one or fld.many_to_many or fld.one_to_one:
pass
else:
relatedModels.append(fld.name)
relationshipsDic["{}".format(m._meta.label).replace("{}.".format(appName),"")] = relatedModels
#Write the modelForm from parent model into forms.py
for pmdl in relationshipsDic.keys():
parentModelName = pmdl
modelFormExist = False
with open("{}{}/{}".format(djangoSettings.MEDIA_ROOT, appName, formsFileName)) as file:
if "class {}Form(forms.ModelForm):".format(parentModelName) in file.read():
file.close()
modelFormExist = True
if modelFormExist == False:
with open("{}{}/{}".format(djangoSettings.MEDIA_ROOT, appName, formsFileName), "a+") as file:
file.write("\n\nclass {0}Form(forms.ModelForm):\n\tclass Meta:\n\t\tmodel = {0}\n\t\tfields = '__all__'".format(parentModelName))
file.close()
parentModel = apps.get_model(appName, pmdl)
instance = get_object_or_404(parentModel, pk=personId)
parentModelForm = "{}Form".format(pmdl) #this is where I need to get the form object with a variable name from forms.py
parentModelForm = parentModelForm(instance = instance) #this is not working (string object is not callable)
parentModelForms.append(parentModelForm)
<then pass this list of models to the template>
...
My forms (automatically populated from my view):
class PrimaryInfoForm(forms.ModelForm):
class Meta:
model = PrimaryInfo
fields = '__all__'
class JobsForm(forms.ModelForm):
class Meta:
model = Jobs
fields = '__all__'
models.py
class Products(models.Model):
company = models.ForeignKey(Companys)
name = models.CharField(unique = True, max_length = 50)
description = models.CharField(unique = True, max_length = 500)
price = models.PositiveIntegerField()
in_stock = models.BooleanField(default = True)
crated = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
forms.py
class ProductForm(forms.ModelForm):
class Meta:
model = Products
fields = '__all__'
name = forms.CharField()
description = forms.CharField(widget = forms.Textarea, )
company = forms.ModelChoiceField(queryset = Companys.objects.all(), label = 'Company')
in_stock = forms.BooleanField(initial = True)
price = forms.IntegerField()
views.py
class ProductCreate(CreateView, ProductEditMixin):
model = ProductForm
template_name = 'store/product_add.html'
fields = '__all__'
def post(self, request, *args, **kwargs):
self.success_url = reverse('get_context_data', kwargs = {'pk' : Companys.objects.first().id})
return super(ProductCreate, self).post(request, *args, **kwargs)
Please help me. Without forms code work. But with forms i have AttributeError: 'ModelFormOptions' object has no attribute 'virtual_fields' error
ProductForm is a form, not a model. It should go in the view's form_class attribute, not model.
(I also don't understand why your ProductForm uses the Company model rather than Product, but never mind.)
I couldn't find any solution in previous answers so i'm here asking how to register the result of a form field made by a queryset. Maybe i'm doing wrong something simple here how ever my model are:
#python_2_unicode_compatible
class Choice(models.Model):
choice_text = models.CharField(max_length=100)
def __str__(self):
return self.choice_text
#python_2_unicode_compatible
class Contatto(models.Model):
contatto_choice = models.ForeignKey(Choice, on_delete=models.PROTECT)
phone_number = models.CharField(max_length=12)
email = models.CharField(max_length=100)
text = models.CharField(max_length=250)
def __str__(self):
return self.email
class ContactForm(ModelForm):
class Meta:
model = Contatto
fields = ['contatto_choice', 'phone_number','email','text']
My forms.py is:
class ContactForm(forms.Form):
contatto_choice = forms.ModelChoiceField(queryset=Choice.objects.all())
phone_number = forms.CharField(max_length=12)
email = forms.CharField(max_length=100)
text = forms.CharField(widget=forms.Textarea, max_length=500)
and my views is:
def contatti(request):
if request.method=="POST":
form = ContactForm(request.POST)
if form.is_valid():
contatto = Contatto()
contatto.phone_number = form.cleaned_data['phone_number']
contatto.email = form.cleaned_data['email']
contatto.text = form.cleaned_data['text']
contatto.contatto_choice = form.cleaned_data['contatto_choice']
contatto.save()
recipients = ['cercaservizi#gmail.com']
send_mail("Contatto Cercaservizi", contatto.phone_number+' '+contatto.email+' '+contatto.text,contatto.email, recipients)
return HttpResponseRedirect('/')
else:
form = ContactForm()
return render(request, 'form.html', {'form': form})
The view of the submitted form complains about the fact that a contatto_choice should be an instance of a choice i cannot find any tutorial about how to solve this. If you could help it would be appreciated.
Edit Your ContactForm
class ContactForm(ModelForm):
contatto_choice = forms.ModelChoiceField(queryset=Choice.objects.all())
class Meta:
model = Contatto
fields = ['contatto_choice', 'phone_number','email','text']
and you will not need other form
I have the following models -
class Jobdtl(models.Model):
jobdtl_id = models.IntegerField(primary_key=True)
jobdtl_cmd = models.TextField(blank=True)
jobdtl_envfile = models.TextField(blank=True)
jobdtl_retnsn = models.SmallIntegerField(blank=True, null=True)
jobdtl_allowadhoc = models.CharField(max_length=1, blank=True)
jobdtl_waitop = models.CharField(max_length=1, blank=True)
class Meta:
managed = False
db_table = 'jobdtl'
class Jobmst(models.Model):
jobmst_id = models.IntegerField(primary_key=True)
jobmst_prntid = models.IntegerField(blank=True, null=True)
jobmst_active = models.CharField(max_length=1, blank=True)
jobmst_evntoffset = models.SmallIntegerField(blank=True, null=True)
jobmst_name = models.TextField(blank=True)
jobmst_owner = models.IntegerField(blank=True, null=True)
jobmst_crttm = models.DateTimeField()
jobdtl_id = models.ForeignKey('Jobdtl', db_column='jobdtl_id', related_name='mstdtl', blank=True, null=True)
jobmst_lstchgtm = models.DateTimeField(blank=True, null=True)
def __unicode__(self):
return self.jobmst_name
class Meta:
managed = False
db_table = 'jobmst'
I'm trying to generate a json similar to what we have here -
http://stackoverflow.com/questions/19709101/django-rest-framework-multiple-models
using the steps here -
http://stackoverflow.com/questions/16793608/how-to-write-a-django-rest-framework-serializer-field-to-merge-data-from-gener
These are my serializers -
class JobmstSerializer(serializers.ModelSerializer):
class Meta:
model = Jobmst
class JobdtlSerializer(serializers.ModelSerializer):
jobmst_id = JobmstSerializer(many=True)
class Meta:
model = Jobdtl
And this is my view
class ResultsList(ListAPIView):
def list(self, request, *args, **kwargs):
jobmstquery = Jobmst.objects.using('Admiral').all()
jobdtlquery = Jobdtl.objects.using('Admiral').all()
results = list()
entries = list(chain(jobmstquery, jobdtlquery)) # combine the two querysets
for entry in entries:
type = entry.__class__.__name__.lower() # 'jobmst', 'jobdtl'
if isinstance(entry, Jobmst):
serializer = JobmstSerializer(entry)
dictionary = {'type': jobmst, 'jobmst_id': jobmst_id, 'jobmst_type': jobmst_type, 'jobmst_prntid': jobmst_prntid, 'jobmst_active': jobmst_active, 'evntmst_id': evntmst_id, 'jobmst_evntoffset': jobmst_evntoffset, 'jobmst_name': jobmst_name, 'jobmst_mode': jobmst_mode, 'jobmst_owner': jobmst_owner, 'jobmst_desc': jobmst_desc, 'jobmst_crttm': jobmst_crttm, 'jobdtl_id': jobdtl_id, 'jobmst_lstchgtm': jobmst_lstchgtm}
if isinstance(entry, Jobdtl):
serializer = JobdtlSerializer(entry)
dictionary = {'type': jobdtl, 'jobdtl_id': jobdtl, 'jobdtl_cmd': jobdtl_cmd, 'jobdtl_envfile': jobdtl_envfile, 'jobdtl_retnsn': jobdtl_retnsn, 'jobdtl_allowadhoc': jobdtl_allowadhoc, 'jobdtl_waitop': jobdtl_waitop}
results.append(dictionary)
return Response(results)
I tie it through my URL -
urlpatterns = patterns('TidalDEV.views',
url(r'^TidalDEV/$', 'ResultsList'),
url(r'^TidalDEV/(?P<pk>[0-9]+)/$', 'ResultsList'),
)
But when I hit my URL at http://localhost/TidalDEV/ or http://localhost/TidalDEV/50244/
I get slammed with an error -
Exception Type: TypeError
Exception Value:
__init__() takes 1 positional argument but 2 were given
Exception Location: D:\Python33\lib\site-packages\django\core\handlers\base.py in get_response, line 114
I ended up doing the following and it worked -
class JobdtlSerializer(serializers.ModelSerializer):
class Meta:
model = Jobdtl
class JobmstSerializer(serializers.ModelSerializer):
jobdtl_id = JobdtlSerializer()
class Meta:
model = Jobmst
then connected with the variation of the default views -
#csrf_exempt
def jobmst_list(request):
"""
List all code snippets, or create a new snippet.
"""
if request.method == 'GET':
DEV = Jobmst.objects.using('AdmiralDEV').all()
serializer = JobmstSerializer(DEV, many=True)
return XMLResponse(serializer.data)
elif request.method == 'POST':
data = XMLParser().parse(request)
serializer = JobmstSerializer(data=data)
if serializer.is_valid():
serializer.save()
return XMLResponse(serializer.data, status=201)
else:
return XMLResponse(serializer.errors, status=400)
#csrf_exempt
def jobmst_detail(request, pk):
"""
Retrieve, update or delete a code snippet.
"""
try:
DEV = Jobmst.objects.using('AdmiralDEV').get(jobmst_id=pk)
except Jobmst.DoesNotExist:
return HttpResponse(status=404)
if request.method == 'GET':
serializer = JobmstSerializer(DEV)
return XMLResponse(serializer.data)
elif request.method == 'PUT':
data = XMLParser().parse(request)
serializer = JobmstSerializer(DEV, data=data)
if serializer.is_valid():
serializer.save()
return XMLResponse(serializer.data)
else:
return XMLResponse(serializer.errors, status=400)
elif request.method == 'DELETE':
DEV.delete()
return HttpResponse(status=204)
That allowed me to get from the 2 separate models. It's unformatted and ugly but proves it can be done. Need to figure out how to link more than these 2 models now (I have 5 minimum).