Django relationship in manyToMany models, object has no attribute - python

I have a problem with creating relationship in m2m models.
models.py
class ECG(models.Model):
procedure= models.ManyToManyField('Procedure')
...
class Procedure(models.Model):
basic_info= models.IntegerField(default=0)
views.py
def newECG(request, procedure_id):
if request.method == 'POST':
form = NewECG(request.POST)
if form.is_valid():
form.save()
info = IncomingProcedure.objects.get(id=procedure_id)
form.procedure.add(info) #HERE IS A PROBLEM
return HttpResponseRedirect('/system/')
else:
form = NewECG()
return render(request, 'system/ecg.html', {'form': form})
forms.py
class NewECG(ModelForm):
class Meta:
model = ECG
exclude = ['procedure']
# fields = '__all__'
fields = [ ... ] # rest fields, except procedure
Procedure already exists. I need to create newECG in relation with procedure. ECG form is saving in db. Problem is when i want to use add() function.
ERROR :'NewECG' object has no attribute 'procedure', exception location: views.py

The ModelForm instance does not have the procedure attribute that is defined on the model. The ECG model instance, however, which is returned by the form's save(...) method, does have it:
ecg_instance = form.save()
info = IncomingProcedure.objects.get(id=procedure_id)
# info = Procedure.objects.get(id=procedure_id)
ecg_instance.procedure.add(info)

You just forgot a step:
def newECG(request, procedure_id):
if request.method == 'POST':
form = NewECG(request.POST)
if form.is_valid():
ecg = form.save()
info = IncomingProcedure.objects.get(id=procedure_id)
ecg.procedure.add(info) #HERE IS A PROBLEM
return HttpResponseRedirect('/system/')

I can't understand why you are trying to add IncomingProcedure.objects to your from in views.py
If you want save it on your database, Should simply do this:
views.py
# ... Your codes:
M = form.save() # save your class instance to M variable
info = IncomingProcedure.objects.get(id=procedure_id)
M.procedure.add(info) # save procedure instance to your object(An ECG model instance)

Related

Django using a modelform to update an instance of model

I have the following model in Django which I use to store data about medicines.
class Medicine(models.Model):
Medicine_Name = models.CharField(max_length=100)
User_Associated = models.ForeignKey(User, on_delete=models.CASCADE)
Tablets_In_Box = models.IntegerField()
Dose_in_mg = models.IntegerField()
Dose_Tablets = models.IntegerField()
Number_Of_Boxes = models.IntegerField()
Last_Collected = models.DateField()
def __str__(self):
return self.Medicine_Name
def get_absolute_url(self):
return reverse('tracker-home')
I am trying to create a model form where a user can update the last collection of one of their medicines. Here is what I began with.
class CollectionForm(forms.ModelForm):
class Meta:
model = Medicine
fields = ['Medicine_Name', 'Number_Of_Boxes', 'Last_Collected']
I do not understand how I can call an instance of my model based on the 'Medicine_Name' from the field. In other words, I need the user to be able to select the correct medicine from a dropdown menu, and then the form must update the 'Last_Collected', and 'Numer_Of_Boxes' fields on my Medicine model.
https://docs.djangoproject.com/en/2.1/topics/forms/modelforms/#the-save-method
It seems this contains relevant information, but I struggle to see how to use it in this instance. How can I correctly get the instance of the medicine form I need, based on the user input in the form? Furthermore how can I use the save method in my views to make sure the database gets updated correctly?
EDIT Added view for the form:
def update(request, pk):
instance = Medicine.objects.get(id=pk)
if request.method == 'POST':
form = CollectionForm(user=request.user, instance=instance, data=request.POST)
if form.is_valid():
instance = form.save(commit=False)
instance.User_Associated = request.user
instance.save()
else:
form = CollectionForm()
context = {'form': form}
return render(request, 'tracker/medicine_collection.html', context )
**EDIT
views:
def update(request, pk):
instance = Medicine.objects.get(id=pk)
if request.method == 'POST':
form = CollectionForm(instance=instance, data=request.POST)
if form.is_valid():
instance = form.save(commit=False)
instance.User_Associated = request.user
instance.save()
return redirect ('/')
....
This is based on updating the instance of the specific user. This tutorial helpt me achieve the same thing.
https://youtu.be/EX6Tt-ZW0so
Tried a different approach (class based views - UpdateView) I just learned here on SO. Did not test it but I think its a step in the right direction.
class UpdateMedicine(LoginRequiredMixin, UpdateView):
model = Medicine #call the model you need to update
fields = ['Medicine_Name', 'Number_Of_Boxes', 'Last_Collected'] #specify the fields you need to update
template_name_suffix = 'medicine_update_form' #specify the template where the update form is living
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context.update(
user=self.request.user, #get the current logged in user
instance=get_object_or_404(Medicine, pk=self.kwargs['pk']) #get the pk of the instance
)
return context
def form_valid(self, form):
form.instance.medicine = get_object_or_404(Medicine, slug=self.kwargs['pk'])
return super().form_valid(form) #saves the updates to the instance
def get_success_url(self):
return reverse('medicine-collection') #name of the url where your 'tracker/medicine_collection.html is living
Link the appropriate templates and urls to the above example and try some things yourself.
Link to the django docs:
https://docs.djangoproject.com/en/3.0/ref/class-based-views/generic-editing/
Good luck!

Django Form ForeignKey save

Sry for stupid question, but I don't understand. I'm trying to use Django Forms, I have 2 models
class Post(models.Model):
unit = models.ForeignKey('Unit',on_delete=models.CASCADE, primary_key=False)
and
class Unit(models.Model):
name = models.CharField(max_length=120, unique = True)
I've created a form
from django import forms
from .models import Post, Unit, StatusOfPost
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = [
'unit',
]
than I've written a view.py
def ideaNewForm(request):
unit = Unit.objects.get(name=request.POST['unit'])
user = request.user
if request.method == 'POST':
form = PostForm(request.POST)
if form.is_valid():
idea = form.save(commit=False)
idea.unit = unit
idea = Post.objects.create(
author = user,
)
return redirect('postsList')
else:
form = PostForm()
return render(request, 'post_new.html', {'form':form})
Unit matching query does not exist.- and i have that such issue.
I have a dropdown list it is a Unit model. How save it right?
Before I did it without Django Form
unit = Unit.objects.get(name=request.POST['unit'])
and it worked well, but I want use Django Forms
I'm not quite sure why you are trying to get the unit separately. It's what is selected in the form, there is no need to get it; just saving the form will create the post with the selected unit. The only thing you need to do is to add the user.
def ideaNewForm(request):
if request.method == 'POST':
form = PostForm(request.POST)
if form.is_valid():
idea = form.save(commit=False)
idea.author = request.user
idea.save()
return redirect('postsList')
else:
form = PostForm()
return render(request, 'post_new.html', {'form':form})
You just missing a ['unit'] after request.POST:
def ideaNewForm(request):
unit = Unit.objects.get(name=request.POST['unit'])
(...remaining codes...)

django - form.cleaned_data[] for all fields in model

I am using django to digitalise a form. This form is a little bit complex, and there are a lot of fields in it. I was wondering if Django could do form.cleaned_data[] for all fields, in stead of declaring variables like obj.fieldname = form.cleaned_data['fieldname'] for each field apart.
I tried it with a forloop in the views.py, but that won't work
This is the forloop I'm talking about:
def get_form_naw(request):
if request.method == 'POST':
form = Form1(request.POST)
if form.is_valid():
for x in Model1():
formname = x.name
o = Model1()
o.formname = form.cleaned_data[formname]
o.save()
else:
form = Form1
return render(request, 'folder/home.html', context=locals())
I'm using a mysql database. My forms are declared like this:
forms.py
class Form1(forms.ModelForm):
class Meta:
model = Model1
exclude = ('id')
You shouldn't have to loop through the fields. You are using a model form, so you should just save the form:
if form.is_valid():
obj = form.save()
...
If you really need to set fields dynamically, you can use setattr.
fieldname = 'username'
value = 'my_user'
setattr(obj, fieldname, value)
you can get the instance of the data before saving like this:
if form.is_valid():
obj = form.save(commit=False) #get instance without saving
# do your thing
obj.save() #save into database

model no iterable "create by user" django

I have a problem, when i try upload files I am trying show the user uploaded the file but not working.
My model is this:
class Document(models.Model):
id = models.AutoField(primary_key=True)
programa=models.CharField(max_length = 100)
materia=models.CharField(max_length = 50)
profesor=models.CharField(max_length = 50)
usuario=models.ForeignKey(Usuario)
add=models.DateTimeField ( auto_now = True )
archivo= models.FileField(upload_to="archivos/",storage=OverwriteStorage(),null = False)
def __unicode__(self):
return self.programa
class Meta:
db_table = u'utp_document'
My view is:
#login_required(login_url='/')
def upload(request):
if request.method=='POST':
form=DocumentForm(request.POST,request.FILES,)
if form.is_valid():
instances = form.save(commit=False)
for instance in instances:
instance.usuario = request.user
instance.save()
return HttpResponseRedirect('/menu/')
else:
form=DocumentForm()
return render_to_response('formulario_modal.html', {'form': form}, context_instance=RequestContext(request))
I followed this post Django - Auto populate created_by field outside django admin using form.
and this my form.py:
class DocumentForm(forms.ModelForm):
class Meta:
model = Document
exclude = ('usuario',)
The problem is what i try new upload file get this error:
'Document' object is not iterable
What am I doing wrong?
form.save() returns a single modal instance:
instance = form.save(commit=False)
instance.usuario.user = request.user
instance.save()
FYI, in the post you've linked a formset is used which is the reason for a loop.

Django, save ModelForm

I have created a model Student which extends from the Django User and is a foreign key to another model while it has an integer field called year. What i'm trying to do is to save a form, which has 2 fields. The one is the course id and the another one is the the integer field year. When I'm clicking submit, i'm getting an error Cannot assign "u'2'": "Student.course" must be a "Course" instance.
models.py
class Student(models.Model):
user = models.OneToOneField(User)
course = models.ForeignKey(Course)
year = models.IntegerField(validators=[MinValueValidator(1),
MaxValueValidator(7)])
view.py
def step3(request):
user = request.user
if request.method == 'POST':
form = SelectCourseYear(request.POST)
if form.is_valid():
form.save()
return render_to_response("registration/complete.html", RequestContext(request))
else:
form = SelectCourseYear()
return render(request, 'registration/step3.html',)
forms.py
class SelectCourseYear(forms.ModelForm):
course = forms.CharField()
year = forms.IntegerField(required=True)
class Meta:
model = Student
fields = ['user', 'course', 'year']
You dont need to redefine fields in the ModelForm if you've already mentioned them in the fields attribute. So your form should look like this -
class SelectCourseYear(forms.ModelForm):
class Meta:
model = Student
fields = ['course', 'year'] # removing user. we'll handle that in view
And we can handle the form with ease in the view -
def step3(request):
user = request.user
if request.method == 'POST':
form = SelectCourseYear(request.POST)
if form.is_valid():
student = form.save(commit=False)
# commit=False tells Django that "Don't send this to database yet.
# I have more things I want to do with it."
student.user = request.user # Set the user object here
student.save() # Now you can send it to DB
return render_to_response("registration/complete.html", RequestContext(request))
else:
form = SelectCourseYear()
return render(request, 'registration/step3.html',)
course has to be an instance of a Course model, not just the primary key of the instance. You can still accept an id in the form as a text input, but you're going to need to retrieve the actual course instance and assign the value.
You'll need to verify that the course id is valid, so putting that code into the clean method isn't a bad idea. Notice also how the course field is excluded here? Otherwise the form will expect it to be present. You also don't need to re-define the year field, as the ModelForm will inherit that field from the Student model.
# forms.py
class SelectCourseYear(forms.ModelForm):
class Meta:
model = Student
exclude = ['user', 'course']
course_id = forms.IntegerField()
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user')
super(SelectCourseYear, self).__init__(*args, **kwargs)
def clean_course_id(self):
course_id = self.cleaned_data.get('course_id')
try:
self.course = Course.objects.get(pk=course_id)
except Course.DoesNotExist:
raise forms.ValidationError('Sorry, that course id is not valid.')
return course_id
def save(self, commit=True):
instance = super(SelectCourseYear, self).save(commit=False)
instance.course = self.course
instance.user = self.user
if commit:
instance.save()
return instance
# views.py
def step3(request):
if request.method == 'POST':
form = SelectCourseYear(request.POST or None, user=request.user)
if form.is_valid():
form.save()
return render_to_response("registration/complete.html",
RequestContext(request))
return render(request, 'registration/step3.html',)
Now, when you call .save() on the model, the course field will be assigned an instance of Course

Categories