Populate dropdown in template from model choices using Django Rest Framework - django

I have the model, serializer, viewset and html as follows:
GENDER = (
('MALE', 'Male'),
('FEMALE', 'Female'),
('OTHERS', 'Others'),
)
class Client(BaseModel):
first_name = models.CharField(max_length=256)
last_name = models.CharField(max_length=256, default="", blank=True, null=True)
designation = models.CharField(max_length=256, default="", blank=True, null=True)
gender = models.CharField(max_length=20, choices=GENDER, null=True, blank=True)
class ClientSerializer(QueryFieldsMixin, DynamicFieldsModelSerializer):
name = serializers.SerializerMethodField()
def get_name(self, obj):
return getattr(obj, "first_name", "") + " " + getattr(obj, "last_name", "")
class Meta:
model = Client
fields = '__all__'
#method_decorator(login_required, name='dispatch')
class ClientViewSet(viewsets.ModelViewSet):
model = Client
queryset = model.objects.all()
serializer_class = ClientSerializer
#action(detail=True, methods=['post','get'], renderer_classes=[renderers.TemplateHTMLRenderer])
def update_client(self, request, *args, **kwargs):
object = self.get_object()
context = {"operation": "Update",
"object_id": object.id,
"events": Event.GetEventsForObject(object)}
template_name = 'contact-client.html'
response = Response(context, template_name=template_name)
<form id="client-form" method="" action="" enctype="multipart/form-data" operation="{{operation}}">
{% csrf_token %}
<div class="row">
<div class="columns medium-5 medium-text-left">
<div class="select2-full select-2-full--sm input-rounded">
<label for = "gender" style="text-align: left;" >Gender</label>
<select id="gender" class="js-select2 input-height-sm element-contact" name="gender" validated="false"></select>
<option></option>
</div>
<div id="gender_error" style="display:none">
<p class="help-text"> <span class="form-action-icon error-icon"></span>Please select gender.</p>
</div>
</div>
<div class="columns medium-5 medium-text-left">
</div>
</div>
</form>
When I instantiate the ClientSerializer in shell like this ClientSerializer() then that gender field is shown along with its choices. But I am not able to show it in the template. All the other fields are being passed correctly.
How can I populate the dropdown with the values of choices in template? What should I pass in the option tag to display the choices and send the data to the view?

Use a ChoiceField instead of CharField
Replace this line
gender = models.CharField(max_length=20, choices=GENDER, null=True, blank=True)
with this one
gender = models.ChoiceField(max_length=20, choices=GENDER, null=True, blank=True)
To show all the choices in your template you can do something like this
from my_app.models import gender
context = {"choices" : gender}
response = Response(context,template_name)
And in template
{% for choice in choices %}
<option value="{{ choice }}">{{ choice }}</option>
{% endfor %}

If you are using the django-template then you can create a model form and pass that form as render context and then render that inside a form.
More on model form: https://docs.djangoproject.com/en/3.1/topics/forms/modelforms/

Related

How to save Django Form and Formset at the same time

I have a page in which I use a form and formset at the same time. The form is for the thesis information and the formset is for the author.
This is the code in my models.py
class thesisDB(Model):
thesis_id = models.AutoField(primary_key=True, blank=True, null=False)
title = models.CharField(max_length=200, blank=True, null=True, unique=True)
published_date = models.DateField(blank=True, null=True)
pdf = models.FileField(upload_to='pdf/', blank=True, null=True ,validators=[FileExtensionValidator(['pdf'])],)
course = models.ForeignKey(ColCourse, default=None, on_delete=models.CASCADE, verbose_name='Course')
tags = TaggableManager()
date_created = models.DateField(auto_now_add=True, blank=True, null=True )
uploaded_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, default=None)
published_status = models.CharField(max_length=10, choices= THESIS_DECISION, default='Pending')
abstract = models.TextField(blank=True, null=True)
hit_count_generic = GenericRelation(HitCount, object_id_field='object_pk', related_query_name='hit_count_generic_relation')
reason = models.TextField(blank=True, null=True)
slug = models.SlugField(max_length = 250, null = True, blank = True)
def save(self, *args, **kwargs):
self.title = self.title.title()
#self.author = self.author.title()
self.slug = slugify(self.title + "-" + self.author + "-" + str(self.published_date))
super().save(*args, **kwargs)
class Meta:
db_table = 'thesis_storage'
initial_validator = RegexValidator('[A-Z]+.', 'Initial must contain period')
class Authors(Model):
thesis = models.ForeignKey(thesisDB, on_delete=models.CASCADE)
first_name = models.CharField(max_length=200, blank=True, null=True)
last_name = models.CharField(max_length=200, blank=True, null=True)
middle_initial = models.CharField(max_length=2, blank=True, null=True, validators=[initial_validator])
This is the code in my forms.py:
class AuthorForm(forms.ModelForm):
class Meta:
model = Authors
exclude = ()
widgets = {
'first_name': forms.TextInput(attrs=
{'placeholder': 'First Name', 'class':'form-control', 'required': 'required'}),
'last_name': forms.TextInput(attrs=
{'placeholder': 'Last Name', 'class':'form-control', 'required': 'required'}),
'middle_initial': forms.TextInput(attrs=
{'placeholder': 'M.I.', 'class':'form-control', 'required': 'required'}),
}
AuthorFormSet = inlineformset_factory(thesisDB, Authors, form=AuthorForm,
fields=['first_name', 'last_name', 'middle_initial'], extra=3, can_delete=False)
class thesisForm(forms.ModelForm):
class Meta:
model = thesisDB
fields = ('title', 'published_date', 'course','tags', 'abstract', 'pdf',)
readonly_fields = ['date_created']
course = forms.ModelChoiceField(queryset=ColCourse.objects.all().order_by('-course_name'))
# abstract = forms.CharField(widget=CKEditorWidget())
# problem = forms.CharField(widget=CKEditorWidget())
widgets = {
'title': forms.TextInput(attrs=
{'placeholder': 'Title', 'class':'form-control', 'required': 'required'}),
'published_date': forms.DateInput(attrs=
{'class':'form-control', 'required': 'required', 'type':'date'}),
'abstract': forms.Textarea(attrs=
{'placeholder': 'Abstract', 'class':'form-control',}),
'course': forms.Select(attrs=
{'placeholder': 'Short Description', 'class':'regDropDown', 'required': 'required'}),
}
def __init__(self, *args, **kwargs):
super(thesisForm, self).__init__(*args, **kwargs)
# Making location required
self.fields['pdf'].required = True
self.fields['abstract'].required = True
self.fields['tags'].required = True
And this is my views.py for submitting the form.
#login_required
#for_students
def submission(request):
formset = AuthorFormSet()
if request.method == "POST":
form = thesisForm(request.POST, request.FILES)
if form.is_valid() and formset.is_valid():
form.instance.uploaded_by = request.user # set the user
post = form.save() # save the form
formset.instance.thesis = form.instance.thesis_id
post = formset.save()
message = "Your project entitled %s has been submitted successfully! We will notify you through email if it is once evaluated" % form.instance.title
messages.success(request, message)
return redirect('/profile/personal_repository/')
else:
form = thesisForm()
formset = AuthorFormSet()
return render(request,'StudentSubmitProject.html',{'form':form, 'formset':formset})
And my template file:
<div class="container-fluid profilecontainer">
<div class="row">
<div class="col-lg-2"></div>
<div class="col-lg-8 right_section">
<h4 class="textmaroon">Submit A Project</h4>
<p>The requirements for submitting a thesis follows:<p>
<ul>
<li>The softcopy of your thesis which is in PDF format.</li>
<li>The pdf file should contain the approval form attesting the thesis has been approved by your department.</li>
<li>The descriptions of thesis such as its Title, Author, Publication Date, Course, and Keywords.</li>
<li>The abstract text of your thesis which should match in the pdf file.</li>
</ul>
<p>Below is the form for submitting a thesis project. Your project would be evaluated first by the Admin Account before it can be available to access in the system, so ensure that the given details are valid to avoid possible rejection.</p>
<hr></hr>
<form method="POST" class="mt-5 form-group profile_form" enctype="multipart/form-data">
{{formset.management_data }}
{% csrf_token %}
<h4 class="textmaroon">Add author</h4>
<p>Enter the author/s of the thesis project</p>
<hr></hr>
<div class="row">
{% for form_s in formset %}
<div class="col-md-5">
{{form_s.first_name | as_crispy_field}}
</div>
<div class="col-md-5">
{{form_s.last_name | as_crispy_field}}
</div>
<div class="col-md-2">
{{form_s.middle_initial | as_crispy_field}}
</div>
{% endfor %}
</div>
<h4 class="textmaroon mt-5">Describe the thesis</h4>
<p>Define the thesis project</p>
<hr></hr>
<div class="row">
<div class="col-md-12">
{{form | crispy}}
</div>
</div>
<div class="row">
<div class="col-md-12">
<button type="submit" class="btn btn-danger mt-3 float-end">Submit</button>
<button type="reset" class="btn btn-secondary mt-3 me-2 float-end">Reset</button>
</div>
</div>
</form>
</div>
<div class="col-lg-2"></div>
</div>
</div>
My problem is that the entered data in the form save, but not in the formset as well.
because you didn't add request.POST to your formset, so no data was passed in the formset:
if request.method == "POST":
formset = AuthorFormSet(request.POST) #need request.POST
form = thesisForm(request.POST, request.FILES)
if form.is_valid() and formset.is_valid():
if there is also file in the formset, add request.FILES as second arg

Django datalist not accepting any input as valid

I am trying to use a datalist input field to allow users to enter their own ingredients on Create a Recipe form. Ideally users can select a GlobalIngredient like salt, pepper, chicken, etc. already in the database or create their own. However, regardless of whether I enter a new ingredient or select a pre-existing ingredient, I am getting the following error: "Select a valid choice. That choice is not one of the available choices.". Unsure why I am getting this error?
Visual:
models.py
class Recipe(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
websiteURL = models.CharField(max_length=200, blank=True, null=True)
image = models.ImageField(upload_to='image/', blank=True, null=True)
name = models.CharField(max_length=220) # grilled chicken pasta
description = models.TextField(blank=True, null=True)
notes = models.TextField(blank=True, null=True)
serves = models.CharField(max_length=30, blank=True, null=True)
prepTime = models.CharField(max_length=50, blank=True, null=True)
cookTime = models.CharField(max_length=50, blank=True, null=True)
class Ingredient(models.Model):
name = models.CharField(max_length=220)
def __str__(self):
return self.name
class GlobalIngredient(Ingredient):
pass # pre-populated ingredients e.g. salt, sugar, flour, tomato
class UserCreatedIngredient(Ingredient): # ingredients user adds, e.g. Big Tomatoes
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
class RecipeIngredient(models.Model):
recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE)
ingredient = models.ForeignKey(Ingredient, null=True, on_delete=models.SET_NULL)
description = models.TextField(blank=True, null=True)
quantity = models.CharField(max_length=50, blank=True, null=True) # 400
unit = models.CharField(max_length=50, blank=True, null=True) # pounds, lbs, oz ,grams, etc
forms.py
class RecipeIngredientForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(RecipeIngredientForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
#self.helper.form_id = 'id-entryform'
#self.helper.form_class = 'form-inline'
self.helper.layout = Layout(
Div(
Div(Field("ingredient", placeholder="Chickpeas - only write the ingredient here"), css_class='col-6 col-lg-4'),
Div(Field("quantity", placeholder="2 x 400"), css_class='col-6 col-md-4'),
Div(Field("unit", placeholder="grams"), css_class='col-5 col-md-4'),
Div(Field("description", placeholder="No added salt tins - All other information, chopped, diced, whisked!", rows='3'), css_class='col-12'),
css_class="row",
),
)
class Meta:
model = RecipeIngredient
fields = ['ingredient', 'quantity', 'unit', 'description']
labels = {
'ingredient': "Ingredient",
"quantity:": "Ingredient Quantity",
"unit": "Unit",
"description:": "Ingredient Description"}
widgets={'ingredient': forms.TextInput(attrs={
'class': 'dropdown',
'list' : 'master_ingredients',
'placeholder': "Chickpeas - only write the ingredient here"
})}
views.py
#login_required
def recipe_create_view(request):
ingredient_list = Ingredient.objects.all()
form = RecipeForm(request.POST or None)
# Formset = modelformset_factory(Model, form=ModelForm, extra=0)
RecipeIngredientFormset = formset_factory(RecipeIngredientForm)
formset = RecipeIngredientFormset(request.POST or None)
RecipeInstructionsFormset = formset_factory(RecipeInstructionForm, extra=0)
instructionFormset = RecipeInstructionsFormset(request.POST or None, initial=[{'stepName': "Step 1"}], prefix="instruction")
context = {
"form": form,
"formset": formset,
"instructionFormset": instructionFormset,
"ingredient_list": ingredient_list
}
if request.method == "POST":
print(request.POST)
if form.is_valid() and formset.is_valid() and instructionFormset.is_valid():
parent = form.save(commit=False)
parent.user = request.user
parent.save()
# formset.save()
#recipe ingredients
for form in formset:
child = form.save(commit=False)
print(child.ingredient)
globalIngredient = Ingredient.objects.filter(name=child.ingredient.lower()) # not truly global as this will return user ingredients too
if (globalIngredient):
pass
else:
newIngredient = UserCreatedIngredient(user=request.user, name=child.ingredient.lower())
newIngredient.save()
if form.instance.ingredient.strip() == '':
pass
else:
child.recipe = parent
child.save()
# recipe instructions
for instructionForm in instructionFormset:
instructionChild = instructionForm.save(commit=False)
if instructionForm.instance.instructions.strip() == '':
pass
else:
instructionChild.recipe = parent
instructionChild.save()
context['message'] = 'Data saved.'
return redirect(parent.get_absolute_url())
else:
form = RecipeForm(request.POST or None)
formset = RecipeIngredientFormset()
instructionFormset = RecipeInstructionsFormset()
return render(request, "recipes/create.html", context)
create.html
<!--RECIPE INGREDIENTS-->
{% if formset %}
<h3 class="mt-4 mb-3">Ingredients</h3>
{{ formset.management_form|crispy }}
<div id='ingredient-form-list'>
{% for ingredient in formset %}
<div class='ingredient-form'>
{% crispy ingredient %}
</div>
{% endfor %}
<datalist id="master_ingredients">
{% for k in ingredient_list %}
<option value="{{k.name|title}}"></option>
{% endfor %}
</datalist>
</div>
<div id='empty-form' class='hidden'>
<div class="row mt-4">
<div class="col-6">{{ formset.empty_form.ingredient|as_crispy_field }}</div>
<div class="col-6">{{ formset.empty_form.quantity|as_crispy_field }}</div>
<div class="col-6">{{ formset.empty_form.unit|as_crispy_field }}</div>
<div id="ingredientIdForChanging" style="display: none;"><div class="col-12">{{ formset.empty_form.description|as_crispy_field }}</div><button type="button"
class="btn btn-outline-danger my-2" onclick="myFunction('showDescription')"><i class="bi bi-dash-circle"></i> Hide
Description</button></div><button type="button"
class="btn btn-outline-primary col-5 col-md-3 col-lg-3 col-xl-3 m-2" id="ingredientIdForChanging1"
onclick="myFunction('showDescription')"><i class="bi bi-plus-circle"></i> Add a
Description Field</button>
</div>
</div>
<button class="btn btn-success my-2" id='add-more' type='button'>Add more ingredients</button>
{% endif %}

Why a form having foreign keys in giving field error in django on form submission

I am creating a feedback form. This form has three foreign keys.
My views.py is
def studentFeedBack(request):
if request.method == 'POST':
studentid_id = request.POST.get("studentid")
studentid = Student.objects.get(id=studentid_id)
courseid_id = request.POST.get("courseid")
courseid = Course.objects.get(id=courseid_id)
teacherid_id = request.POST.get("teacherid")
teacherid = SchoolTeacher.objects.get(id=teacherid_id)
description = request.POST.get("description")
rating = request.POST.get("rating")
studentFeedBackModel.objects.create(
courseid=courseid,
description=description,
studentid=studentid,
teacherid=teacherid,
rating=rating
)
return render(
request,
'forms/studentFeedBack.html',
{
'studentids':Student.objects.all(),
'courseids':Course.objects.all(),
'teacherids':SchoolTeacher.objects.all(),
}
)
and my model for feedback form is
class StudentFeedBack(models.Model):
feedbackid = models.AutoField(primary_key=True)
courseid = models.ForeignKey('Course', on_delete=models.CASCADE)
description = models.CharField(max_length=500)
submitdate = models.DateTimeField(auto_now_add=True)
teacherid = models.ForeignKey('SchoolTeacher', on_delete=models.CASCADE)
studentid = models.ForeignKey('Student', on_delete=models.CASCADE)
option = [('Good','Good'),('Average','Average'),('Bad','Bad')]
rating = models.CharField(max_length=100, choices=option, default='none')
The above model has foreign key from models
class Course(models.Model):
courseid = models.IntegerField(primary_key=True)
coursedescription = models.CharField(max_length=500)
coursename = models.CharField(max_length=50)
userid = models.IntegerField()
code = models.CharField(max_length=50)
videolink = models.FileField(default='default_link')
# roleid = models.ForeignKey(RoleName, on_delete=models.CASCADE)
createddate = models.DateTimeField()
imagelink = models.URLField(default='default_link')
duration = models.DateTimeField()
longdes = models.TextField()
coursetype = models.CharField(max_length=50)
# classid = models.ForeignKey(TblClass, on_delete=models.CASCADE)
assignto = models.CharField(max_length=200)
status = models.BinaryField()
def _str_(self):
return self.coursename
class Meta:
db_table = "courseids"
class SchoolTeacher(models.Model):
teacherid = models.IntegerField(primary_key=True)
name = models.CharField(max_length=50)
address = models.CharField(max_length=200)
email = models.EmailField()
contact = models.IntegerField()
# classid = models.ForeignKey(TblClass, on_delete=models.CASCADE)
# schoolid = models.ForeignKey(School, on_delete=models.CASCADE)
passowrd = models.CharField(max_length=13)
image = models.ImageField(default='default.jpg')
regno = models.CharField(max_length=20)
joiningdate = models.DateTimeField()
def _str_(self):
return self.name
class Meta:
db_table = "teacherids"
class Student(models.Model):
studentid = models.IntegerField(primary_key=True)
regno = models.CharField(max_length=20)
name = models.CharField(max_length=50)
email = models.EmailField(max_length=50)
contactno = models.CharField(max_length=13)
registrationdate = models.DateTimeField()
address = models.CharField(max_length=200)
# classid = models.ForeignKey(TblClass, on_delete=models.CASCADE)
# schoolid = models.ForeignKey(School, on_delete=models.CASCADE)
password = models.CharField(max_length=13)
imagepath = models.ImageField(max_length=100, default='default.jpg')
sectionid = models.IntegerField()
def _str_(self):
return self.name
class Meta:
db_table = "studentids"
The html form for the feedback form is
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<form action="/studentFeedBack/" method="POST">
{% csrf_token %}
<label for="studentid">Student Id</label>
<select name="studentid" required>
{% for studentid in studentids %}
<option value="{{studentid.id}}">{{studentid.name}}</option>
{% endfor %}
</select><br><br>
<label for="courseid">Course Id</label>
<select name="courseid" required>
{% for courseid in courseids %}
<option value="{{courseid.id}}">{{courseid.coursename}}</option>
{% endfor %}
</select><br><br>
<label for="teacherid">Teacher Id</label>
<select name="teacherid" required>
{% for teacherid in teacherids %}
<option value="{{teacherid.id}}">{{teacherid.name}}</option>
{% endfor %}
</select><br><br>
<label for="description" >Feedback</label>
<textarea class="form-control" rows="3" name="description"></textarea><br><br>
<label for="rating">Rating</label><br>
<input type="radio" id="Good" name="rating" value="Good">
<label for="Good">Good</label><br>
<input type="radio" id="Average" name="rating" value="Average">
<label for="Average">Average</label><br>
<input type="radio" id="Bad" name="rating" value="Bad">
<label for="Bad">Bad</label><br><br>
<button type="submit" class="btn btn-primary" >Submit</button>
</form>
</body>
</html>
Everything is working fine in command prompt and browser as soon as the form is submitted it is giving the following error
FieldError at /studentFeedBack/
Cannot resolve keyword 'id' into field. Choices are: address, contactno, email, imagepath, name, password, registrationdate, regno, sectionid, studentfeedback, studentid
I tried adding the data manually in admin panel and its working completely okay
The problem in your code is that your models have studentid/courseid/teacherid as primary keys. Which means that your models no longer have an id field.
You'll will see the same problem if you inspect your html, as the values will be empty. You could replace your id with pk (which is always usable) or the correct primary key field.
Another note, check out Django ModelForms, which help you with the validation of the data. As now you'll get DoesNotExists errors (or even ValueErrors) if someone hijacks your form and posts in random data.

In Django getting errors based on dropdown selection

Getting error when fields are selected from the down. Not seeing why it is throwing error
Django Dropdown form.error: ERROR ALERT:
location_name Select a valid choice. That choice is not one of the available choices.
Here is the model, form, view and html looks like
MODEL
class Code (models.Model):
name = models.CharField(max_length=4, default=None, blank=True)
def __str__(self): return self.name
class Device (models.Model):
code = models.ForeignKey(Code, on_delete=models.CASCADE, null=True)
ip = models.GenericIPAddressField(protocol='IPv4', unique=True)
def __str__(self): return self.ip
class SiteData (models.Model):
site = models.ForeignKey(Code, on_delete=models.SET_NULL, null=True)
site_ip = models.ForeignKey(Device, on_delete=models.SET_NULL, null=True)
site_data1 = models.CharField(max_length=3, default='120')
class CombineData(models.Model):
location = models.ForeignKey(Code, on_delete=models.SET_NULL, null=True)
device = models.ForeignKey(AddData, on_delete=models.SET_NULL, null=True)
locdata = models.ForeignKey(SiteData, on_delete=models.SET_NULL, null=True)
FORM
class CombineData_form(forms.ModelForm):
class Meta:
model = P2_NexusLeafPair
fields = '__all__'
VIEW
def comboView(request, *args, **kwargs):
template_name = 'site_display.html'
code = Code.objects.order_by('-name')
device = Device.objects.order_by('-ip')
sitename = SiteData.objects.order_by('-site')
content = {
'code': code,
'device': device,
'sitename': sitename
}
if request.method == 'POST':
form = CombineData_form(request.POST or None)
print(form.is_valid())
#print(form.errors)
if form.is_valid():
. . .
else:
messages.error(request, form.errors)
else:
form = CombineData_form()
return render(request, template_name, content)
HTML
<form id="comboView" class="post-form" role=form method="POST" action="comboView">{% csrf_token %}
<div name="code" class="dropdown" id="mainselection" required>
<select name="dc_name">
<option class="dropdown-item" value="">---------</option>
{% for item in code %}
<option value="{{ item }}">{{ item }}</option>
{% endfor %}
</div>
<input type="submit" value="Submit" />
</form>
{same as other fields: device, sitename}
{% for item in content %}
{{item.code}}
{% endfor %}
Try that.

Django 2.0: TextInput in ModelChoiceField shows id instead if value

I changed ModelChoiceField to be shown as a TextInput.
I have a field named 'filename' of this type: models.ForeignKey('Filename', on_delete=models.SET_NULL, null=True, blank=True) in a class as follow:
models.py
class Event(models.Model):
name = models.CharField('Name', max_length=100, blank=True, default='')
filename = models.ForeignKey('Filename', on_delete=models.SET_NULL, null=True, blank=True)
class Filename(models.Model):
name = models.CharField('Name', max_length=50)
def __str__(self):
return self.nome
This is part of my 'forms.py' I use show form in frontend after defining the template (myappname/templates/myappname/event_edit.html)
forms.py
class EventEditForm(forms.ModelForm):
def __init__(self, data=None, *args, **kwargs):
if data is not None:
data = data.copy()
if data['filename']:
f, f_created = Filename.objects.get_or_create(nome=data['filename'])
data['filename'] = m.id
super(EventEditForm, self).__init__(data=data, *args, **kwargs)
self.fields['filename'] = forms.ModelChoiceField(queryset=Filename.objects.all(), widget=forms.TextInput(attrs={'class': 'form-control', 'value':self.instance.filename}))
self.fields['filename'].required = False
class Meta:
model = Event
fields = ['name', 'filename']
and this is my event_edit.html:
<form method="post" class="form-horizontal">
{% csrf_token %}
{% for field in event_form %}
<div class="form-group form-group-lg">
<label for="{{ field.id_for_label }}" class="col-sm-2 control-label">{{field.label}}</label>
<div class="col-sm-6">
{{ field }}
</div>
<div class="col-sm-4">
{{ field.errors }}
</div>
</div>
{% endfor %}
<div class="form-group">
<div class="col-sm-10">
<button type="submit" class="btn btn-primary btn-lg center-block">Save</button>
</div>
</div>
</form>
The problem is that if I override ModelChoiceField to be a TextInput the 'filename' field shows id instead of showing field name.
Otherwise, If I leave it as a Choice Field it correctly shows value instead of id.
How can I solve this issue?
Based on your comments and the code in EventEditForm, you want a form that will:
display the Event.name and the linked Filename.name
use the submitted name to update Event.name
use the submitted filename to lookup or create a Filename and update Event.filename
This should work:
class EventEditForm(forms.ModelForm):
"""
Calling form.save() will:
* update the Event.name
* update the Event.filename with a Filename instance
found or created using the supplied name
"""
fname = forms.CharField(
label='Filename',
required=False,
widget=forms.TextInput(attrs={'class': 'form-control'}),
)
class Meta:
model = Event
fields = ['name',]
widgets = {
'name': forms.TextInput(attrs={'class': 'form-control'}),
}
def __init__(self, *args, **kwargs):
super(EventEditForm, self).__init__(*args, **kwargs)
self.initial['fname'] = self.instance.filename
def save(self, commit=True):
instance = super(EventEditForm, self).save(commit=False)
cleaned_fname = self.cleaned_data['fname']
if cleaned_fname:
f, f_created = Filename.objects.get_or_create(name=cleaned_fname)
instance.filename = f
else:
instance.filename = None
if commit:
instance.save()
return instance