Django admin ManyToManyField: improving usability on change_form? - django

I have Django models as follows:
class Subject(models.Model):
name = models.CharField(max_length=35, unique=True)
class Book(models.Model):
title = models.CharField(max_length=400)
subject = models.ManyToManyField(Subject, related_name='books', blank=True, verbose_name="Subject")
There are many Subjects - around 100.
When editing a Book record on the Django admin, it is very difficult to see which subjects are present on a particular book.
The Django admin offers a multi-select list, which is great, but to see for a book, you have to scroll through the entire select list.
It would be much better if either:
I could offer a read-only list of the subjects above the multi-select list, or
the multi-select list began with the selected subjects, then had an entry like '----', then continued with the other subjects.
Does anyone have any idea how I could implement either of the above in Django, to improve the usability of ManyToManyFields in the Django admin?
Thanks!

Use filter_horizontal (or filter_vertical).

Related

Django model foreignkey or charfield?

Django Model and Form that I want to make
Hello. I'm fairly new to Django and I have a hard time understanding which model field to use. I didn't post any code because my code is so messy right now and most of it still following "Django for Beginner" book by William S. Vincent.
I have an app consisting 2 models, Product model and Production model. Some fields on production model are linked to product model. Then from production model, I make a form for user input using ModelForm. (There's a link to an image to help understanding model and form relation.)
I have several questions regarding this matter.
If I set product_id on Production Model as ForeignKey to Product, what field should I use for product_name and material?
When I use CharField for both product_name and material, there are entry for both product_name and material on form and I don't want that. How to change it to readonly and have value updated based on product_id? (I'm not sure if this is related to Django form or not.)
Right now I'm using ModelForm to make Production form and then using FormView to render the form. Is it the right approach? What is the difference between this one and CreateView from model?
Thank you in advance for any comments and answers.
If you have a name and a material on the product model, you don't need those on the production model unless they relate to the production object. If I were you, I'd have a foreign key on Production to the product. It might look something like;
class Production(models.Model):
product = models.ForeignKey(
to=Product,
verbose_name=_("Product"),
on_delete=models.CASCADE
)
machine = models.CharField(
verbose_name=_("Machine No"),
max_length=255
)
date = models.DateTimeField(
verbose_name=_("Date"),
blank=True,
null=True
)
Then your form might be;
class ProductionForm(forms.ModelForm):
class Meta:
model = Production
fields = (
'product',
'machine',
'date',
)
I would recommend using the django admin to get your models as you want them before you start working with views. If you know the data is being stored in a way you need, then you can worry about building the frontend. The admin is around page 70 of that book you've got. You can also do readonly fields with that.

How to best create connections for a booking app?

I am new to Django and relational databases coming from the Firebase world. I am having trouble figuring out the best modeling for a Doctor-Patient booking app and generally how relational DBS works best; I would like to minimize future problems by doing a great job now. I am going to use Django and Django Rest Framework at the backend to feed a React frontend.
So far, I've created these models in a clinic app. Patients and Secretaries are going to be part of the users, and so are Doctors. I then create the Serializers and Viewsets for the API.
class Clinic(models.Model):
name = models.CharField(max_length=200)
description = models.TextField()
accepted = models.BooleanField(default=False)
class Doctor(models.Model):
clinic = models.ManyToManyField(
Clinic, related_name="doctor")
first_name = models.CharField(max_length=200)
last_name = models.CharField(max_length=200)
email = models.EmailField(max_length=240, default="email")
appointment_duration = models.IntegerField(default=20)
class Secretary(models.Model):
clinic = models.ForeignKey(
Clinic, on_delete=models.CASCADE, related_name="secretary")
name = models.CharField(max_length=200)
email = models.EmailField(max_length=240, default="email")
doctors_responsible_for = models.ManyToManyField(Doctor)
class Patient(models.Model):
first_name = models.CharField(max_length=200)
last_name = models.CharField(max_length=200)
email = models.EmailField(max_length=240, default="email")
date_of_birth = models.DateField()
age = models.PositiveIntegerField(default=0)
Should I create a User model to be able to differentiate users (Doctors, Secretaries and Patients)? They are all going to be able to register and log in and each will see different things on the page. Should I just return 'is_doctor' or 'is_secretary' from the serializer API and show different content from there?
I'm confused as to how I would connect a User model with a Doctor or Secretary model, for example, or if I even need to since they're all users...
How would I differentiate users (Doctor, Secretary, Patient) at the registration moment? E.g., for each of them to have a different registration form with a boolean for is_doctor, is_secretary?
I can't to come up with a solution for storing booked appointments. I'm wondering if I should create a new model, Bookings, for saving bookings but I'm not sure if this booking model should hold every single booking (from any patient to any doctor), considering this app will be used by a lot of people. Or should bookings be under each patient and each doctor?
In this case, secretaries will also be able to manually add bookings to a Doctor calendar and add the patient as well.
I am building all of this in a single app, clinic, perhaps it is recommended to create different apps for this?
Each doctor will need to have its own calendar for this app to work, with say, 'day 12, blocks of 20mins from 09:00 to 11:30'. Should I create a Calendar model? Or how is it best to achieve this? How to best come up with this model? This calendar will be populated with blocks of time from whatever each doctor chooses as their availability.
First of all, I'm a django noob, so please read the following with that it mind.
Looks pretty good - the only thing I see missing is how you link patients to clinics and or doctors.
The other thing I notice is how doctors can have multiple clinics. I assume each clinic has its own calender, rather the doctor itself? Or maybe both? i.e. Even if a doctor was available on his calendar, he might not have a room at the clinic for the patient as other doctors' calenders would clash with it.
Personally, I wouldn't create a new app for clinic unless you want to model it in far more detail. Keep it simple initially.
Also, if you're allowing doctors, secretaries, and patients to login to your site, it might be better to have consumer/provider class model descending from custom user. ideas...
I would start thinking about the problem in more abstract terms. Service/provider/consumer.
But, I think you're on the right track.
I can throw in some ideas.
Models
I think you are on the right track. You just need to associate models Doctor, Secretary and Patient to the User model. I would recommend you to create a custom user model inherited from AbstractUser.
In this model, you can either add a choice field with choices for each type of user. link to docs
Also, you need to link the user model with the correct model.
One way to do is to have a OneToOneField for the user model in all your user type models: Doctor, Secretary, Patient
Or you can explore generic relations. It will further streamline things for you. link to docs.
Signup
You can provide a field for users to select at the time of signup, or provide separate links to signup and handle things at the backend. Something like If you are a doctor, click here to signup. In both cases, you'll need to override the signup process.
So a signup link can look like: /signup/doctor/ or /signup/patient/. All signup will be using the same view, just different url kwargs. link to docs
You can just create rows on the relevant model for user type on form success.
Booking
Yes, you need to create a separate model, and you can store all your bookings in this model. Doesn't matter how many users use your app. Just use a good database solution, like Postgres. There are ways to optimize your queries, like indexing, don't worry about it for now. Just make sure to save all references like, patient, doctor, created, last modified, created by which user, from_datetime, to_datetime, etc.
It would be better to handle the 20 min appointment blocks in forms.py.
You can create a list of acceptable time blocks, so that if in future you want to change this time to say 30 min, its easily doable. Just handle all validations at the form level and it should do the trick.

How to get existing values from the database into the django model field for django admin

I need help to get existing questions from the field question_name into the field dependent_question (with dropdown) from the Questions model class. It will help user to select dependent question when they add any new question from django admin panel.
# model.py
class Questions(models.Model):
question_id = models.AutoField(primary_key=True)
question_name = models.CharField(max_length=300)
dependent_question = models.CharField(max_length=300,blank=True, null=True)
Take a look at this post: https://simpleisbetterthancomplex.com/tutorial/2018/01/29/how-to-implement-dependent-or-chained-dropdown-list-with-django.html
It shows you how to achieve that using javascript. I have done this, and it works great.

How to fill a field with pre-defined options in the admin page

I'm new to Django and to learn it I'm trying to create a news-like site, where the news-posts are written in the admin page. To achieve this I created a model called Post, and, among other things, I want it to store the post genre. Therefore I made a variable called genre which equals models.CharField() method. The problem with this approach is that in the admin page I have to write the post genre every time, when instead I'd like to choose the genre from a set of pre-defined genres. How can I achieve this functionality in the admin page?
Add a tuple of choices to your field and it will show up as a select widget in the admin.
class Post(models.Model):
GENRE_CHOICES = (
('movie', 'Movie'),
('music', 'Music'),
)
genre = models.CharField(max_length=255, choices=GENRE_CHOICES)

"One-Off" Editable field Django Admin

I am creating an intranet with Django and I would like to make certain unique parts of the site editable (welcome message, mission statement, etc) from the built-in admin interface.
I currently have a model that houses these "unique" sections:
def Section(models.Model):
title = models.CharField(max_length=100)
body = models.TextField()
def __unicode__(self):
return self.title
then I make explicit template calls that pulls out the appropriate section. This works, but an admin could add more content to this model that wont show up and this could be confusing and is undesirable.
Is there a more elegant solution?
Have you tried a pluggable Django CMS app? I would suggest django-cms or django-flatblocks. Both can do what you are looking for. Flatblocks is a simpler system and quick to implementation while django-cms is more involved (comparatively) but has a lot more features/ functionality.