Django forms data retrieving and updating problem - python

I've four fields in my models.py file.
class Item(models.Model):
product_name = models.CharField(max_length=100)
quantity = models.IntegerField()
size_choice = (
('S', 'Short'),
('M','Medium'),
('L','Long')
)
size = models.CharField(max_length=30, choices=size_choice,blank=True, null=True)
date = models.DateField(blank=True, null=True)
And this is my forms.py file:
class ItemForm(ModelForm):
class Meta:
model = Item
widgets = {'date':DateInput()}
fields = ['product_name','quantity']
As I'm taking two fields only so it will display only two fields in my additem.html file:
<form action="" method="post">
{% csrf_token %}
{{ form }}
<button type="submit">Add</button>
</form>
In my itemlist.html file I can retrieve 'product_name' and 'quantity' from database as it is being saved from additem.html file. But in this itemlist.html file I've created two more inputs for 'size' and 'date'. So from here i want to update data into database(all four coulmns). Updating two fileds is fine but how will i update 'size' and 'field' from itemlist.html file.
{% for neww in all %}
<tr>
<td>{{ neww.product_name }}</td>
<td>{{ neww.quantity }}</td>
<td><input type="text" value="{{ neww.size }}"</td> /* This */
<td><input type="text" value="{{ neww.date }}"</td> /* and this i want to update from here */
<td>Edit</tr>{% endfor %}
My update_item.html file:
<form action="" method="POST">
{% csrf_token %}
{{ form }}
<input type="submit" value="Update">
</form>
My itemlist views:
def itemlist(request):
all_items = Item.objects.all()
return render(request, 'item/itemlist.html',{'all': all_items})
And my update_item views:
def update_item(request, id):
if request.method == 'POST':
pi = Item.objects.get(pk=id)
fm = ItemForm(request.POST, instance=pi)
if fm.is_valid():
fm.save()
return redirect('/itemlist')
else:
pi = Item.objects.get(pk=id)
fm = ItemForm(instance=pi)
return render(request, 'item/update_item.html', {'form':fm})
I searched on Internet. I didn't find any similar question. I've stuck here since a week. Any help would be really appreciated.

First thing to note is that if you are requesting a form data from html template, then it should be under the form tag. and action "PATH TO THE URL containing the views." as following:
{% for neww in all %}
<tr>
<td>{{ neww.product_name }}</td>
<td>{{ neww.quantity }}</td>
<form action="PATH TO THE URL" method="POST">
{% csrf_token %}
<td><input type="text" value="{{ neww.size }}" name="val1"></td> /* This */
<td><input type="text" value="{{ neww.date }}" name="val2"></td> /* and this i want to update from here */
<input type="submit" value="Update">
</form>
<td>Edit
and in your views.py file you can request the data to update your tables in the database as following:
size = request.POST['val1']
date = request.POST['val2']
now you can use these values to be updated in the tables.
There are more options to achieve this functionality in case you want the data prefilled in the form partly using the instances and id. Just check on YouTube or google how to prefill the django form partly. You can also hide the form fields in the html using the css styles.

Try this :
def update_item(request, id):
if request.method == 'POST':
pi = Item.objects.get(pk=id)
fm = ItemForm(request.POST, instance=pi)
fm.size = request.POST["size"]
fm.date = request.POST["date"]
if fm.is_valid():
fm.save()
return redirect('/itemlist')
else:
pi = Item.objects.get(pk=id)
fm = ItemForm(instance=pi)
return render(request, 'item/update_item.html', {'form':fm})

Related

How do I get the current item in the model from the request?

When a submit button is clicked, I want to be able to know what item the user was on. The button would be on an item's page that the user gets taken to when they click on an item. This button is is part of a django form (PlaceBid) that allows the user to bid for the item. So I want to be able to update what the item's highest bid is if the bid is higher than the current highest. This means that I need to know what item the user was viewing.
I also want to save the bid in a model called Bid and in that model I also need to know what listing the bid is for.
So how do I get the correct item from the model?
The models:
Listing() is the model for the item
Bid() is the model for the bid
views.py:
def bid(request):
if request.method == 'POST':
form = PlaceBid(request.POST)
if form.is_valid():
current = Listing.objects.get(pk=request.id) # my attempt to get the current item
highest = current.highest_bid
if form.cleaned_data['bid'] < highest:
obj = Bid()
obj.price = form.cleaned_data['bid']
obj.item = current
obj.user = User.objects.get(pk=request.user.id)
obj.save()
current.highest_bid = form.cleaned_data['bid']
current.save()
return HttpResponseRedirect(request.path_info)
forms.py:
class PlaceBid(forms.Form):
bid = forms.FloatField(required=False, widget=forms.NumberInput(attrs={
'class': 'bid',
}))
html:
<form action=" {% url 'bid' %} " method="post">
{% csrf_token %}
{{ bidForm }}
<input type="submit" value="Place Bid" class="place-bid">
</form>
With the limited code shown, I can only assume at this point that you have a bidding form for each item in a forloop. Example:
{% for item in items %}
...
<form action=" {% url 'bid' %} " method="post">
{% csrf_token %}
{{ bidForm }}
<input type="submit" value="Place Bid" class="place-bid">
</form>
...
{% endfor %}
But here are two methods that can be done...
Use a hidden input field to hold the item object id then retrieve that field name on the server to get the item's id value.
# html
<form action=" {% url 'bid' %} " method="post">
{% csrf_token %}
{{ bidForm }}
<input type="hidden" value="{{ item.id }}" name="item_id">
<input type="submit" value="Place Bid" class="place-bid">
</form>
# views.py
def bid(request):
if request.method == 'POST':
form = PlaceBid(request.POST)
if form.is_valid():
item_id = request.POST.get('item_id', None)
current = Listing.objects.get(id=item_id)
# rest of code follows...
Pass the item's id via the url. (My recommendation)
# html
<form action=" {% url 'bid' item.id %} " method="post">
{% csrf_token %}
{{ bidForm }}
<input type="submit" value="Place Bid" class="place-bid">
</form>
# urls.py
# update the necessary url to accept an id
path('bid/<int:id>/', views.bid, name='bid')
# views.py
def bid(request, id):
if request.method == 'POST':
form = PlaceBid(request.POST)
if form.is_valid():
current = Listing.objects.get(id=id) # id passed to this method used here...
# rest of code follows...
Also, instead of using Listing.objects.get(id=id), I'd suggest using get_object_or_404(Listing, id=id) as this will handle any potential error that Listing.objects.get(id=id) will throw.
You won't get it from the request. Hide it in the form.
class PlaceBid(forms.Form):
bid = forms.FloatField(required=False, widget=forms.NumberInput(attrs={
'class': 'bid',
}))
listing_id = forms.IntegerField(widget=forms.HiddenInput())
Then in your method that displays the form (I'm using function-based views)
def view_listing(request, listing_id)
listing = Listing.objects.get(id=listing_id)
myForm = PlaceBid(initial={"listing_id" : listing_id})
return render("whatever.html", {"listing" : listing, "form" : form })
I suppose another option would be to stash the listing_id in the session, but I try to avoid that.

Django form post not saving

I am making a Django application (for the first time in my life). As part of the application, a timetable needs to be implemented. Loading data (from the databse) into the timetable works fine:
Timetable view
The thing is that the data should be editable. So users need to be able to change the time or the yes/no parameter. I've created a POST handler in views.py, but when I press save, the page quickly reloads and the old values are back. What am I doing wrong?
models.py
class timeTable(models.Model):
key = models.CharField(max_length=200, unique=True, null=True)
value = models.CharField(max_length=200, null=True)
def __str__(self):
return self.key
views.py
#login_required(login_url='login')
def timetable(request):
timeTableFormset = modelformset_factory(timeTable, fields='__all__' ,extra=0)
timetableform = timeTableFormset(queryset=timeTable.objects.all())
if request.method == 'POST':
form = timeTableFormset(request.POST)
if form.is_valid():
form.save()
return render(request, 'VulnManager/timetable.html', {'timetableform': timetableform})
timetable.html:
<form method="POST">
{% csrf_token %}
<table id="tablePreview" class="table table-borderless table-hover">
<!--Table head-->
<thead>
<tr>
<th></th>
<th>Monday</th>
<th>Tuesday</th>
<th>Wednesday</th>
<th>Thursday</th>
<th>Friday</th>
<th>Saturday</th>
<th>Sunday</th>
</tr>
</thead>
<!--Table head-->
<!--Table body-->
<tbody>
<tr>
<th scope="row">Scan?</th>
{{ timetableform.management_form }}
{% for timeTableValue in timetableform.forms %}
{% if forloop.counter <= 7 %}
<td><select class="form-control" id="{{ timeTableValue.key.value }}" disabled="true">
<option>{{ timeTableValue.value.value }}</option>
<option>
{% if timeTableValue.value.value == "true" %}
false
{% elif timeTableValue.value.value == "false" %}
true
{% endif %}
</option>
</select></td>
{% if forloop.counter == 7 %}
</tr>
<tr>
<th scope="row">Time begin</th>
{% endif %}
{% elif forloop.counter >= 8 and forloop.counter <= 14 %}
<td><input type="text" id="{{ timeTableValue.key.value }}" onchange="validateHhMm(this);" value="{{ timeTableValue.value.value }}" readonly /></td>
{% if forloop.counter == 14 %}
</tr>
<tr>
<th scope="row">Time end</th>
{% endif %}
{% elif forloop.counter >= 15 and forloop.counter <= 21 %}
<td><input type="text" id="{{ timeTableValue.key.value }}" onchange="validateHhMm(this);" value="{{ timeTableValue.value.value }}" readonly /></td>
{% endif %}
{% endfor %}
</tr>
</tbody>
<!--Table body-->
</table>
<input type="button" class="btn-primary" id="edit" value="Edit" />
<input type="submit" class="btn-primary" id="save" value="Save" />
</form>
Your "form" variable has the formset in it, but you have to loop through the forms in the formset individually:
if form.is_valid():
for form_line in form:
form_line.save()
Your view is always rendering the "get" form for lack of a better term.
I think if you keep your variable names the same, it'll make things a bit simpler and consistent. So to explain this;
views.py
#login_required(login_url='login')
def timetable(request):
timeTableFormset = modelformset_factory(timeTable, fields='__all__' ,extra=0)
timetableform = timeTableFormset(queryset=timeTable.objects.all())
if request.method == 'POST':
form = timeTableFormset(request.POST) # This form just gets left in this block
if form.is_valid():
form.save()
return render(
request,
'VulnManager/timetable.html',
{'timetableform': timetableform} # The context includes the fresh new form, with no post data
)
What you should do, is just call it formset, because it makes life easier;
from django.contrib import messages
#login_required(login_url='login')
def timetable(request):
timeTableFormset = modelformset_factory(timeTable, fields='__all__' ,extra=0)
formset = timeTableFormset(queryset=timeTable.objects.all())
if request.method == 'POST':
formset = timeTableFormset(data=request.POST, queryset=timeTable.objects.all())
if formset.is_valid():
formset.save()
# Do something here to reassure the user it saved. Redirect or add a message
messages.success(request, 'Form saved.')
return render(
request,
'VulnManager/timetable.html',
{'timetableform': formset}
)
There's an article here which may provide some worthy reading for you; https://medium.com/#MicroPyramid/understanding-djangos-model-fromsets-in-detail-and-their-advanced-usage-131dfe66853d

django modelformset_factory raises form not valid: id Select a valid choice. That choice is not one of the available choices

i am trying to create a student attendance sheet in django using django modelformset_factory...but when i save the formset it thows me the id is not valid here is my implementation
i have two models one StudentAttendance and StudentClass:
1: the StudentAttendance model is responsible for stroring students
attendance data here is the example
class StudentAttendance(models.Model):
classroom_id = models.ForeignKey(ClassRoom, on_delete=models.CASCADE, related_name='student_attendance')
attendance_date = models.DateField()
student_id = models.ForeignKey(Student, on_delete=models.CASCADE, related_name='student_attendance')
status = models.CharField(max_length=20, choices=ATTENDANCE_CHOICES)
comment = models.CharField(max_length=150, blank=True)
#signed_by = models.ForeignKey(Teacher, on_delete=models.CASCADE)
date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return str(self.student_id)
2: the StudentClass model is a submodel that maps a student to his respective class
class StudentClass(models.Model):
"""
This is a bridge table to link a student to a class
when you add a student to a class we update the selected class capacity
"""
main_class = models.ForeignKey(ClassRoom, on_delete=models.CASCADE, related_name='class_student')
academic_year = models.ForeignKey(AcademicYear, on_delete=models.CASCADE)
student_id = models.ForeignKey(Student, on_delete=models.CASCADE, related_name='student_class')
#property
def is_current_class(self):
if self.academic_year.is_current_session:
return True
return False
def __str__(self):
return str(self.student_id)
So my forms.py implementation is:
class StudentsAttendanceForm(forms.ModelForm):
class Meta:
model = StudentAttendance
fields = ('status', 'comment')
#exclude = [
#'siqned_by',
#]
On my views.py:
def student_attendance_manager(request):
"""
this function is responsible for querying the attendance parameters and present the student multiple attendance form
"""
if request.method == "POST":
# get the class name , the attendance date and present the attendance form
class_name = get_object_or_404(ClassRoom, pk=request.POST['class_name']) # class name
attendance_date = request.POST['date_field'] # date
# get the students in the class which is current active
student = StudentClass.objects.filter(main_class=request.POST['class_name'])
# modelform creation
AttendanceFormSet = modelformset_factory(StudentAttendance, form=StudentsAttendanceForm, extra=0)
# initiate the form and pass in the required parameters ie: classroom_id, attendance_date
list_formset = AttendanceFormSet(queryset=student)
# initialise the class_name and attendance date
#for form_inst in list_formset:
#form_inst.fields['classroom_id'].initial = class_name
#form_inst.fields['attendance_date'].initial = attendance_date
template = 'attendance/students_attendance_form.html'
context = {
'class_name':class_name,
'attendance_form': list_formset,
}
return JsonResponse({'html_form': render_to_string(template, context, request=request)})
template = 'attendance/students_attendance_manager.html'
class_date_selector_form = ClassroomDateQueryForm(request.GET or None)
context = {
'choice_form':class_date_selector_form
}
return render(request, template, context)
when the User Posts the form to be submited this is how i handle the form:
def student_attendance_register(request):
if request.method == "POST":
students = StudentClass.objects.filter(main_class=request.GET['class_id'])
StudentsAttendanceFormSet = modelformset_factory(StudentAttendance, form=StudentsAttendanceForm, extra=0)
list_formset = StudentsAttendanceFormSet(request.POST, queryset=students)
if list_formset.is_valid():
list_formset.save()
return HttpResponse('valid')
else:
return HttpResponse(list_formset.errors)
on my template i display the form in a table and this is my implementation:
form.html:
<form class="js-mark-attendance" method="post" action="{% url 'attendance:student_attendance_register' %}?class_id={{ class_name.id }}">
{% csrf_token %}
<table class="table-striped table table-bordered" id="Student_attendance_table">
<thead>
<tr>
<th>#</th>
<th>Admission Number</th>
<th>Name</th>
<th>Status</th>
<th>Comment</th>
</tr>
</thead>
<tbody>
{{ attendance_form.management_form }}
{% for form_inst in attendance_form %}
{% for hidden in form_inst.hidden_fields %}
{{ hidden }}
{% endfor %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ form_inst.instance.student_id.admission_number }}</td>
<td>{{ form_inst.instance.student_id }}</td>
<td>{{ form_inst.status }}</td>
<td> {{ form_inst.comment }}</td>
{{ form_inst.classroom_id.as_hidden }}
{{ form_inst.attendance_date.as_hidden }}
{{ form_inst.student_id.as_hidden }}
</tr>
{% endfor %}
</tbody>
</table>
<div class="row">
<div class="col-md-12 d-flex justify-content-center">
<input type="submit" value="Mark Attendance" class="btn btn-success">
</div>
</div>
</form>
and this is the error that django throws after the user has clicked submit button:
id
Select a valid choice. That choice is not one of the available choices.
so my question is ... how can i handle this post request form and or if their is an alternative way of doing my task:
any leads will be much upreciated
oops....I found my problem was the wrong usage of modelsfomset_factory...

Django formset with no initial data

I am a Django rookie and I am developing a small app to register time (duration) and quantity of activities per user per day. Sort of like a work log. My problem is this: My “add entry” view displays and updates old records rather than adding new records to the db. I need a view to add new records, not replace old ones.
From searching around and from the #django IRC channel, I understand that the formset-way by default draws on old data rather than setting the client up for adding new data. I have, however, not found anything about how to avoid this behaviour and have the client provide a blank form for "appending new data" rather than "editing existing data".
My deadline is drawing really close and all help is greatly appreciated.
Here are the relevant code snippets:
From models.py
class Activity(models.Model):
name = models.CharField(max_length=200)
description = models.TextField()
class Workday(models.Model):
entrydate = models.DateField()
worker = models.ForeignKey(User, on_delete=models.CASCADE)
class Entry(models.Model):
duration = models.DurationField()
quantity = models.PositiveIntegerField()
activity = models.ForeignKey(Activity, on_delete=models.CASCADE)
workday = models.ForeignKey(Workday, on_delete=models.CASCADE)
From forms.py
class EntryForm(ModelForm):
activity = ModelChoiceField(queryset=Activity.objects.order_by('name'), initial=0)
class Meta:
model = Entry
fields = ['activity',
'duration',
'quantity',
]
class WorkdayForm(ModelForm):
class Meta:
model = Workday
fields = ['entrydate']
widgets = {'entrydate': SelectDateWidget}
From views.py
def addentry(request):
EntryFormSet = modelformset_factory(Entry, form=EntryForm, extra=0, fields=('activity', 'duration', 'quantity'))
if request.method == 'POST':
workdayform = WorkdayForm(request.POST, prefix='workday')
formset = EntryFormSet(request.POST)
if formset.is_valid() and workdayform.is_valid():
# Generate a workday object
workday = workdayform.save(commit=False)
workday.entrydate = workdayform.cleaned_data['entrydate']
workday.worker = request.user
workday.save()
# Generate entry objects for each form in the entry formset
for form in formset:
e = form.save(commit=False)
e.workday = workday
e.save()
form.save_m2m()
messages.add_message(request, messages.SUCCESS,
"Registrert aktivitet " +
e.workday.entrydate.strftime('%A %d. %B %Y') +
": " + e.activity.name + " (" + str(e.quantity) +") - " +
str(e.duration)
)
return redirect('index')
else:
workdayform = WorkdayForm(request.POST, prefix='workday')
formset = EntryFormSet(request.POST)
for dict in formset.errors:
messages.add_message(request, messages.ERROR, dict)
context = {
'workdayform': workdayform,
'formset': formset,
}
return render(request, 'register/addentry.html', context)
else:
workdayform = WorkdayForm(prefix='workday')
formset = EntryFormSet()
context = {
'workdayform': workdayform,
'formset': formset,
}
return render(request, 'register/addentry.html', context)
From addentry.html
{% block content %}
{% if user.is_authenticated %}
<h1>Ny dag</h1>
{% if formset and workdayform %}
<form id="newdayform" method="POST" class="post-form">
{% csrf_token %}
{{ workdayform.as_p }}
{{ formset.management_form }}
<table>
<thead>
<tr>
<td>Aktivitet</td>
<td>Varighet<br/>(HH:MM:SS)</td>
<td>Antall</td>
</tr>
</thead>
<tbody>
{% for form in formset %}
<tr>
<td>{{ form.activity }}</td>
<td>{{ form.duration }}</td>
<td>{{ form.quantity }}</td>
<td class="hidden">{{ form.id }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<button type="submit">Registrer tid</button>
</form>
<script src="{% static 'register/jquery.formset.js' %}"></script>
<script type="text/javascript">
$(function() {
$('#newdayform tbody tr').formset();
})
</script>
{% if entryform.errors or workdayform.errors %}
<h3>Feil i utfyllingen</h3>
{{ entryform.errors }}
{{ workdayform.errors }}
{% endif %}
{% else %}
<p>No form!</p>
{% endif %}
{% endif %}
{% endblock %}
Thanks to #e4c5 and this previous Q&A, the issue is solved by passing a queryset of no objects to the formset, like this:
def addentry(request):
(...)
qs = Entry.objects.none()
formset = EntryFormSet(queryset=qs)
(...)

Django Form, with Class Meta model based in class model, and more fields

Please, I have a similar case I'll introduce them and wish you could help me understand and handle this case properly.
I have the simple model case:
# -*- coding: utf-8 -*-
from django.db import models
class City(models.Model):
name = models.CharField("City", max_length=100, blank=False, null=False)
state = models.CharField("State", max_length=2, blank=False, null=False)
class Neighborhood(models.Model):
name = models.CharField("Name", max_length=100, blank=False, null=False)
city = models.ForeignKey(City, blank=False, null=False)
The model forms:
from django import forms
from app.models import *
class CityForm(forms.ModelForm):
class Meta:
model = City
class NeighborhoodForm(forms.ModelForm):
class Meta:
model = Neighborhood
state = forms.CharField("State", max_length=2, required=True)
Theirs views:
City View:
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
from django.template import RequestContext
from app.forms import CityForm
from app.models import City
STATES = ["AC", "AL", "AP", "AM", "BA", "CE", "DF", "ES", "GO", "MA", "MT", "MS", "MG", "PR",
"PB", "PA", "PE", "PI", "RJ", "RN", "RS", "RO", "RR", "SC", "SE", "SP", "TO"]
def index(request):
if "submit" in request.POST:
form = CityForm(request.POST, request.FILES)
if form.is_valid():
form.save(commit=True)
elif "cancel" in request.POST:
return HttpResponseRedirect("/")
else:
form = CityForm()
cities = City.objects.all()
data = {
"form": form,
"states": STATES,
"cities": cities
}
return render_to_response("city/index.html", data, context_instance=RequestContext(request))
And the Neighborhood view:
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
from django.template import RequestContext
from app.forms import NeighborhoodForm
from app.models import Neighborhood, City
from app.city.views import STATES
def index(request):
if "submit" in request.POST:
form = NeighborhoodForm(request.POST, request.FILES)
if form.is_valid():
form.save(commit=True)
elif "cancel" in request.POST:
return HttpResponseRedirect("/")
else:
form = NeighborhoodForm()
neighborhoods = Neighborhood.objects.all()
cities = City.objects.all()
data = {
"form": form,
"states": STATES,
"cities": cities,
"neighborhoods": neighborhoods
}
return render_to_response("neighborhood/inserir.html", data, context_instance=RequestContext(request))
And finally, the template of Neighborhood:
{% extends "base.html" %}
{% block content %}
<form action="" method="post" id="neighborhoodForm" name="neighborhoodForm">
{% csrf_token %}
<div>
<label>State:</label>
<select id="state" name="state" autofocus="autofocus">
<option value=""></option>
{% for item in states %}
<option value="{{ item }}"
{% if item == form.state.value %}
selected="selected"
{% endif %}>{{ item }}</option>
{% endfor %}
</select>
</div>
<div>
<label>City:</label>
<select id="city" name="city">
<option value=""></option>
{% for item in cities %}
<option value="{{ item.id }}"
{% if item.id == form.city.value|add:0 %}
selected="selected"
{% endif %}>{{ item.name }}</option>
{% endfor %}
</select>
</div>
<div>
<label>Neighborhood Name:</label>
<input type="text" id="name" name="name" value="{{ form.name.value|default_if_none:"" }}"/>
</div>
<div>
<button type="submit" id="submit" name="submit" value="submit">Submit</button>
<button type="submit" id="cancel" name="cancel" value="cancel">Cancel</button>
</div>
</form>
<br/>
<table border="1">
<tr>
<th>Neighborhood Name</th>
<th>City</th>
<th>State</th>
</tr>
{% for item in neighborhoods %}
<tr>
<td>{{ item.name }}</td>
<td>{{ item.city.name }}</td>
<td>{{ item.city.state }}</td>
</tr>
{% endfor %}
</table>
{% endblock %}
My difficulty on in view of neighborhoods. I have the City and State fields, which are in the neighborhood template for filters.
To add a record I have no problem, but a simple post does not return the value in the "state" of NeighborhoodForm to the template again. That's because the value that was sent in the post does not find the "state" field of the form.
When you open a record for editing happen the same thing, ie, the "state" field will not be filled.
So this is my problem. Can you help me? How should I do or what I'm doing wrong?
Thanks all for the assistance given.
What you really want here is to assign and save custom values to fields. To do this, you have to provide initial values and save method of form.
If you have a object to load data from, then you must pass it the form, for example:
neighbor = Neighborhood.objects.get(pk=1)
form = NeighborhoodForm(instance=neighbor)
The above code initialize the form with the object and fields related to it. But it still misses out on state field. To initialize it, you must pass initial value for it:
neighbor = Neighborhood.objects.get(pk=1)
state = neighbor.city.state
form = NeighborhoodForm(instance=neighbor, initial={'state': state})
OR you could override form's __init__ method to extract value:
def __init__(self, *args, **kwargs):
super(NeighborhoodForm, self).__init__(*args, **kwargs)
if 'instance' in kwargs:
state = self.instance.city.state
self.fields['state'].initial = state
And you can save data similarly by overriding save method:
def save(self, *args, **kwargs):
new_neighbor = super(NeighborhoodForm, self).save(*args, **kwargs)
city = City.objects.create(state=self.cleaned_data['state'])
new_neighbor.city = city
new_neighbor.save()
return new_neighbor

Categories

Resources