ModelForm has empty fields list - django

Sorry for my poor english...
I've got a Model called Habitation :
class Habitation(models.Model):
propr = models.ForeignKey(Client, related_name="proprietaire")
locat = models.ForeignKey(Client, related_name="locataire", null=True, blank=True)
etage = models.CharField(max_length=2, blank=True)
numero = models.CharField(max_length=3, blank=True)
ad1 = models.CharField(max_length=64)
ad2 = models.CharField(max_length=64, blank=True)
cp = models.CharField(max_length=5)
ville = models.CharField(max_length=32)
def get_appareils(self):
return Appareil.objects.filter(habitation=self)
def selflink(self):
if self.id:
return 'Editer' % str(self.id)
else:
return 'Indéfini'
selflink.allow_tags = True
def __unicode__(self):
return u'%s - %s %s' % (self.ad1, self.cp, self.ville)
With his edit view :
def edit(request, habitation_id):
habitation = Habitation.objects.get(pk=habitation_id)
if request.POST:
form = HabitationForm(request.POST, instance=habitation)
if form.is_valid():
form.save()
return redirect('clients')
else:
form = HabitationForm(instance=habitation)
print form.fields
return render_to_response('habitations/edit.html', {
'habitation_id': habitation_id,
'form': form,
}, context_instance=RequestContext(request))
and his template :
<table>
<form action="/habitations/edit/{{ habitation_id }}/" method="post">
{{ form }}
{% csrf_token %}
{{ form.as_table }}
</form>
</table>
Form:
from django import forms
from client import models
class HabitationForm(forms.ModelForm):
class meta:
model = models.Habitation
fields = ('propr', 'locat', 'etage', 'numero', 'ad1', 'ad2', 'cp', 'ville',)
My view (or my ModelForm) doesn't retrive any field, so no more form field.
Is anybody has any suggestion ?

The meta class name in form should be Meta not meta.
Update your form to
from django import forms
from client import models
class HabitationForm(forms.ModelForm):
class Meta: #<---- define with capital M
model = models.Habitation
fields = ('propr', 'locat', 'tegae', 'numero', 'ad1', 'ad2', 'cp', 'ville',)

Related

Django form fields required and optional configuration

I am in a middle of a project. I have a model :-
class CustomersModels(models.Model):
def servChoices(servs):
lst = [x.serv_name for x in servs]
ch =()
for a in lst:
ch += (a,a),
return ch
customer_name = models.CharField(max_length=100)
comp_name = models.CharField(max_length=100)
ph_no = models.CharField(max_length=12)
webs_name = models.URLField(max_length=200)
service_insterested = models.OneToOneField(ServiceModel, on_delete = models.CASCADE)
def __str__(self):
return self.customer_name
I have a corresponding form for this model.
Now what i want is the fields customer_name, comp_name, webs_name
to be optional in one page. And required in another page.
Please guide me to establish the task in the most convenient manner
Deleted in 'def servChoices', service_insterested because I don't have access to them in the model. I also made it to return a string with the name of the class return 'CustomersModels', so that you can edit, delete records with empty values.
The field class 'customer_name', 'comp_name' ,'webs_name' are set to blank=True to make them optional.
In the NoForm, the required field is 'ph_no'. YesForm requires all fields to be filled in. For this, a validator (clean) is used, which will display a message on the page which field is not filled in (the form will not be sent until all fields are filled). You can read about clean here:
In the bboard views, replace with your folder where you have the templates (this is the string template_name = 'bboard/templ_yes.html').
urls.py
urlpatterns = [
path('yes/', YesCreateView.as_view(), name='yes'),
path('no/', NoCreateView.as_view(), name='no'),
]
views.py
from django.views.generic.edit import CreateView
from django.urls import reverse_lazy
from .forms import NoForm, YesForm
class NoCreateView(CreateView):
template_name = 'bboard/templ_no.html'
form_class = NoForm
success_url = reverse_lazy('no')
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
return context
class YesCreateView(CreateView):
template_name = 'bboard/templ_yes.html'
form_class = YesForm
success_url = reverse_lazy('yes')
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
return context
forms.py
from django.forms import ModelForm
from .models import CustomersModels
from django.core.exceptions import ValidationError
class YesForm(ModelForm):
class Meta:
model = CustomersModels
fields = ('customer_name', 'comp_name', 'ph_no', 'webs_name')
def clean(self):
cleaned_data = super().clean()
customer_name = cleaned_data.get('customer_name')
comp_name = cleaned_data.get('comp_name')
webs_name = cleaned_data.get('webs_name')
if len(customer_name) <= 0 or customer_name == '':
raise ValidationError(
"fill in the field customer_name"
)
if len(comp_name) <= 0 or comp_name == '':
raise ValidationError(
"fill in the field comp_name"
)
if len(webs_name) <= 0 or webs_name == '':
raise ValidationError(
"fill in the field webs_name"
)
class NoForm(ModelForm):
class Meta:
model = CustomersModels
fields = ('customer_name', 'comp_name', 'ph_no', 'webs_name')
models.py
class CustomersModels(models.Model):
customer_name = models.CharField(max_length=100, blank=True)
comp_name = models.CharField(max_length=100, blank=True)
ph_no = models.CharField(max_length=12)
webs_name = models.URLField(max_length=200, blank=True)
def __str__(self):
return 'CustomersModels'
tepmplate(templ_yes.html)
<h2>form</h2>
<form method="post" action="{% url 'yes'%}">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="adding">
</form>
tepmplate(templ_no.html)
<h2>form</h2>
<form method="post" action="{% url 'no'%}">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="adding">
</form>

How to retrieve selected data from Django Choice Field?

I want to retrieve the question_description answer_descritption and question_image answer_image if found in the database according to topic and question type using two ChoiceField for both: Topic and Question Type.
However, I don't know how to do that. I have seen some tutorials and gotten glimpses of what I have to do, but I am not sure how to preform the same techniques on my case because online there are not that many ChoiceField examples, except that there are general examples on how to use forms and extract data from the database.
This is the models.py
from django.db import models
from home.choices import *
# Create your models here.
class Topic(models.Model):
topic_name = models.IntegerField(
choices = question_topic_name_choices, default = 1)
def __str__(self):
return '%s' % self.topic_name
class Image (models.Model):
image_file = models.ImageField()
def __str__(self):
return '%s' % self.image_file
class Question(models.Model):
question_type = models. IntegerField(
choices = questions_type_choices, default = 1)
question_topic = models.ForeignKey( 'Topic',
on_delete=models.CASCADE,
blank=True,
null=True)
question_description = models.TextField()
question_answer = models.ForeignKey( 'Answer',
on_delete=models.CASCADE,
blank=True,
null=True)
question_image = models.ForeignKey( 'Image',
on_delete=models.CASCADE,
blank=True,
null=True)
def __str__(self):
return '%s' % self.question_type
class Answer(models.Model):
answer_description = models.TextField()
answer_image = models.ForeignKey( 'Image',
on_delete=models.CASCADE,
blank=True,
null=True)
answer_topic = models.ForeignKey( 'Topic',
on_delete=models.CASCADE,
blank=True,
null=True)
def __str__(self):
return '%s' % self.answer_description
This is the forms.py
from django import forms
from betterforms.multiform import MultiModelForm
from .models import Topic, Image, Question, Answer
from .choices import questions_type_choices, question_topic_name_choices
class TopicForm(forms.ModelForm):
topic_name = forms.ChoiceField(
choices=question_topic_name_choices,
widget = forms.Select(
attrs = {'class': 'home-select-one'}
))
class Meta:
model = Topic
fields = ['topic_name',]
def __str__(self):
return self.fields
class QuestionForm(forms.ModelForm):
question_type = forms.ChoiceField(
choices= questions_type_choices,
widget = forms.Select(
attrs = {'class': 'home-select-two'},
))
class Meta:
model = Question
fields = ['question_type',]
def __str__(self):
return self.fields
class QuizMultiForm(MultiModelForm):
form_classes = {
'topics':TopicForm,
'questions':QuestionForm
}
This is the views.py
from django.shortcuts import render, render_to_response
from django.views.generic import TemplateView
from home.models import Topic, Image, Question, Answer
from home.forms import QuizMultiForm
class QuizView(TemplateView):
template_name = 'index.html'
def get(self, request):
# What queries do I need to put here to get the question and answer's description according to the ChoiceField input
form = QuizMultiForm()
return render (request, self.template_name, {'form': form})
def post(self, request):
form = QuizMultiForm(request.POST)
if form.is_valid():
text = form.cleaned_data['topic_name', 'question_type'] # I don't know what to put here!
args = {'form': form, 'text': text}
return render (request, self.template_name, args)
This is the template:
{% extends 'base.html' %}
{% block content %}
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" id="home-Physics-time-button">It is Physics Time</button>
<h1> {{ text }} </h1>
</form>
{% endblock content %}
I would appropriate the help!
Thank you!
The cleaned_data attribute of the form, contains a dictionary that maps the name of the field with the bounded data. And from the MultiForm docs you can read:
cleaned_data
Returns an OrderedDict of the cleaned_data for each of the child forms.
Just extract data like this:
topic_name = form.cleaned_data['topics']['topic_name']
question_type = form.cleaned_data['question']['question_type']
# And so on ...

How to get option for select tag in forms.py from my model?

Please help me to solve this problem! I have form for job application and I have this in my
models.py:
class Vacancy(models.Model):
vacancy_title = models.CharField(max_length=100)
vacancy_description = models.TextField()
data = models.DateTimeField(default=timezone.now)
contact_person = models.CharField(max_length=50)
phone_number = models.CharField(max_length=30)
mail = models.EmailField();
def __str__(self):
return self.vacancy_title
A user must choose one of the vacancies
<select name="job_field" id="job_field">
{% for vacancy in vacancies %}
<option value="">{{ vacancy.vacancy_title }}</option>
{% endfor %}
</select>
Here is the forms.py:
from django import forms
from .models import Vacancy
CHOICES = (Vacancy.objects.all().values_list('vacancy_title', flat=True))
class ApplicantForm(forms.Form):
name = forms.CharField(max_length=50)
surname = forms.CharField(max_length=50)
email = forms.EmailField()
selected_position = forms.ChoiceField(choices=CHOICES)
And the views.py:
def send_resume(request):
vacancies = Vacancy.objects.all();
if request.method == 'POST':
form = ApplicantForm(request.POST)
if form.is_valid():
name = form.cleaned_data['applicant_name']
surname = form.cleaned_data['applicant_surname']
passport_number = form.cleaned_data['passport_number']
from_mail = form.cleaned_data['mail']
position = form.cleaned_data['position']
else:
form = ApplicantForm()
context = {'vacancies': vacancies}
return render(request, 'interactive/send_resume.html', context)
Now in the forms.py I cannot connect vacancy_title to the choice of the select group(Choice Field). How to do it?
You can just use ModelChoiceField.
selected_position = forms.ModelChoiceField(queryset=Vacancy.objects.all(), empty_label='(Nothing)')
It's more generic way
Use django-model-utils module. Your model code can look as below.
from model_utils import Choices
VACANCY_CHOICE = Choices(
('MANAGER', 'MANAGER', _('Development Manager')),
('SALES', 'SALES', _('Sales VP')),
)
class Vacancy(models.Model):
vacancy_title = models.CharField(choices=VACANCY_CHOICE, default=VACANCY_CHOICE.MANAGER,max_length=100)
Try to use {{form}} in your template.

get data based on primary key and display in html

I am trying to get data based on primary key and display for EDIT in html page. but i am getting 'QuerySet' object has no attribute '_meta' error.
I try to resolve it by looking at other posts but unable to do so.. hope somebody will help in problem.
my forms:
class StudentForm(forms.ModelForm):
class Meta:
model = Student
fields = ('stuName','stuCity','stuPhone','stuNationality','stuCreatedt')
class CourseForm(forms.ModelForm):
class Meta:
model = Course
fields = ('courseId','courseName','enrolledStu','students','dept')
class DeptForm(forms.ModelForm):
class Meta:
model = Dept
fields = ('deptId','deptName')
Models.py
class Student(models.Model):
stuName = models.CharField(max_length=100)
stuCity = models.CharField(max_length=100)
stuPhone = models.IntegerField(max_length=10)
stuNationality = models.CharField(max_length=50)
stuCreatedt = models.DateTimeField(default=timezone.now)
def __str__(self):
return '%s %s %s' % (self.stuName,self.stuCity,self.stuNationality)
Class Dept :
class Dept(models.Model):
deptId = models.AutoField(primary_key=True)
deptName = models.CharField(max_length=100)
def __str__(self):
return '%s %s' % (self.deptId, self.deptName)
class Course
class Course(models.Model):
courseId = models.AutoField(primary_key=True)
courseName = models.CharField(max_length=100)
enrolledStu = models.IntegerField(max_length=3)
students = models.ManyToManyField(Student)
dept = models.ForeignKey(Dept, on_delete=models.CASCADE)
def __str__(self):
return '%s %s %s %s' % (self.courseName,self.enrolledStu,self.students,self.dept)
urls.py for edit is
url(r'^stuApp/(?P\d+)/$', views.edtStudent, name='edtStudent'),
method for edit inside view.py is :
def edtStudent(request,pk):
course = Course.objects.filter(pk=1).prefetch_related('students').select_related('dept')
if request.method =="POST":
form = CourseForm(request.POST,instance=Course)
if form.is_valid():
course = form.save(commit=False)
course.courseName = request.POST['courseName']
course.enrolledStu = request.Post['enrolledStu']
course.save()
course.save_m2m()
return redirect('liststudent')
else:
#form = CourseForm()
#return render(request, 'stuApp/edtStudent.html', {'form':form})
form = CourseForm(instance=course)
return render_to_response('edtStudent.html', {'form': form})
Html is :
<form method="POST" class="post-form">{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="save btn btn-default">Save</button>
</form>
it displays log from else but somehow doesn't display anything on html..
Thank you for your time....
filter always returns a queryset. But you need to pass a model instance, not a queryset, to the form. Use get instead.
course = Course.objects.filter(pk=1).prefetch_related('students').select_related('dept').get()

How to create and process a form with multiple same fields?

I'm really stuck with this. To show my problem I created a new Django project and started from scratch, focusing only on one single form.
What I'm trying to do is to create a form with several fields of the same name. I tried using modelformset_factory to achieve this but it looks to me like it's not what I really need.
Below is my code (also on dpaste) which currently works fine with one single field called name. How can I create and process a form which would have several name fields? Could somebody point me in the right direction?
# models.py
class Category(models.Model):
name = models.CharField(max_length=30, unique=True)
user = models.ForeignKey(User, blank=True, null=True)
class Meta:
verbose_name_plural = "Ingredience Categories"
def __unicode__(self):
return self.name
# forms.py
class CategoryForm(ModelForm):
class Meta:
model = Category
fields = ('name',)
# views.py
def home(request):
if request.method == 'POST':
catform = CategoryForm(request.POST)
catformInstance = catform.save(commit = False)
catformInstance.save()
return HttpResponseRedirect('')
else:
catform = CategoryForm()
context = {'catform': catform}
return render_to_response('home.html', context, context_instance=RequestContext(request))
# home.html template
<h3>Insert new Category</h3>
<form action="/" method="post" id="ingr-cat-form">{% csrf_token %}
{{ catform.as_p }}
<input type="submit" name="ingrCatForm" value="Save" />
</form>
UPDATE: to clarify, I want to allow user to insert several categories within one form. I think I'm getting close, here is my new version of views.py but it still stores just one category (the last one in the list):
def home(request):
if request.method == 'POST':
catform = CategoryForm(request.POST)
names = request.POST.getlist('name')
catformInstance = catform.save(commit = False)
for name in names:
catformInstance.name = name
catformInstance.save()
return HttpResponseRedirect('')
else:
catform = CategoryForm()
context = {'catform': catform}
return render_to_response('home.html', context, context_instance=RequestContext(request))
You cannot have fields with the same name (on the same Model). If you only need to change the html label in the html form, use
class Category(models.Model):
name = models.CharField(max_length=30, unique=True)
name2 = models.CharField(max_length=30, unique=True, verbose_name="name")
user = models.ForeignKey(User, blank=True, null=True)
or
class CategoryForm(ModelForm):
def __init__(self , *args, **kwargs):
super(CategoryForm, self).__init__(*args, **kwargs)
self.fields['name2'].label = "name"
Here is a working solution. Thanks to #YardenST for pointing me in the right direction. I managed to solve my initial problem by following this tutorial.
# models.py
class Category(models.Model):
name = models.CharField(max_length=30, unique=True)
user = models.ForeignKey(User, blank=True, null=True)
class Meta:
verbose_name_plural = "Ingredience Categories"
def __unicode__(self):
return self.name
# forms.py
class CategoryForm(ModelForm):
class Meta:
model = Category
fields = ('name',)
# views.py
def home(request):
if request.method == 'POST':
catforms = [CategoryForm(request.POST, prefix=str(x), instance=Category()) for x in range(0,3)]
if all([cf.is_valid() for cf in catforms]):
for cf in catforms:
catformInstance = cf.save(commit = False)
catformInstance.save()
return HttpResponseRedirect('')
else:
catform = [CategoryForm(prefix=str(x), instance=Category()) for x in range(0,3)]
context = {'catform': catform}
return render_to_response('home.html', context, context_instance=RequestContext(request))
# home.html template
<h3>Insert new Category</h3>
<form action="/" method="post" id="ingr-cat-form">{% csrf_token %}
{% for catform_instance in catform %} {{ catform_instance.as_p }} {% endfor %}
<input type="submit" name="ingrCatForm" value="Save" />
</form>