I have a Django project that I'm trying to cobble together for a very basic survey that needs to be entered for demographic information. I've dummied up some data through the admin site in order to get my ListView working for the time being.
Unfortunately, I'm getting a strange response. I built the models.py to be a drop-down of a full spelled out and then to keep it small, I've made the actual storage in the db 1-3 characters. When I get my list view, one that uses 1 character to store for gender presents as (<django.db.models.fields.CharField>,), I would like for it to present as as the larger name of "Male", "Female", "Non-binary".
However, for my race and ethnicity fields which are 2 & 3 characters, those are returning as the actual storage for the DB (i.e, 'AA', 'NHP'). I'm more comfortable with SQL, so I'm not opposed to adding a table for a key as there would only be 11 entries for now, but it is possible that more things could be added down the line.
models.py:
from django.db import models
from django.contrib import admin
from django.contrib.auth.models import User
# Create your models here.
class StuData(models.Model):
id_num = models.IntegerField(primary_key=True)
entry_date = models.DateTimeField('Date of Entry')
MALE = 'm'
FEMALE = 'f'
OTHER = 'x'
GENUNK = 'u'
GENDER_SELECTIONS = [
(MALE,'Male'),
(FEMALE,'Female'),
(OTHER,'Non-Binary'),
(GENUNK,'Unknown'),
]
gender = models.CharField(max_length=1, choices=GENDER_SELECTIONS),
## Build the selections for the race field
AFR_RACE = 'AA'
ASI_RACE = 'AS'
WHI_RACE = 'WH'
UNK_RACE = 'UN'
RACE_SELECTIONS = [
(AFR_RACE, 'African-American'),
(ASI_RACE, 'Asian/Pacific Islander'),
(WHI_RACE, 'White'),
(UNK_RACE, 'Unknown Race'),
]
race = models.CharField(max_length=2, choices=RACE_SELECTIONS)
## Build the selections for the ethnicity field
HSP = 'HIS'
NHP = 'NHP'
UNK = 'UNE'
ETHNICITY_SELECTIONS = [
(HSP, 'Hispanic Origin'),
(NHP, 'Not of Hispanic Origin'),
(UNK, 'Unknown Ethnicity'),
]
ethnicity = models.CharField(max_length=10, choices=ETHNICITY_SELECTIONS)
stu_count = models.IntegerField(default=1)
user = models.ForeignKey(User, on_delete=models.CASCADE)
class Meta:
ordering = ["cad_num"]
def __str__(self):
return self.name
views.py:
from django.shortcuts import render
from django.http import HttpResponse
from mvstop.models import StuData
from django.views.generic.list import ListView
from django.views.generic.edit import UpdateView, CreateView
# Create your views here.
class StuDataList(ListView):
model = StuData
template = "myapp/studata_list.html"
fields = ""
paginate_by = 25
def Meta():
ordering = ['id_num']
def __str__(self):
return self.name
studata_list.html:
<!DOCTYPE html>
{% extends "./base.html" %}
{% block content %}
<h3>Most recent entries</h3>
<table id="studata">
<tr>
<th>ID Number</th>
<th>Entry Date</th>
<th>Gender</th>
<th>Race</th>
<th>Ethnicity</th>
<th>Count</th>
</tr>
{% for stu in studata_list %}
<tr>
<tr>
<td>{{ stu.id_num }}</td>
<td>{{ stu.entry_date }}</td>
<td>{{ stu.gender }}</td>
<td>{{ stu.race }}</td>
<td>{{ stu.ethnicity }}</td>
<td>{{ stu.occupants }}</td>
</tr>
{% endfor %}
</tr>
</table>
{% endblock %}
Django have build in method for that:
get_FIELD_display()
so in your template:
{% for stu in studata_list %}
<tr>
<tr>
<td>{{ stu.id_num }}</td>
<td>{{ stu.entry_date }}</td>
<td>{{ stu.get_gender_display }}</td>
<td>{{ stu.get_race_dispaly }}</td>
<td>{{ stu.get_ethnicity_display }}</td>
<td>{{ stu.occupants }}</td>
</tr>
{% endfor %}
Related
I am creating an app for a school schedule using Django. Admin users can currently add classes to a list. Student users can view that list but I want to create a button/link that will add that class object to a separate list that will act as their applied classes.
Models.py
class Class(models.Model):
def __str__(self):
return self.name
name = models.CharField(max_length=50)
crn = models.CharField(max_length=5, validators=[RegexValidator(r'^\d{1,10}$')])
grade_mode = models.CharField(max_length=50)
subject = models.CharField(max_length=3)
course_num = models.CharField(max_length=4, validators=[RegexValidator(r'^\d{1,10}$')])
section_num = models.CharField(max_length=3, validators=[RegexValidator(r'^\d{1,10}$')])
credit_hours = models.FloatField(validators=[MinValueValidator(0.0), MaxValueValidator(5.000)])
teacher = models.CharField(max_length=50)
Views.py
#login_required
#dec.student_required
def index(request):
class_list = Class.objects.all().order_by("-name")
# Allow for Posting of New Classes to Schedule.
if request.method == "POST":
form = ClassesForm(request.POST)
if form.is_valid():
form.save()
form = ClassesForm()
messages.success(request, "Class Added to Registry!")
else:
form = ClassesForm()
context_dict = {'classes': class_list,
'form': form}
return render(request, 'index.html', context=context_dict)
Index.HTML Add Button
<table>
<tbody>
{% if classes %}
{% for class in classes %}
<tr>
<td>Class Name: </td>
<td>Subject: </td>
<td>CRN: </td>
<td>Course Number: </td>
<td>Section Number: </td>
<td>Credit Hours: </td>
<td>Teacher: </td>
<td>Grade Mode: </td>
<td>Add Class</td>
</tr>
<tr>
<td>{{ class.name }}</td>
<td>{{ class.subject }}</td>
<td>{{ class.crn }}</td>
<td>{{ class.course_num }}</td>
<td>{{ class.section_num }}</td>
<td>{{ class.credit_hours }}</td>
<td>{{ class.teacher }}</td>
<td>{{ class.grade_mode }}</td>
<td>
<form method="GET">
{% csrf_token %}
<button class="addToSchedule" type="submit" value="add" name="Add Class">
Add Class
</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
{% else %}
<strong>There are no classes added.</strong>
{% endif %}
</table>
Image on Website.
So far I can print out the models on their own separate list as shown above but I don't know where to go in regards to the button or if a button is even the correct way of doing it. I want to click on a button and that model will be added and saved to the Added Classes section above.
I am making a hotell-page, and have made models for bookings and rooms.
I want to display the bookings related to a room in a table, and have the related bookings laying under the spesific room.
I show the code from the views.py file here:
def vaskehjelp(response):
available_rooms = Room.objects.filter(available=True)
room_nums = []
context = {}
for room in available_rooms:
related_bookings = Booking.objects.filter(room=room)
if related_bookings:
room_nums.append(room.room_no)
context[room.room_no] = related_bookings
context["room_nums"] = room_nums
context["available_rooms"] = available_rooms
print(context)
return render(response, "../templates/se_vaskbare_rom.html", context)
and the code from my template file here:
<table class="table table-striped table-dark">
<tr class="thead-dark">
<th scope="col">Room No.</th>
<th scope="col">Capacity</th>
<th scope="col">Room Type</th>
</tr>
{% for item in available_rooms %}
<tr scope="row">
<td>{{ item.room_no }}</td>
<td>{{ item.capacity }}</td>
<td>{{ item.room_type }}</td>
</tr>
{% if item.room_no in room_nums %}
{% for booking in item.room_no %}
<h1></h1>
<tr scope="row">
<td>{{ booking.cin_date }}</td>
<td>ku</td>
<td>{{ booking.cout_date }}</td>
</tr>
{% endfor %}
{% endif %}
{% endfor %}
</table>
The problem is that the booking-element in the template code doesent seem to work. I dont manage to access the lists of bookings related to the current selected room. As you see i have an outer for loop to iterate over the rooms, and then the inner for loop iterate over the related bookings (only in case that room is in the "room_nums" list. The problem is (i think) that the for booking in item.room_no doesnt work, i dont get any info from the booking variable at least...
In the table i should have had the check in and check out dates in the left and right column, but i dont get this information from the booking variable...
ps: the idea is that item.room_no is referrering to a list in the context dictionary. I have tried other things, but this is the closest i have come.
Here are the models:
class Room(models.Model):
room_choices = [('S', 'Single Occupancy'), ('D', 'Double Occupancy'), ('F', 'Firemannsrom')]
room_no = models.CharField(max_length=5) # primary key
available = models.BooleanField(default=False)
capacity = models.IntegerField(default=None)
room_type = models.CharField(choices=room_choices, max_length=1, default=None)
price = models.IntegerField( blank=True, null=True)
def __str__(self):
return "Romnr: " + str(self.room_no) + " -- type:" + str(self.room_type)
and
class Booking(models.Model):
#defaultRom = Room.objects.get(room_no='100')
#defaultRomID = defaultRom.id
room_choices = [('S', 'Single Occupancy'), ('D', 'Double Occupancy'), ('F', 'Firemannsrom')]
bookingid = models.AutoField(db_column='BookingID', primary_key=True) # Field name made lowercase.
guest = models.ForeignKey('auth.User', on_delete=models.CASCADE) # eller settings.AUTH_USER_MODEL
cin_date = models.DateField(db_column='CIN_Date', blank=True, null=True,
verbose_name='Check-In Date') # Field name made lowercase.
cout_date = models.DateField(db_column='COUT_Date', blank=True, null=True,
verbose_name='Check-Out Date') # Field name made lowercase.
room_type = models.CharField(choices=room_choices, max_length=1, default=None)
room = models.ForeignKey('Room', on_delete=models.CASCADE, db_column='Room', default=None)
class Meta:
managed = True
db_table = 'Booking'
def __str__(self):
return "Bruker: " + self.guest.__str__() + " -- id:" + str(self.bookingid) + " -- Inndato: " + self.cin_date.__str__() + " -- Utdato: " + self.cout_date.__str__() + " -- " + self.room.__str__()
Here is the the result of print(context):
{'100': <QuerySet [<Booking: Bruker: email -- id:27 -- Inndato: 2020-03-27 -- Utdato: 2020-03-29 -- Romnr: 100 -- type:S>]>, '103': <QuerySet [<Booking: Bruker: olaNordmann -- id:26 -- Inndato: 2020-03-07 -- Utdato: 2020-03-15 -- Romnr: 103 -- type:D>]>, 'room_nums': ['100', '103'], 'available_rooms': <QuerySet [<Room: Romnr: 100 -- type:S>, <Room: Romnr: 103 -- type:D>, <Room: Romnr: 106 -- type:F>, <Room: Romnr: 101 -- type:S>]>}
Thanks in advance!
You are referencing to CharField defined in Room class instead of Booking queryset
a quick solution might be to change the code in a following way:
{% for booking in item.related_bookings %}
<h1></h1>
<tr scope="row">
<td>{{ booking.cin_date }}</td>
<td>ku</td>
<td>{{ booking.cout_date }}</td>
</tr>
{% endfor %}
def vaskehjelp(response):
available_rooms = Room.objects.filter(available=True)
context = {}
for room in available_rooms:
related_bookings = Booking.objects.filter(room=room)
if related_bookings:
room_nums.append(room.room_no)
room.related_bookings = related_bookings
context["room_nums"] = room_nums
context["available_rooms"] = available_rooms
print(context)
return render(response, "../templates/se_vaskbare_rom.html", context)
But I believe that the easiest solution is the following one:
def vaskehjelp(response):
context = {}
available_rooms = Room.objects.filter(available=True).prefetch_related('Room')
context["available_rooms"] = available_rooms
return render(response, "../templates/se_vaskbare_rom.html", context)
{% for item in available_rooms %}
<tr scope="row">
<td>{{ item.room_no }}</td>
<td>{{ item.capacity }}</td>
<td>{{ item.room_type }}</td>
</tr>
{% for booking in item.Room %}
<h1></h1>
<tr scope="row">
<td>{{ booking.cin_date }}</td>
<td>ku</td>
<td>{{ booking.cout_date }}</td>
</tr>
{% endfor %}
{% endfor %}
i'm pretty new to django and i'm struggling with models and database but i managed to get some stuff right but this here isnt working out for me.
so basically what i want to do is when i click on a course it shows me a table with the students who are registered to this course but i keep getting an empty table
models.py
from django.db import models
from django.contrib.auth import get_user_model
from django.urls import reverse
from django.utils.text import slugify
User = get_user_model()
# Create your models here
class student (models.Model):
S_id = models.IntegerField(unique=True)
S_fname = models.CharField(max_length=255)
S_lname = models.CharField(max_length=255)
def __str__(self):
return self.S_id
class classes(models.Model):
C_id = models.CharField(max_length=255,unique=True)
C_name = models.CharField(max_length=255)
C_room = models.CharField(max_length=255)
Start_time = models.CharField(max_length=255)
Instructs = models.ManyToManyField(User, through='Teaches')
Registered = models.ManyToManyField(student, through='Registered')
slug = models.SlugField(allow_unicode=True, unique=True)
def __str__(self):
return self.C_id
def save(self,*args,**kwargs):
self.slug = slugify(self.C_id)
super().save(*args,**kwargs)
def get_absolute_url(self):
return reverse('classes:single',kwargs={'slug':self.slug})
class Meta:
ordering = ['C_name']
class Teaches(models.Model):
Instructor = models.ForeignKey(User, related_name='St_id', on_delete=models.CASCADE)
Course = models.ForeignKey(classes, related_name='Co_id', on_delete=models.CASCADE)
class Registered(models.Model):
Student = models.ForeignKey(student, related_name='Stu_id', on_delete=models.CASCADE)
Course = models.ForeignKey(classes, related_name='Cou_id', on_delete=models.CASCADE)
classes_detail.html
{% extends "classes/classes_base.html" %} {% block pregroup %}
<div class="container">
<h1>{{classes.C_name}}</h1>
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th>Student ID</th>
<th>Student First Name</th>
<th>Student Last Name</th>
<th>attendance</th>
</tr>
</thead>
<tbody>
{% for student in object_list %}
{% if student in classes.Registered.all %}
<tr class="">
<td>{{ student.S_id }}</td>
<td>{{ student.S_fname }}</td>
<td>{{ student.S_lname }}</td>
<td></td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endblock pregroup %}
views.py
from django.shortcuts import render
from django.contrib.auth.mixins import LoginRequiredMixin,PermissionRequiredMixin
from django.shortcuts import get_object_or_404
from django.urls import reverse
from django.views import generic
from .models import classes,Teaches
from django.contrib import messages
# Create your views here.
class ListClasses(generic.ListView):
model = classes
class SingleClass(generic.DetailView):
model = classes
This is what your classes details template should look like:
{% for student in object.Registered.all %}
<tr class="">
<td>{{ student.S_id }}</td>
<td>{{ student.S_fname }}</td>
<td>{{ student.S_lname }}</td>
<td></td>
</tr>
{% endfor %}
In the code below the inner forloop is not working
<tbody>
{% for rec in medrec %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ rec.date }}</td>
<td>{{ rec.disease }}</td>
<td>{{ rec.treatment }}</td>
<td> {% for n in medicine.forloop.parentforloop.counter0 %}
{{ n.medicine }}
{% endfor %}
</td>
</tr>
{% endfor %}
</tbody>
The code above generates a table. Each rec has a array of medicines.
Like for the rec.forloop.counter where forloop.counter == 1 there will objects in the medicine array index [0].
How do i print it?
def profile(request,rid):
patient = Patient.objects.get(pk=rid)
medic = MedicalRec.objects.filter(patient=patient)
i=0
a=[]
for n in medic:
a.append(medicine.objects.filter(Rec= n))
print(a)
if patient:
return render(request,'patient.html',{
'medrec' : medic,
'pat' : patient,
'medicine' : a
})
else:
return 'patient not found'
Models
from django.db import models
# Create your models here.
class Patient(models.Model):
name = models.CharField(max_length=100)
age = models.IntegerField()
address = models.TextField()
contact = models.CharField(max_length=15)
def __str__(self):
return self.name
class Stock(models.Model):
name = models.CharField(max_length=100)
quantity = models.IntegerField()
expiry = models.DateField()
price = models.IntegerField()
def __str__(self):
return self.name
class MedicalRec(models.Model):
patient = models.ForeignKey(Patient)
date = models.DateField()
disease = models.TextField()
treatment = models.TextField()
medicine = models.ForeignKey(Stock)
def __str__(self):
return str(self.date)
class medicine(models.Model):
Rec = models.ForeignKey(MedicalRec,related_name='med_set')
medicine = models.ForeignKey(Stock)
def __str__(self):
return str(self.Rec.date)
class Billing(models.Model):
name = models.ForeignKey(Stock)
rate = models.IntegerField()
Date = models.DateField()
def __str__(self):
return self.id
You don't have to create the list yourself. Django creates a reverse relation for you. It will be named medicine_set, but now that you're showing your models you have overridden it to be med_set. So you do not have to create a list in your view. You can use the related manager in your template:
view:
def profile(request, rid):
patient = get_object_or_404(Patient, pk=rid)
medic = MedicalRec.objects.filter(patient=patient)
return render(request, 'patient.html', {
'pat': patient,
'medrec': medic,
})
Template:
<tbody>
{% for rec in medrec %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ rec.date }}</td>
<td>{{ rec.disease }}</td>
<td>{{ rec.treatment }}</td>
<td>
{% for medicine in medrec.med_set.all %}
{{ medicine }}
{% endfor %}
</td>
</tr>
{% endfor %}
</tbody>
I modified melvyn's answer and it worked
<tbody>
{% for rec in medrec %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ rec.date }}</td>
<td>{{ rec.disease }}</td>
<td>{{ rec.treatment }}</td>
<td>
{% for medicine in rec.med_set.all %}
{{ medicine.medicine }},
{% endfor %}
</td>
</tr>
{% endfor %}
</tbody>
I have two forms in my views, when I hit on save it's not working properly, when I want to display on my templates what I saved not showing as expected.
Here's what I have:
views.py
def index(request):
queryset = Personinfo.objects.all()
queryset2 = Person.objects.all()
qs = chain(queryset,queryset2)
form = personform(request.POST or None)
form2 = personinfoform(request.POST or None)
context = {
"queryset": queryset,
"queryset2": queryset2,
"qs": qs,
"form2":form2,
"form":form,
}
form2_valid = form2.is_valid()
form_valid = form.is_valid()
if form2_valid and form_valid:
a = form2.save()
b= form.save(commit=False)
b.ForeignkeytoA = a
b.save()
return render(request, "index.html", context)
index.html
<form method="POST" action="">{% csrf_token %}
{{form2.as_p}}
{{form.as_p}}
<input type="submit" value="Save!" />
</form>
<table >
<tr>
<th>Name</th>
<th>Address</th>
<th>Number</th>
<th>Hobbies</th>
</tr>
{% for item in qs %}
<tr>
<td>{{ item.name }}</td> #form2
<td>{{ item.address }}</td> #form1
<td>{{ item.phone_number }}</td> #form1
<td>{{ item.address }}</td> #form1
</tr>
{% endfor %}
</table>
models.py
class Personinfo(models.Model):
name = models.CharField(max_length=128)
def __str__(self):
return self.name
class Person(models.Model):
person = models.ForeignKey(Personinfo)
address = models.TextField()
phone_number = models.CharField(max_length=128)
hobbies =models.CharField(max_length=128)
def __str__(self):
return self.person
my output:
As you can see my table isn't showing my items as expected.
Is there a possible way to show every item in the same row?
Two errors are present. If I understand right, you're expecting the data from a Person instance and the data from its accompanying PersonInfo instance to print on the same line. However, you're trying to achieve this by using chain, which is not joining the querysets based on their relationship, but rather concatenating them blindly.
So if Person.objects.all() returns a queryset which contains the following data
id person address phone_number hobbies
1 1 a a a
2 2 5 5 5
and PersonInfo.objects.all() returns a queryset which contains
id Name
1 aaa
2 aa
chain combines them as
id person name address phone_number hobbies
1 aaa
2 aa
1 1 a a a
2 2 5 5 5
Instead, you should utilize the relationship between the models. If you pass only the Person queryset as context to your template, you could write
{% for p in persons %}
<tr>
<td>{{ p.person.name }}</td>
<td>{{ p.address }}</td>
<td>{{ p.phone_number }}</td>
<td>{{ p.hobbies }}</td>
</tr>
{% endfor %}
--
Additionally you are setting the Personinfo related instance incorrectly when you save your forms. By using b.ForeignkeytoA you are creating a new variable as a member of the object b called ForeignkeytoA, which has nothing to do with the Personinfo relationship. To set the related Personinfo, you should reference the name of the foreign key field, person. To correct this, that segment should be
# ...
b = form.save(commit = False)
b.person = a
b.save()
# ...