Reputation: 251
I've been working on a small django website as I learn django. According to the documentation when you create a form class with a meta class that points at a model with foreign key fields, it'll render those fields as select inputs.
In my application I have 3 models, client
test
, and record
where record
carries two foreign keys, each of whom point to client
and test
respectively
class Client(models.Model):
first = models.CharField(max_length=264)
last = models.CharField(max_length=264)
DOB = models.DateField()
def __str__(self):
return self.first + " " + self.last
class Test(models.Model):
test = models.CharField(max_length=264)
fee = models.DecimalField(max_digits=12, decimal_places=2)
def __str__(self):
return self.test
class Record(models.Model):
client = models.ForeignKey(Client, on_delete=models.CASCADE)
test = models.ForeignKey(Test, on_delete=models.CASCADE)
date = models.DateField()
def __str__(self):
return str(self.date) + " " + str(self.test) + " for " + str(self.client)
class NewLabRecord(forms.ModelForm):
client = forms.ChoiceField(
label='Client ID',
widget=forms.Select(
attrs={'class': 'form-control'}))
test = forms.ChoiceField(
label='Test ID',
widget=forms.Select(
attrs={'class': 'form-control'}))
date = forms.DateField(
label='Test Date',
widget=forms.DateInput(
attrs={'class': 'form-control'}))
class Meta:
model = models.Record
fields = '__all__'
I render NewLabRecord
at the top of my index view for records
. The idea is to create a record and redirect back to the page (therefore seeing it in the list of records). Presently, I'm emulating class-based-views and not actually implementing it because I have not learned it yet. Nevertheless, this pattern does work for my client
and test
(the code is nearly identical).
class LabRecord:
@staticmethod
def index(request):
new_record_form = forms.NewLabRecord
records = models.Record.objects.order_by('date')
print(records)
context = {
'records': records,
'new_record_form': new_record_form
}
return render(request, "layouts/lab/record/index.html", context=context)
<div class="collapse" id="createLabRecord">
{% include 'components/lab/record/create.html' %}
</div>
<!DOCTYPE html>
{% block content %}
<div class="card col-sm" style="">
<form class="form" method="post" action="{% url 'lab:create lab record' %}">
{{ new_record_form }}
{% csrf_token %}
<input type="submit" value="submit">
</form>
</div>
{% endblock %}
Now, when I go to the url for this view, /lab/records/
, the view renders two select fields and an input for the date; however, the select fields are empty!
Note: I have 9 clients
and 4 tests
in the database!
Upvotes: 1
Views: 1686
Reputation: 1450
In your view, you need to query your Client and Test models and put those lists into your context to make them available to your form/template.
records = models.Record.objects.order_by('date')
clients = models.Client.objects.all()
tests = models.Test.objects.all()
context = {
'records': records,
'new_record_form': new_record_form,
'clients' : clients,
'tests' : tests,
}
I have not learned the forms portion of django yet to tell you if there is something else to connect the lists to the input select fields.
Edit: It looks like the following in your form should accomplish the desired:
class NewLabRecord(forms.ModelForm):
client = forms.ModelChoiceField(models.Client.objects.all())
test = forms.ModelChoiceField(models.Test.objects.all())
date = forms.DateField(
label='Test Date',
widget=forms.DateInput(
attrs={'class': 'form-control'}))
class Meta:
model = models.Record
fields = '__all__'
And I don't think that the changes to your view are then necessary.
Upvotes: 2