I'm doing a edit form for some data. I'm having problem to pass information to . As you can see in my view, I pass the data to form using "initial" dictionary.
VIEWS.PY
#login_required
def project_detail(request, project_id):
if request.method == 'POST':
project = get_object_or_404(Project, pk=project_id)
form = ProjectDetailForm(project_id, request.POST, instance = project)
if form.is_valid():
instance = form.save(commit=False)
instance.client = Project.objects.get(pk=project_id).client
form.save()
messages.success(request,'Projeto modificado')
return redirect('projects')
else:
messages.error(request,'Ocorreu um erro!')
else:
project = get_object_or_404(Project, pk=project_id)
form = ProjectDetailForm(project_id, initial={'modal':project.modal,
'culture':project.culture,
'owner':project.owner,
'value':project.value,
'final_date':project.final_date,
'text':project.text,
'status':project.status,
'farm':project.farm.values()})
return render(request,'project_detail.html',{'form':form})
But doing this, the data is not displaied in . Thinking here, ManyToManyField saves data in lists. I tried iterate this field but still not working and I guess thats not the best way to do this.
MODELS.PY
class Project(models.Model):
modal_types = [('CUSTEIO AGRÍCOLA','Custeio Agrícola'),('CUSTEIO PECUÁRIO','Custeio Pecuário'),('INVESTIMENTO AGRÍCOLA','Investimento Agrícola'),('INVESTIMENTO PECUÁRIO','Investimento Pecuário'),('FGPP','FGPP')]
status_opts = [('Análise','Análise'),('Desenvolvimento','Desenvolvimento'),('Processamento','Processamento'),('Liberação','Liberação'),('Finalizado','Finalizado'),('Cancelado','Cancelado'),('Suspenso','Suspenso')]
farm = models.ManyToManyField(Farm, related_name='farm_name',verbose_name='Propriedade beneficiada')
client = models.ForeignKey(Clients, on_delete=models.CASCADE, related_name='project_client',default=None,null=True, verbose_name='Cliente')
owner = models.ForeignKey(Owner, on_delete=models.CASCADE, related_name='project_bidder',default=None,null=True, verbose_name='Proponente')
warranty = models.ManyToManyField(Farm, related_name='project_warranty',default=None, verbose_name='Propriedade de garantia')
modal = models.CharField(max_length=100,default=None,choices=modal_types, null=True, verbose_name='Tipo')
culture = models.CharField(max_length=50,null=True, verbose_name='Cultura')
status = models.CharField(max_length=50,null=True, verbose_name='Status', choices=status_opts)
created_date = models.DateField(null=True, verbose_name='Data de criação')
value = models.FloatField(max_length=10,null=True, verbose_name='Valor financiado')
final_date = models.DateField(default=None,null=True, verbose_name='Fim do contrato')
text = models.TextField(default=None,null=True, verbose_name='Observações')
forms.py
class ProjectDetailForm(ModelForm):
class Meta:
model = Project
fields = ['status','owner', 'farm', 'warranty', 'modal', 'culture', 'value','final_date','text']
def __init__(self, project_id, *args, **kwargs):
client_id = Project.objects.get(pk=project_id).client
super(ProjectDetailForm,self).__init__(*args,**kwargs)
self.fields['value'].required = False
self.fields['final_date'].required = False
self.fields['text'].required = False
self.fields['farm'].queryset = Farm.objects.filter(client=client_id)
self.fields['warranty'].queryset = Farm.objects.filter(client=client_id)
for field_name, field in self.fields.items():
field.widget.attrs['class'] = 'form-control'
Here all the fields with information, but in "select" nothing is selected, despite having data in the database
Someone can help me?
Why are you passing 'project_id' into your form class instance? Try changing this:
form = ProjectDetailForm(project_id, request.POST, instance = project)
to this:
form = ProjectDetailForm(request.POST, instance = project)
and see if it helps. Also in your form initialization, I'm not sure you're using the "initial=" values dictionary correctly. Initial values are typically defaults applicable to the "create" view, not database records that it sounds like you want to see in an update view. I think you want to pass in the instance of your database record there, something like:
else:
project = get_object_or_404(Project, pk=project_id)
form = ProjectDetailForm(instance=project)
Also, you really don't need to write project object query twice in this view. You can do something like:
def project_detail(request, project_id):
project = get_object_or_404(Project, pk=project_id) # query this once here
if request.method == 'POST':
form = ProjectDetailForm(request.POST, instance=project)
if form.is_valid():
instance = form.save(commit=False)
instance.client = Project.objects.get(pk=project_id).client
form.save()
messages.success(request,'Projeto modificado')
return redirect('projects')
else:
messages.error(request,'Ocorreu um erro!')
# you probably want a redirect here as well
else:
form = ProjectDetailForm(instance=project)
return render(request,'project_detail.html',{'form':form})
Finally, if you're trying to limit the choices from your ManyToMany field in the user's form, you can do so with something like this:
class ProjectDetailForm(forms.ModelForm):
class Meta:
model = YourModelName
fields = ['farm']
farm = forms.ModelMultipleChoiceField(
queryset=Farm.objects.filter(some_field=some_criteria).order_by('some_field'),
widget=forms.CheckboxSelectMultiple)
More info about widgets on form classes here in Django docs.
How can i use in my views instances from other class?
For example in my views i have:
MODELS
class Projekt(models.Model):
nazwa_projektu = models.CharField(max_length=200, unique=True)
opis_projektu = models.TextField()
wybor_projekt = models.CharField(max_length=100, choices=wybor_t_f, default="FALSZ")
VIEWS
def ProjektViewOptions(request, pk):
profil = Profil.objects.get(user=request.user)
projekt = Projekt.objects.get(id=pk)
srodek = projekt.srodek_set.all
form = OptionsForm(request.POST or None)
template_name = 'viewOptionsProjekt.html'
if request.method == "POST":
if form.is_valid():
pro.wybor_projekt = 'PRAWDA'
pro.save()
opcje = form.save(commit=False)
opcje.wlasciciel = profil
opcje.projekt = projekt
opcje.save()
opcje.wybor = 'PRAWDA'
form.save()
I want to do that, if i create a new Project this project have a options "FALSZ" when I "POST" this options will turn into the "PRAWDA"
I tried do :
opcje.projekt.wybor_projekt = "PRAWDA"
But this unfortunately dont work.
I dont want full solution. I need a little direction. ;)
I currently have a Django form that saves data from a questionnaire against a user, where a user is stored as a Foreign Key from the Person model. I can successfully find the person from the Person class using get_object_or_404(), but when I try to save(commit=True), the data is not being saved in the database. See below for my code:
# models.py
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=100)
email = models.EmailField(max_length=254, primary_key=True)
tel_number = models.CharField(max_length=13, blank=True)
referral_code = models.UUIDField()
class Meta:
verbose_name_plural = 'People'
def __str__(self):
return str(self.referral_code)
class Questionnaire(models.Model):
user = models.ForeignKey(Person, related_name='questionnaire_person', on_delete=models.CASCADE)
... and some questionnaire questions here (CharFields and TextFields) ...
# views.py
def index_questionnaire(request):
template = 'questionnaire.html'
# load blank instance of template
questionnaire = UserQuestionnaire()
context = {
"questionnaire": questionnaire
}
# if user has submitted something, check form is valid
if request.method == 'POST':
answers = UserQuestionnaire(data=request.POST)
if answers.is_valid():
# submission is genuine so save as new entry to database
# get user's unique referral ID from URL
user_referral_id = request.GET.get('user')
# check legit person
try:
answers.save(commit=False)
answers.person = get_object_or_404(Person, referral_code=user_referral_id)
print('user found: {}'.format(answers.person))
answers.save(commit=True)
print('Questionnaire saved')
except:
print("user not found")
return render(
request,
template,
context
)
#forms.py
class UserQuestionnaire(forms.ModelForm):
class Meta:
model = Questionnaire
fields = (
'answers_1',
'free_text_1',
'answers_2',
'answers_3',
'answers_4',
'answers_5',
'answers_6'
)
widgets = {
'answers_2' : forms.RadioSelect(),
'answers_3' : forms.RadioSelect(),
'answers_4' : forms.RadioSelect(),
'answers_5' : forms.RadioSelect(),
}
So at the moment I'm drawing the user parameter from the URL, which is uuid.uuid4(). The print statement in the "try: except" bit successfully prints out the user UUID as expected, yet when submitted it doesn't save correctly. For further info, I am using the MultiSelectField() for one of the questionnaire questions.
If anyone has any suggestions as to why this might be, that would be amazing!
That is because asnwers.save(commit=False) creates another new object.
Do something like
f = answer.save(commit=false)
f.person = get_object_or_404(Person, referral_code=user_referral_id)
f.save()
No need to do f.save(commit=True) since the True is default.
for more info check docs:
docs.djangoproject.com/en/3.1/topics/forms/modelforms/
I am new to Django. I want to populate a form for model Score with dynamic labels/verbose names from another model : Question.
Essentially, each user has 5 current questions which they are going to score in a form as either "yes" or "no"
I have the data for a User's current five questions saved in a dictionary and can pass this dictionary into the view or template, but do not know how to use a dictionary to population the labels/ verbose names for the form.
#Model
class Score(models.Model):
yesno = ((0,"No"),(1,"Yes"),)
oneScore =models.IntegerField(choices=yesno,default='none')
twoScore =models.IntegerField(choices=yesno,default='none')
threeScore =models.IntegerField(choices=yesno,default='none')
fourScore =models.IntegerField(choices=yesno,default='none')
fiveScore =models.IntegerField(choices=yesno,default='none')
author = models.ForeignKey('auth.User')
date_created = models.DateTimeField(blank=False, null=False)
#Model
class QuestionManager(models.Manager):
def current_for_user(self,user):
question1 = Question.objects.filter(author=user,statementNumber=1).order_by('-id').first()
question2 = Question.objects.filter(author=user,statementNumber=2).order_by('-id').first()
question3 = Question.objects.filter(author=user,statementNumber=3).order_by('-id').first()
question4 = Question.objects.filter(author=user,statementNumber=4).order_by('-id').first()
question5 = Question.objects.filter(author=user,statementNumber=5).order_by('-id').first()
question_list = {"1":question1,
"2":question2,
"3":question3,
"4":question4,
"5":question5}
return question_list
class Question(models.Model):
statementNumber=models.IntegerField(choices=NUMBER, default='1',verbose_name="The number of the statement")
text = models.CharField(max_length=500,help_text="Enter your text", verbose_name="New Statement")
author = models.ForeignKey('auth.User')
date_created = models.DateTimeField(blank=False, null=False)
objects=QuestionManager()
#Form
class ScoreForm(forms.ModelForm):
class Meta:
model = Score
fields = ('oneScore','twoScore','threeScore','fourScore','fiveScore','bigScore')
#View
def score(request):
user = request.user
questions = Question.objects.current_for_user(user)
if request.method == "POST":
questions = Question.objects.current_for_user(user)
form = ScoreForm(request.POST)
if form.is_valid():
score = form.save(commit=False)
score.author = request.user
score.save()
return redirect('scoresheet',pk=score.pk)
else:
form = ScoreForm()
return render(request,'MC/score.html',{'form': form,'questions':sorted(questions.items())})
I'm not really sure what you're after, but you can pass anything you like to the form:
class ScoreForm(forms.ModelForm):
def __init__(self, questions, *args, **kwargs):
super().__init__(*args, **kwargs)
for num, question in questions.items():
self.fields.get('some_field').label = question
#View
def score(request):
user = request.user
questions = Question.objects.current_for_user(user)
if:
# ...
else:
form = ScoreForm(questions)
return render(request,'MC/score.html',{'form': form})
I am trying to make an image field using mongoengine in DJango. The form shows up, I upload the image, all other fields are saved except the image but it keeps saying "This field is required" for the thumbnail_new field. Here is my model
class VideoMain(Document):
"""This class represents the Video Meta data model."""
video_id = fields.SequenceField()
ytlink = fields.StringField()
title = fields.StringField()
description =fields.StringField()
show = fields.StringField()
published_at = forms.DateTimeField()
views = fields.IntField()
thumbnail = fields.StringField()
**thumbnail_new = fields.ImageField(size=600,thumbnail_size=None)**
channel_name = fields.StringField()
channel_description = fields.StringField()
guests = fields.ListField(fields.StringField(max_length=30))
anchors = fields.ListField(fields.StringField(max_length=30))
tags = fields.ListField(fields.StringField(max_length=30))
And here is the Django form
from django import forms
from .models import *
class ShowDetailsForm(forms.Form):
shows = Show.objects.all()
title = forms.CharField()
description = forms.CharField()
channel = forms.CharField()
publishingdate = forms.CharField()
views = forms.IntegerField()
thumbnail = forms.CharField()
thumbnail_new = forms.ImageField()
#show = forms.ChoiceField(shows)
class Meta:
model = VideoMain
fields="__all__"
And finally the view function where the form has to be stored
def show_video_data(request):
"""
View function for renewing a specific BookInstance by librarian"""
if request.method == 'POST':
#print("I am post")
form = ShowDetailsForm(request.POST,request.FILES)
if form.is_valid():
newfile=FileUploadHandler(title='anything', file=request.FILES['thumbnail_new'])
newfile.save()
print (form.photo)
# do saving #
form.save()
return HttpResponseRedirect('/fetchvideodata')
I am new to django, so please bear If there is a silly mistake. I couldn't find a solution or tutorial that uses both mongoengine and django forms. Also I got error while specifying collection_name="thumbs",**kwargs in the model thumbnail_new = fields.ImageField(size=600,thumbnail_size=None).