How to Use Foreign Keys in Django Models
Hello Everyone, today I will be simply building a simple Records and Schedule App for hospitals to store records of immunized patients, so it’s like a hospital e-registry system.
Sometimes, one has to build an app, that comprises of models that depend on one another, it can sometimes be complicated as a beginner using Django, this tutorial will help to make the process less difficult.
App Structural
Records Schedule App (models would include):
- Records (all records you have)
- Schedules (all the schedules for each record)
Templates
- add templates for records and schedules
To access the app source code visit the github link — source code
STEP 1
Using your command prompt ( I am using Linux)
mkdir ehospital_systempython3 –versionpip install pipenvpipenv shellpip install Djangodjango-admin startproject edit_hospitalcd edit_hospitalpython manage.py startapp hospital
STEP 2
add the app to settings.py
INSTALLED_APPS = [# my _app'hospital',# your app_name#....'django.contrib.admin',
STEP 3
In your models.py add Record models
# .. hospital/models.py
class Record(models.Model):
slug = models.SlugField() first_name = models.CharField(max_length = 200) last_name = models.CharField(max_length = 200) birth_date = models.DateTimeField() weight = models.CharField(max_length=10) height = models.CharField(max_length=10) parent_name = models.CharField(max_length=200) parent_mobile = models.CharField(max_length=16) home_address = models.CharField(max_length=300)
def __str__(self):
return self.first_name + " " + self.last_name
Also, add also the Schedule model in models.py
# .. hospital/models.py
class Schedule(models.Model):
slug = models.SlugField() date_immunized = models.DateTimeField() initial_date = models.DateTimeField() record = models.ForeignKey(Record, on_delete = models.SET_NULL, null =True) disease_type = models.CharField(max_length = 30) vaccine_type = models.CharField(max_length=30) position = models.IntegerField()
def __str__(self):
return self.vaccine_type + " for " + self.disease_type
STEP 4:
in your app views add
# .. hospital/views.pyclass RecordListView(ListView):
model = Recordclass RecordDetailView(DetailView):
model = Record
STEP 5:
create urls.py in the app: hospital/urls.py
# .. hospital/urls.pyfrom django.urls import pathfrom .views import RecordListView, RecordDetailView, ScheduleDetailViewapp_name = 'hospital'urlpatterns = [path('',RecordListView.as_view(), name='list' ),path('<slug>', RecordDetailView.as_view(), name="detail"),]
urls.py in your Django project
# ... edit_hospital/urls.py
from django.contrib import adminfrom django.urls import path, includeurlpatterns = [path('admin/', admin.site.urls),path('', include('hospital.urls', namespace = 'hospital')),]
Run app
python manage.py migrationspython manage.py migratepython manage.py createsuperuserpython manage.py runserver
STEP 6:
Templates
— inside the app make this folder, of app_name and create an HTML template (base.html it should look like this: hospital/base.html
# .. hospital/base.html<!doctype html><html lang="en"><head><!-- Required meta tags --><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"><!-- Bootstrap CSS --><link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous"><title>EHospital App</title></head><body class="container">{% block content %}{% endblock content %}<!-- Optional JavaScript --><!-- jQuery first, then Popper.js, then Bootstrap JS --><script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script><script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script><script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script></body></html>
…. templates/hospital/records_list.html >> this is the default template name for using the ListView in Django views
# ... hospital/records_list.html
{% extends 'hospital/base.html' %}{% block content %}<h1> Your Records Page</h1><br><ul class="list-group">{% for object in object_list %}<li class="list-group-item"><a href="{{ object.get_absolute_url }}">{{ object }}</a></li>{% endfor %}</ul>{% endblock %}
…. templates/hospital/records_detail.html >> this is the default template name for using the DetailView in Django views
# .. hospital/records_detail.html{% extends 'hospital/base.html' %}
{% block content %}<h1> Detail for a Record </h1><p>{{ object.first_name }}</p><p> {{ object.home_address}}</p><h3> Date Immunized (for vaccine)</h3>{% endblock %}
STEP 7:
add records to your Record model
go to URL — http://127.0.0.1:8000/
Before we start making use of our Schedule models you have to make some additions
For the detail go to http://127.0.0.1:8000/third
third: here is the slug, I added to it from the admin site while creating the record
STEP 8:
Now to link the schedule model to the model of the record, we add this under the Record model in models.py
the property helps to get all the schedules in the schedule model to the Record model
@propertydef schedules(self):return self.schedule_set.all().order_by('position')
STEP 9:
Now in your views.py add DetailView for the Schedule model.
this simply assigns Slug ( a short label for something) to the models
# ...class ScheduleDetailView(View):def get(self, request, record_slug, schedule_slug, *args, **kwargs):record_qs = Record.objects.filter(slug=record_slug)if record_qs.exists():record = record_qs.first()schedule_qs = record.schedules.filter(slug=schedule_slug)if schedule_qs.exists():schedule = schedule_qs.first()context = {'object' : schedule}return render(request, "hospital/schedule_detail.html", context)
STEP 10:
In your models.py again update the Schedule model
#.....def get_absolute_url(self):return reverse("hospital:record-detail", kwargs={'record_slug': self.record.slug,'schedule_slug':self.slug,})
STEP 11:
Then in your urls.py in your Django app update it, and add the ScheduleDetailView
#....hospital/urls.py
#...path('<record_slug>/<schedule_slug>/', ScheduleDetailView.as_view(), name="record-detail"),]
STEP 12:
Now create a template for the ScheduleDetailView,
templates/hospital/schedule_detail.html >> this is the default for Detailview in Django
{% extends 'hospital/base.html' %} {% block content %}<h3> Schedules For a Record</h3><h6> {{ object }}</h6>{% endblock%}
Lastly, we don’t need a ListView, for the Schedule model, cause it will be added in the same place as the Record detail page. So update your record detail template as
#.... hospital/record_detail.html
{% extends 'hospital/base.html' %}{% block content %}<h1> Detail for {{ object.first_name }} Record </h1><h5> Birth Date : {{object.birth_date}} </h5><h5> Weight : {{object.weight }}</h5><h5>Height : {{ object.height }}</h5><h5> Parents : {{ object.parent_name }} </h5><h5> Parent Mobile Number : {{ object.parent_mobile}}</h5><h5>Home Address : {{object.home_address}}</h5><br><table class="table table-striped"><thead><tr><th scope="col">#</th><th scope="col">Date Immunized</th><th scope="col">Vaccine Type</th><th scope="col">Disease Type</th></tr></thead><tbody>{% for schedule in object.schedules %}<tr><th scope="row">{{schedule.position}}</th><td> <a href="{{ schedule.get_absolute_url }}">{{ schedule.date_immunized }}</a></td><td> {{ schedule.vaccine_type }}</td><td> {{ schedule.disease_type }}</td></tr>
{% endfor%}</tbody></table>{% endblock %}
STEP 13:
Next, add Schedules for records in from your admin page
▲
Well Done.😉
Now You can add UpdateView to edit both models and do much other stuff…
I hope this was helpful
Having any errors or need to understand it, more follow this video guide from JustDjango, I got most if not all from it.