Django Form Initial Value not Showing - django

I want to make a form to edit a model object, with the initial data being the original data (before the change), but it doesn't show,
it was just a blank form
models.py:
class Employee(models.Model):
first_name = models.CharField(max_length=200)
last_name = models.CharField(max_length=200)
forms.py:
class EmployeeForm(forms.ModelForm):
class Meta:
model = Employee
fields = ['first_name', 'last_name']
labels = {'first_name' : 'First Name:', 'last_name' : 'Last Name:' }
input_attrs = {'class' : 'form-control'}
widgets = {
'first_name' : forms.TextInput(attrs=input_attrs),
'last_name' : forms.TextInput(attrs=input_attrs)}
views.py:
def edit(request, id):
employee = Employee.objects.get(id=id)
data = {
'first_name' : employee.first_name,
'last_name' : employee.last_name,
}
form = EmployeeForm(request.POST or None, initial=data, instance=employee)
if (form.is_valid and request.method == 'POST'):
form.save()
return HttpResponseRedirect('/form/')
response = {'employee_form' : EmployeeForm, 'employee':employee}
return render(request, 'editemployee.html', response)
editemployee.html:
<div class="form">
<div class="form-group">
<form action="" method="POST">
{% csrf_token %}
{% for form in employee_form %}
{{ form.label }}
{{ form }}
<br>
{% endfor %}
<input type="submit" value="Submit" class="btn btn-primary">
</form>
</div>
</div>
Can anyone please tell me where I went wrong? I've tried so many things but to no avail. The form works fine, but the initial data doesn't show.

Editing an existing record, no initial data is needed, it comes from the model instance.
form = EmployeeForm(request.POST or None, instance=employee)
If you need default data in those fields, you can add it in the model.

Related

Django how to use a ModelChoiceField in a formset_factory

I am trying to use a modelchoicefield from the form in a formset_factory but i dont understand the error and don't know how to solve it.
(edit added the models.py)
models.py
class Order(Model):
user = ForeignKey(User, on_delete=SET_NULL, null=True)
fee = ForeignKey(Fee, on_delete=SET_NULL, null=True)
route = ForeignKey(Route, on_delete=SET_NULL, null=True)
price_rate = ForeignKey(PriceRate, on_delete=SET_NULL, null=True)
pallet_amount = IntegerField()
status = BooleanField()
postal_code = CharField(max_length=6)
city = CharField(max_length=255)
street = CharField(max_length=255)
delivery_from = DateTimeField()
delivery_until = DateTimeField(null=True)
created_at = DateTimeField(auto_now_add=True, blank=True)
updated_at = DateTimeField(auto_now=True)
deleted_at = DateTimeField(null=True, blank=True)
views.py
def routecreate_view(request):
orderformset = formset_factory(OrdersRouteForm, can_delete=False, extra=1)
if request.method == 'POST':
form = RouteForm(request.POST)
formset = orderformset(request.POST)
if form.is_valid() and formset.is_valid():
# process the data in form.cleaned_data as required
messages.success(request,
"You succesfully created an route.")
return HttpResponseRedirect(reverse('planner.dashboard'))
else:
form = RouteForm()
formset = orderformset()
return render(request, 'planner/route.html', {'form': form, 'formset': formset})
forms.py
class OrdersRouteForm(forms.ModelForm):
route = ModelChoiceField(
queryset=Order.objects.filter(status=1, delivery_until__gte=datetime.datetime.now(), deleted_at=None),
label='Order')
class Meta:
model = Order
fields = ("route",)
def __init__(self, *args, **kwargs):
super(OrdersRouteForm, self).__init__(*args, **kwargs)
for visible in self.visible_fields():
visible.field.widget.attrs['class'] = 'form-control m-2'
self.fields['route'].label_from_instance = self.label_from_instance
#staticmethod
def label_from_instance(obj):
return "pallets: %s, %s, %s, %s" % (obj.pallet_amount, obj.street, obj.city, obj.postal_code)
template:
{% extends 'base.html' %}
{% block base %}
<div class="container rounded bg-white mt-5 mb-5">
<div class="row">
<div class="col-md-5 border-right mx-auto">
planner//route
<div class="p-3 py-5">
<form id="form-container" method="POST">
{% csrf_token %}
{{ form }}
{{ formset }}
<button id="add-form" type="button">Add Another Bird</button>
<button class="btn btn-danger profile-button mt-3" onclick="window.history.back()">Cancel
</button>
<button class="btn btn-primary float-end mt-3" type="submit">Order</button>
</form>
</div>
</div>
</div>
</div>
{% endblock %}
error:
Cannot assign "<Order: Order object (2)>": "Order.route" must be a "Route" instance.
The error occurs when i fill the formset with request.POST and then try to send the formset to the template.
I have tried an inlineformset and modelformset and didnt get it to work. ANY solution is welcome.
The problem seemed to be with the modelform. I removed this from the code:
class Meta:
model = Order
fields = ("route",)
I don't understand why this caused the problem and if anyone knows and can explain it please feel free to do so.
hope it helps anyone else with this problem.

How to extract JSON value from a list and render it in a django model form?

I am trying to render a Django model form using the below model. The problem is one of the model field is a JSONField. This is a list of length 1 having some JSON data. When I render the model form, the number field renders the list without any issues. But I want to extract the phone value from the JSON inside the list and render it. I have tried extracting it in the template but it is not working as intended.
How can I extract the phone value from the JSON and render it in the form? As example, when I render the data for id 1 using my view, I should see 'Client_1' in the name field and '1234567890' in the number field.
I am using Django 3.1 and using Django Crispy Forms to render the model form.
Data as seen client table in db:
id name number
1 Client_1 [{'type': 'mobile', 'phone': '1234567890'}]
2 Client_2 [{'type': 'mobile', 'phone': '3334445555'}]
3 Client_3 [{'type': 'mobile', 'phone': '9876543210'}]
models.py:
class Client(models.Model):
name = models.TextField()
number = models.JSONField(blank=True, null=True)
forms.py:
from .models import Client
class ClientForm(forms.ModelForm):
class Meta:
model = Client
fields = '__all__'
clients.html template:
{% load crispy_forms_tags %}
<form method="POST">
<div class="form-row">
<div class="form-group col-md-6">
{{ form.name | as_crispy_field }}
</div>
<div class="form-group col-md-6">
{% for item in form.number %}
{{ item.0.phone | as_crispy_field }}
{% endfor %}
</div>
</div>
</form>
views.py:
def clients(request, pk):
instance = Client.objects.get(pk=pk)
if request.method == 'POST':
form = ClientForm(request.POST, instance=instance)
if form.is_valid():
form.save()
else:
form = ClientForm(instance=instance)
return render(request, 'clients.html', {'form': form})
You need add fields dynamically to your form, here is a working example :
class ClientForm(forms.ModelForm):
def __init__(self, *args, instance=None, **kwargs):
super(ClientForm, self).__init__(*args, instance=instance, **kwargs)
if instance:
for index, obj in enumerate(instance.number):
self.fields[f'phone_{index}'] = forms.CharField(initial=obj.get('phone', ''))
def save(self, commit=True):
for index, obj in enumerate(self.instance.number):
obj['phone'] = self.cleaned_data.get(f'phone_{index}', '')
return super(ClientForm, self).save(commit=commit)
class Meta:
model = Client
fields = ['name']
Your template should then be :
{% load crispy_forms_tags %}
<form method="POST">
<div class="form-row">
<div class="form-group col-md-6">
{{ form.name | as_crispy_field }}
</div>
<div class="form-group col-md-6">
{{ form.phone_0 | as_crispy_field }}
</div>
</div>
</form>
NB : If you alway store your phones in a list, you should set a default to your JsonField :
class Client(models.Model):
name = models.TextField()
number = models.JSONField(default=list)

Not able to pass the method as POST from django template to django view

I am making a Django form but not able to pass the form as a "POST" method. When I press the submit button, the form information is sent as "GET" which I can see by printing on the terminal. Hence the if condition in the code remains false. Please help me figure out what is going wrong here.
Below is the code for the rendering the template.
# Code for the /template.py#
{% block content %}
<div class="container">
<div class="row">
<div class="col-sm-8">
<h1>Please answer the question</h1>
<form method="post">
{% crispy user_form user_form.helper %}
<p><input type="submit" class='btn btn-primary' value="Submit"
method = "post"></p>
{% csrf_token %}
</form>
</div>
</div>
</div>
{% endblock %}
Below is the code in the views.py file.
# /*Code for the /views.py*/
def launch_survey(request, pagelink):
pagelink_html = pagelink+".html"
user_form = FormQuestionaire()
print(request.method)
if (request.method == 'post'):
print("We are not here")
user_form = FormQuestionaire(request.POST)
if user_form.is_valid():
print('Validation Success')
print("NAME: "+user_form.cleaned_data['First_name'])
return render(request, "modern_business/"+pagelink_html, {'user_form':user_form})
Below is the code in the forms.py file.
# /*FORMS.PY*/
from django import forms
from firstapp.models import Questionaire
from crispy_forms.helper import FormHelper
from django.core import validators
class FormQuestionaire(forms.ModelForm):
helper = FormHelper()
helper.form_show_labels = True
helper.form_class = 'form-group row'
helper._form_method = "post"
CHOICES = [('1', 'First'), ('2', 'Second')]
choice_field = forms.ChoiceField(choices=CHOICES,
widget=forms.RadioSelect,
label = "Do you like this website?", initial = '1',
required = True,)
mult_field
= forms.ChoiceField
(widget=forms.CheckboxSelectMultiple,
choices=CHOICES,
label = "Do you like our Checkbox?", required = True,)
class Meta:
model = Questionaire
fields = ['First_name', 'Last_name', 'email', 'paid']
labels = {'First_name': ('Enter Your first name') ,
'Last_name': ('Enter your last name'),
'Enter your email': ('Whether it is paid'),}
print(request.method) always prints GET even though form is set to POST.
The method is always in all caps.
if request.method == 'POST':

django - image isn't saving, all other fields are

When I update the user profile via the view everything is saving to the db except the image. The forms are validating but image isn't being saved. I can log in the admin portal and successfully add an image to an existing instance. I assume my problem lies in my html template but I can't figure out what it is.
**Btw I've read multiple similiar post but none I believe addresses my issue.
form.py
class EditUserForm(forms.ModelForm):
template_name='/something/else'
class Meta:
model = User
fields = (
'email',
'first_name',
'last_name',
)
class EditProfileForm(forms.ModelForm):
template_name='/something/else'
class Meta:
model = UserProfile
fields = (
'description',
'city',
'website',
'phone',
'image',
)
views.py
#transaction.atomic
def edit_profile(request):
if request.method == 'POST':
form = EditUserForm(request.POST, instance=request.user)
form2 = EditProfileForm(request.POST, instance=request.user.userprofile)
if form.is_valid() and form2.is_valid():
form.save()
form2.save()
return redirect(reverse('accounts:view_profile'))
else:
form = EditUserForm(instance=request.user)
form2 = EditProfileForm(instance=request.user.userprofile)
args = {'form': form, 'form2':form2}
return render(request, 'accounts/edit_profile.html', args)
models.py
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
description = models.CharField(max_length=100, default='')
city = models.CharField(max_length=100, default='')
website = models.URLField(default='')
phone = models.IntegerField(default=0)
image = models.ImageField(upload_to='profile_image', blank=True)
def __str__(self):
return self.user.username
edit_profile.html
<div class="container">
{% if form.errors %}
<ol>
{% for field in form %}
<H3 class="title">
<p class="error"> {% if field.errors %}<li>{{ field.errors|striptags }}</li>{% endif %}</p>
</H3>
{% endfor %}
</ol>
{% endif %}
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
{{ form2.as_p }}
<button type="submit">Submit</button>
</form>
<br>
</div>
If you are uploading files, you must instantiate the form with request.POST and request.FILES.
form2 = EditProfileForm(request.POST, request.FILES, instance=request.user.userprofile)
See the docs on file uploads for more info.

django hidden field error

i'm building a message system for a virtual community, but i can't take the userprofile id
i have in views.py
def save_message(request):
if request.method == 'POST':
form = MessageForm(request.POST)
if form.is_valid():
new_obj = form.save(commit=False)
new_obj.sender = request.user
u = UserProfile.objects.get(request.POST['userprofile_id'])
new_obj.owner = u
new_obj.save()
return HttpResponseRedirect('.')
else:
form = MessageForm()
return render_to_response('messages/messages.html', {
'form': form,
},
context_instance=RequestContext(request))
and the template:
{% block primary %}
<form action="." method="post">
{{ form.as_p }}
<p><input type="hidden" value="{{ userprofile.id }}" name = "owner" /></p>
<p><input type="submit" value="Send Message!" /></p>
</form>
{% endblock %}
forms.py:
class MessageForm(ModelForm):
class Meta:
model = Messages
fields = ['message']
models.py:
class Messages(models.Model):
message = models.CharField(max_length = 300)
read = models.BooleanField(default=False)
owner = models.ForeignKey(UserProfile)
sender = models.ForeignKey(User)
I don't figure out why i get this error,since i'm just trying to get the profileId of a user, using a hiddeen field.
the error is:
Key 'UserProfile_id' not found in <QueryDict: {u'owner': [u''], u'message': [u'fdghjkl']}>
and i'm getting it after i fill out the message text field.
Thanks!
it should be
u = UserProfile.objects.get(request.POST['owner'])
because the input's name is 'owner!!
Can you set raise(raise Exception,request.POST) before string: u = UserProfile.objects.get(request.POST['userprofile_id'])
And show me output.