Problem saving data in a modelform - django

I have a modelform set up for a user to enter his contact info. The validation and form.is_valid() method is working, however the request.POST data is not being stored to the db, and I'm having trouble figuring out what the problem is. Here is what I currently have --
# model
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
contact_email = models.EmailField(max_length=100, blank=True)
contact_phone = models.IntegerField(max_length=11, blank=True)
website = models.CharField(max_length=256, blank=True)
class ContactInfoForm(ModelForm):
class Meta:
model = UserProfile
fields = ('contact_email', 'contact_phone', 'website',)
# view
#login_required
def edit_contact(request):
contact_email = request.user.get_profile().contact_email
form = ContactInfoForm(initial={'contact_email':contact_email,})
if request.method == 'POST':
form = ContactInfoForm(request.POST, instance=request.user)
if form.is_valid():
form.save()
return render_to_response(...)
# template
<form action="." method="post"> {% csrf_token %}
<table>
{{form}}
</table>
<p><input type="submit" name="save_changes" value="Save Changes" ></p>
</form>

I think the error might be the instance you're calling in your ModelForm. You need to use a UserProfile instance, but you're using a User instance. The following might work (untested):
#login_required
def edit_contact(request):
contact_email = request.user.get_profile().contact_email
form = ContactInfoForm(initial={'contact_email':contact_email,})
user_profile = UserProfile.objects.get(contact_email=contact_email)
if request.method == 'POST':
form = ContactInfoForm(request.POST, instance=user_profile)
if form.is_valid():
form.save()
return render_to_response(...)

Related

How to have pre/post populated id field in django form submission

What I am trying to achieve is to have my "student_id" auto-generated field to be part of the form submission in the sense that the "student_id" field does not have to be manually input in form submission:
The "student_id" field needs to be either pre-generated upon displaying the form or to be generated upon form submission.
I have tried and currently facing error when submitting form as bellow:
KeyError at 'student_id'
Exception Value: 'student_id'
Removing the "student_id = form.cleaned_data['student_id']" syntax in views.py does not help either.
I have the following model, which generates an auto "student_id" field
class Student(models.Model):
student_id = models.AutoField(primary_key=True,unique=True, max_length=10, blank=False)
name = models.CharField(max_length=200, blank=False)
first_name = models.CharField(max_length=100, blank=True)
last_name = models.CharField(max_length=100, blank=True)
def __str__(self):
return self.name
my forms.py:
Class StudentForm(forms.ModelForm):
class Meta:
model = Student
fields = [
'student_id','name', 'first_name', 'last_name'
]
my views.py:
def index(request):
if request.method == 'POST':
form = StudentForm(request.POST, or None)
if form.is_valid():
student_id = form.cleaned_data['student_id']
form.save()
else:
FormError = StudentForm.errors
return redirect(f'/card/{student_id}')
else:
form = StudentForm()
template_name = 'index.html'
context = {
'form' : form,
}
return render(request, template_name, context)
my html:
<form method="POST" action="{% url 'student:index' %}" enctype="multipart/form-data">{% csrf_token %}
<div class="form-group">
{{ form | crispy }}
</div>
<input type="submit" value="Envoyer" class="btn btn-primary btn-lg btn-block">
</form>
Will appreciate any help

Django upload image using page slud/id

I'm trying to add the ability to upload an image to a post but having issues.
The image field is in its own model but uses a foreign key to show which post it relates to.
At the moment the upload button does not post the form but also how would I use the post page url/slug/id as the image foreign key.
Would i need to call it in the html post page?
views.py
def designUpload(request):
if request.method == 'POST':
form = ImageForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return render(request, 'users/dashboard.html')
else:
form = ImageForm()
return render(request, 'users/dashboard.html', {
'form': form
})
**models.py**
class Designs(models.Model):
forbrief = models.ForeignKey(Brief, on_delete=CASCADE)
postedby = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
design = models.ImageField(null=True, blank=True)
date = models.DateTimeField(auto_now=True, blank=True)
forms.py
class ImageForm(forms.ModelForm):
class Meta:
model = Designs
fields = ["design",]
HTML Form
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
<input type="image" name="mydesign">
<button type="submit">Upload</button>
</form>

Django MultiValueDictKeyError for upload file

There has a file upload page for upload file to a object by id in model. However, it shown MultiValueDictKeyError after submitted. I would appreciate if any help.
models.py:
class Order(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, blank=True, null=True)
items = models.ManyToManyField(OrderItem)
img_upload = models.FileField(upload_to='payment', null=True)
forms.py:
class Upload_File(forms.Form):
class Meta:
model = Order
fields = ('img_upload')
views.py:
def upload_page(request, id):
order = get_object_or_404(Order, id=id)
form = Upload_File(request.POST or None, request.FILES or None)
if request.method == 'POST':
order.img_upload = request.FILES['file']
if form.is_valid():
form.save()
messages.success(request, 'Succeed')
return redirect('user_info')
else:
form = Upload_File()
context = {
'form': form,
}
return render(request, 'upload.html', context)
html:
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<input class="form-group" type="file" name="file">
<button class="form-group" type="submit">Submit</button>
</form>

Django is rendering empty template to create new profile instead of submitting form

First some code:
models.py
class Findings(models.Model):
patient = models.ForeignKey(Profile, null=True, blank=True, on_delete=models.CASCADE)
finding_type = models.CharField(max_length=35, null=True)
upload = models.FileField(null=True, blank=True)
date_created = models.DateField(auto_now=True)
description = models.TextField(null=True, blank=True)
def __str__(self):
return self.finding_type
forms.py
class AddFindingForm(ModelForm):
class Meta:
model = Findings
fields = ('finding_type', 'description', 'upload', 'patient')
labels = {
'finding_type' : _('Rodzaj badania'),
'description': _('Opis'),
'upload': _('Dodaj plik'),
}
views.py
def add_finding(request):
form = AddFindingForm()
if request.method == 'POST':
form = UserProfileForm(request.POST, request.FILES)
if form.is_valid():
form = form.save(commit=False)
form.patient = request.user.profile
form.save()
return redirect('profile')
context = {'form': form}
return render(request, 'add_finding.html', context)
template
{% block content %}
<form method="POST" enctype="multipart/form-data" action="">
{% csrf_token %}
{{ form.as_p}}
<button type="submit"> Wyƛlij </button>
</form>
{% endblock %}
So, everytime i'm trying to submit a filled form it displays another form to create new Profile, even if i'm setting patient manually.
The empty form it's displaying is on the same url.
I have no idea why it's doing that...
You are submitting your request.POST data to wrong form. Doing this user's submitted data never gets into AddFindingForm() instead it should be,
def add_finding(request):
form = AddFindingForm()
if request.method == 'POST':
form = AddFindingForm(request.POST, request.FILES) # Change Here
if form.is_valid():
form = form.save(commit=False)
form.patient = request.user.profile
form.save()
return redirect('profile')
context = {'form': form}
return render(request, 'add_finding.html', context)

How to handle a form and formset in the same page?

I have both a form in and a formset for the same model. The first form that I have is written in HTML because I needed some kind of widgets which Django doesn't have out of the box.
models.py
class MyModel(models.Model):
name = models.CharField(max_length=255, null=True, blank=True)
phone_number = models.CharField(max_length=255, null=True, blank=True)
some_other_field = models.CharField(max_length=255, null=True, blank=True)
views.py
class MyView(View):
def get(self, request):
formset = modelformset_factory(MyModel, fields=('name', 'some_other_field', extra=2)
return render(request, 'index.html', context={'formset': formset})
def post(self, request):
formset = modelformset_factory(MyModel, request.POST, fields=('name', 'some_other_field'))
if formset.is_valid():
formset.save()
MyModel.objects.create(name=request.POST.get('name'))
return HttpResponse("done")
index.html
<form method="post" action="">
<input type="text" name="name">
{{ formset.management_form }}
{% for form in formset %}
{{form}}
{% endfor %}
</form>
This does not work at all, cause the request.POST sends all the irrelevant data to the modelformset such as in this case, the name field and I end up with this error.
AttributeError: 'QueryDict' object has no attribute '__name__'
This is not how you use a modelformset_factory, you cannot pass the data to it. modelformset_factory returns a class which you can then instantiate to pass it the data. Did you read this?
So you have to first have to create the class:
MyModelFormset = modelformset_factory(MyModel, fields=(...), extra=...)
Then you instantiate it:
formset = MyModelFormset()
# or
formset = MyModelFormset(request.POST)
or you can do that at once:
formset = modelformset_factory(MyModel, fields=..., extra=...)(request.POST)