class Question(models.Model):
"""This class represents a question. It can have 2 or more options."""
created_on = models.DateTimeField(auto_now_add = 1)
title = models.CharField(max_length = 200)
slug = models.SlugField(unique = True, max_length = 200)
class Choice(models.Model):
"""This represents an answer to the Question, and has a foreignkey to it"""
question = models.ForeignKey(Question)
text = models.TextField()
total_votes = models.IntegerField(default = 0)
I want query last question and it's choice Im try but can't get last as form
to get the last item you can do something like:
q = Question.objects.order_by('id').reverse()[0]
and to get the choices:
choices = q.choice_set.all()
To sum-up, this is how your view should look like:
def last_q(request):
return render_to_response('poll/last.html', { 'last_q': Question.objects.order_by('id').reverse()[0] } )
and this is your template:
{% for c in last_q.choice_set.all %}
<input type="radio" name="choice" value="{{ c.id }}" />{{ c.text }}
{% endfor %}
something like that!
Related
My views.py file is
def studentFeedBack(request):
studentid = ''
courseid = ''
teacherid = ''
if request.method == 'POST':
studentid_id = request.POST.get("studentid")
studentid = studentid.objects.get(id=studentid_id)
courseid_id = request.POST.get("courseid")
courseid = courseid.objects.get(id=courseid_id)
teacherid_id = request.POST.get("teacherid")
teacherid = teacherid.objects.get(id=teacherid_id)
description = request.POST.get("description")
rating = request.POST.get("rating")
studentFeedBack.objects.create(
courseid=courseid,
description=description,
studentid=studentid,
teacherid=teacherid,
rating=rating
)
return render(
request,
'forms/studentFeedBack.html',
{
'studentids':studentid.objects.all(),
'courseids':courseid.objects.all(),
'teacherids':teacherid.objects.all(),
}
)
and my models.py file 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')
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')
createddate = models.DateTimeField()
imagelink = models.URLField(default='default_link')
duration = models.DateTimeField()
longdes = models.TextField()
coursetype = models.CharField(max_length=50)
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()
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)
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"
and studentFeedBack html file has the following form
<form action="/studentFeedBack/" method="POST">
{% csrf_token %}
<label for="studentid">Student Id</label>
<!-- <input type="number" name="studentid"><br><br> -->
<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>
<input type="number" name="courseid"><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>
<!-- <input type="number" name="teacherid"><br><br> -->
<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>
The studentFeedBack model has foreign keys from student, schoolTeacher and Course. This is giving error on browser that 'str' object has no attribute 'objects'
Other than that my form is not giving any values in select options and that is also probably because of this error.
The design of the view is the issue
According to the line
studentid =''
studentid remains a string . You could try proper importation of the models.
Try:
views.py
from .models import Course, Student,schoolTeacher,studentFeedBack
def studentFeedBack(request):
#studentid = ''
#courseid = ''
#teacherid = ''
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")
studentFeedBack.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(),
}
)
Alternatively, Django is superb at handing forms for models
https://docs.djangoproject.com/en/3.1/topics/forms/modelforms/#modelform
This will be better for your view as there is no validation at the moment
You could also have:
views.py
...
from django.forms.models import modelform_factory
from .models import studentFeedBack
def studentFeedBack(request):
fields=[
'courseid','description','studentid','teacherid','rating']
form=modelform_factory(studentFeedBack, fields=fields)
if request.method == 'POST':
form=modelform_factory(studentFeedBack, fields=fields, data=request.POST)
## Validates the data submitted
if form.is_valid():
## Creates a studentFeedBack instance
form.save()
## If form is invalid, it will fall through to the template with the incorrect data.
else:
### Handle the incorrect form
pass
return render(
request,
'forms/studentFeedBack.html',
{
'studentids':Student.objects.all(),
'courseids':Course.objects.all(),
'teacherids':schoolTeacher.objects.all(),
'form':form,
}
)
forms/studentFeedBack.html
<form action="/studentFeedBack/" method="POST">
{% csrf_token %}
{{form.as_p}}
</form>
https://docs.djangoproject.com/en/3.1/topics/forms/#working-with-form-templates
You may need to add a verbose_name attribute to your model fields:
models.py
class StudentFeedBack(models.Model):
...
teacherid = models.ForeignKey('schoolTeacher', on_delete=models.CASCADE, verbose_name="Teacher")
...
https://docs.djangoproject.com/en/3.1/ref/models/fields/#verbose-name
Customize as needed.
I hope this helps you understand Django better.
Edit
The function-based view has the same name as an imported model
For the first view:
from .models import Course, Student,schoolTeacher
from .models import studentFeedBack as studentFeedBackModel
def studentFeedBack(request):
#studentid = ''
#courseid = ''
#teacherid = ''
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(),
}
)
I am trying to insert those value I got from radio buttons after the user as taken options. Then I want to insert it into another table which I will use to prepare the final result for the student. After I've taken all my values and created an insert query, I am getting this error.
models.py:
class Question(models.Model):
course = models.ForeignKey(Course, on_delete=models.CASCADE, related_name='questions')
text = models.CharField('Question', max_length=500)
def __str__(self):
return self.text
class Answer(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE, related_name='answers')
text = models.CharField('Answer', max_length=255)
is_correct = models.BooleanField('Correct answer', default=False)
def __str__(self):
return self.text
class TakenQuiz(models.Model):
student = models.ForeignKey(Student, on_delete=models.CASCADE, related_name='taken_quizzes')
course = models.ForeignKey(Course, on_delete=models.CASCADE, related_name='taken_course')
question = models.ForeignKey(Question, on_delete=models.CASCADE, related_name='taken_question')
selected_choice = models.ForeignKey(Answer, on_delete=models.CASCADE, null=True)
marks_obtained = models.DecimalField('Marks Obtained', default=0, decimal_places=2, max_digits=6)
is_correct = models.BooleanField('Was this attempt correct?', default=False, null=False)
date = models.DateTimeField(auto_now_add=True)
views.py:
#login_required
#student_required
def take_exam(request, pk):
course = get_object_or_404(Course, pk=pk)
student = request.user.student
question = course.questions.filter()
#correct_answers = student.course_answers.filter(answer__question__quiz=course, answer__is_correct=True).count()
total_questions = course.questions.count()
choice = Answer.objects.filter()
marks_obtainable = Details.objects.get(course_id=course)
if request.method == 'POST':
question_pk = request.POST.getlist('question_pk')
choice_pk = [request.POST['choice_pk{}'.format(q)] for q in question_pk]
zipped = zip(question_pk, choice_pk)
for x, y in zipped:
correct_answers = Answer.objects.filter(question_id=x, is_correct=True).values('id').first()['id']
#print(type(correct_answers))
#print(choice_pk)
print(x, y, correct_answers)
print(x, y, correct_answers)
if int(y) == correct_answers:
print("correct") #using this to comfirm the the conditional statement above
z = TakenQuiz.objects.create(student=student, question=int(x), course=course, mark_obtained=marks_obtainable, is_correct=True)
z.save()
takenquiz = TakenQuiz()
takenquiz.student = student
takenquiz.question = x
takenquiz.course = course
takenquiz.selected_choice = y
takenquiz.marks_obtained = marks_obtainable
takenquiz.is_correct = True
takenquiz.save()
else:
print("Not correct")
z = TakenQuiz.objects.create(student=student, question=x, course=course, mark_obtained=marks_obtainable, is_correct=False)
z.save()
return render(request, 'classroom/students/take_exam_form.html', {
'course': course,
'question': question,
'course': course,
'total_questions': total_questions,
'choice': choice,
'marks_obtainable': marks_obtainable,
})
take_exam_form.html:
<form method="post" novalidate>
{% csrf_token %}
{% for questions in question %}
<input type="hidden" name="question_pk" value="{{ questions.pk }}">
<h3 class="text-info">{{ questions.text|safe }}</h3>
{% for choices in questions.answers.all %}
<input class="form-check-input" type="radio" name="choice_pk{{ questions.pk }}" id="choices-{{ forloop.counter }}" value="{{ choices.pk }}">
<label class="form-check-label" for="choices-{{ forloop.counter }}">
{{ choices.text|safe }}
</label>
{% endfor %}
{% endfor %}
<button type="submit" class="btn btn-primary">Submit Now →</button>
</form>
question_pk = request.POST.getlist('question_pk')
question_obj = Question.objects.filter(id=int(question_pk)
while save
takenquiz.question = question_obj
I have these three models -- A "Thing" has an associated "Album", which contains typically three or four "Photo"s of the "Thing". For the latest nine "Thing"s, I want to display the first photo of the thing from the "Album", along with other details of the thing (e.g., name, country of manufacture) using a template called "headquarters.html".
The following are my models:
class Thing(models.Model):
name = models.CharField(verbose_name = "Item", max_length = 60)
price = models.DecimalField(max_digits = 5, decimal_places = 2)
country_of_manufacture = models.CharField(verbose_name = "Country of Manufacture", max_length = 40)
created_on = models.DateTimeField(verbose_name = "Creation Date", default = django.utils.timezone.now, editable = False)
album = models.OneToOneField(Album, on_delete = models.CASCADE, null = True)
def __str__(self):
return self.name
class Album(models.Model):
name = models.CharField(verbose_name = "Photo Album", max_length = 60)
created_on = models.DateTimeField(verbose_name = "Creation Date", default = django.utils.timezone.now, editable = False)
def __str__(self):
return self.name
class Photo(models.Model):
photo_identity = models.ImageField(blank = True, null = True, upload_to="media/%Y/%m/%d/")
photo_in = models.ForeignKey(Album, on_delete = models.PROTECT)
uploaded_on = models.DateTimeField(verbose_name = "Creation Date", default = django.utils.timezone.now, editable = False)
def __str__(self):
return '%s -- (%s)' % (self.photo_in.name + " Album", self.photo_identity)
This is my view.py:
def headquarters(request, *args, **kwargs):
last_nine = Thing.objects.all().order_by('-id')[:9]
mylist = []
for thing in last_nine:
mylist.append (thing.album.photo_set.first().photo_identity)
return render(request, 'headquarters.html', {"nine_items" : last_nine, "URL_list" : mylist})
This is my template (headquarters.html):
{% for item in nine_items %}
<div class="col-lg-4 col-sm-6 portfolio-item">
<div class="card h-100">
<img class="card-img-top" src="{{ **what_do_put_in_here** }}" alt="">
<div class="card-body">
<h4 class="card-title">
{{item.name}}
</h4>
<p class="card-text">Brand: {{item.brand}}</p>
<p class="card-text">Item ID: {{item.id}}</p>
<p class="card-text">Item price: {{item.price}}</p>
<p class="card-text">Made in {{item.country_of_manufacture}}</p>
</div>
</div>
</div>
{% endfor %}
I cant get the first photo from "Album" to display. Nothing comes out. I've tried various things over three days, but with no success. Any help is greatly appreciated. Thank you.
Sincerely,
CKLee
As is explained in the documentation [Django-doc], you can use the url attribute of the value that is associated with the ImageField, so:
<img class="card-img-top" src="{{ item.album.photo_set.first.photo_identity.url }}" alt="">
I have difficulties to work with 2 forms within one view. Here is my code and issue :
Model
class Process(models.Model):
name = models.CharField(max_length = 200)
order = models.IntegerField(
default=0,
validators=[
MinValueValidator(0)
]
)
status = models.BooleanField(default = True)
process_owner = models.CharField(max_length = 200)
created_by = models.CharField(max_length = 200)
created_at = models.DateTimeField(auto_now_add = True)
updated_at = models.DateTimeField(auto_now = True)
class SubProcess(models.Model):
process = models.ForeignKey(Process, on_delete=models.CASCADE)
next_sub_process = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=False)
name = models.CharField(max_length = 200)
status = models.BooleanField(default = True)
sub_process_owner = models.CharField(max_length = 200)
created_by = models.CharField(max_length = 200)
created_at = models.DateTimeField(auto_now_add = True)
updated_at = models.DateTimeField(auto_now = True)
Forms
class createProcessForm(ModelForm):
class Meta:
model = Process
fields = ['name', 'order',]
class createSubProcessForOneShotCreationForm(ModelForm):
class Meta:
model = SubProcess
fields = ['name',]
Template
<form action="{% url 'processmanagement:create_process_subProcess_step' %}" method="post">
{% csrf_token %}
<p>Process</p>
{{ form_process }}
<p>Sub Process</p>
{{ form_subProcess }}
<p></p>
<input type="submit" value="Submit" />
</form>
The view
def create_process_subProcess_step(request):
if request.method == 'POST':
form_process = createProcessForm(request.POST)
print('form_process : ' + str(form_process))
form_subProcess = createSubProcessForOneShotCreationForm(request.POST)
if form_process.is_valid() and form_subProcess.is_valid():
process_instance = form_process.save()
subProcess_instance = form_subProcess.save(commit=False)
subProcess_instance.process = process_instance
subProcess_instance.save()
return redirect('processmanagement:displayProcessAndSubProcess')
form_process = createProcessForm()
form_subProcess = createSubProcessForOneShotCreationForm()
context = {
'form_process' : form_process,
'form_subProcess' : form_subProcess
}
return render(request, 'processmanagement/create_process_subProcess_step', context)
When creating 2 forms within one view and saving those, it looks like the data related to the name from the second form is saved in DB in both first and second objects while the first form should populate the first object and the second form should populate the second object. e.g : in the web page, you validate : process name = A, subprocess name = B, in Db you get process name = B, subprocess name = B.
How should I handle that ?
MariaDb results
I went through different topics such as autocommit, cache issue, db issue (I have changed from SQLite to MariaDB) but nothing helped me.
You should use a prefix in your form instantiations so that the field names don't conflict.
I am passing the foreign key id in the values_list to the template and so my template can only show the id of the referenced object. I would like to get the actual object though without explicitly passing the fields.
models.py:
class Transaction(models.Model):
''' This class will host RBC raw data. '''
account_type = models.CharField(max_length = 20)
account_number = models.CharField(max_length = 20)
transaction_date = models.DateField()
cheque_number = models.CharField(max_length = 20, null = True, blank = True)
description_1 = models.CharField(max_length = 100, null = True, blank = True)
description_2 = models.CharField(max_length = 100, null = True, blank = True)
cad = models.DecimalField(max_digits = 10, decimal_places = 2, blank = True, null = True)
usd = models.DecimalField(max_digits = 10, decimal_places = 2, blank = True, null = True)
user = models.ForeignKey(settings.AUTH_USER_MODEL, blank = True, null = True, on_delete = models.PROTECT)
category = models.ForeignKey('BudgetCategory', blank = True, null = True, on_delete = models.PROTECT) # same as above comment
subcategory = models.ForeignKey('BudgetSubCategory', blank = True, null = True, on_delete = models.PROTECT) # Does not delete related sub-categories if a transaction is delted.
views.py:
transaction_fields = ['account_type', 'account_number', 'transaction_date', 'description_1', 'description_2','cad', 'category', 'subcategory']
field_order_by = ['category', 'subcategory', 'description_1', 'transaction_date']
class AllRecordsView(ListView):
template_name = 'index.html'
context_object_name = 'transactions'
fields = transaction_fields
field_order_by = field_order_by
def get_queryset(self, *args, **kwargs):
transactions = Transaction.objects.all().values_list(*self.fields).order_by(*field_order_by)
return transactions
def get_context_data(self, **kwargs):
context = super(AllRecordsView, self).get_context_data(**kwargs)
column_fields = fields_to_columns(self.fields) # returns the name of columns in capitalized form and changing underscore to space
context['fields'] = column_fields # Adding a context variable called field which hosts the column names list
return context
Template:
{% for transaction in transactions %}
<tr>
{% for field in transaction %}
<td> {{ field }} </td>
</tr>
In other words, I am trying to avoid passing all transaction objects and calling each field separately:
<tr>
{% for transaction in transactions %}
<td> {{ transaction.account_type }} </td>
...
<td>
{{ transaction.category.name }}
</td>
{% endfor %}
</tr>
Is there anyway that I can maintain code versatility and display the foreign key objects' attributes?
You can access traverse relationships by using the double underscore notation similar to how you do in a filter call. Such as:
Class A:
b = ForeignKey(B)
class B:
description = CharField()
A.objects.all().values_list('b__description')
So for yours it seems like you'd change transaction_fields to include a 'related_obj__field_needed' value in the list.