How to isolate detail data

In my Django app, I created three separate users: is_organizer, is_pharmacist or user. The organizer or the pharmacist has the access to perform basic CRUD operation, and see their data separately, their specific isolation works well in detail, and retrieve operations but it is not effective in performing the Update and CreateView operations as I wanted. What I want is that: (a). I would want the Foreignkeys parameter, e.g. patients which get prepopulated in the select-option icon by the MedicationHistoryCreateView to be totally isolated from the pharmacist and the organizer — I don’t want either of the user to see their previous input in the select-option icon of the patients. (b) I want the data from (a) to be ordered from the recent date and let the user’s first 5 patients selection field appear, not every entry at a time. I would want all the above changes/solutions to be applied in the MedicationHistoryUpdateView as well. Please I really need your help on this issue to get it resolved. Thanks.

Here are my code snippets, I don’t know what I am doing wrong, kindly help me out and fix it because I have run out ideas:

My model:

from songs.models.py

class User(AbstractUser):

    """ User model helps us gather users in our database and categorize
    their respective tasks in our organization. """
    is_organizer = models.BooleanField(
        default=False, verbose_name="is an organizer?")
  is_pharmacist = models.BooleanField(
        default=False, verbose_name=" is a pharmacist?")
     # other fields

from pharmcare.models.py


class PatientDetail(models.Model):

    class Meta:
        ordering = ['id', '-date_created']
    first_name = models.CharField(max_length=20, validators=[NAME_REGEX])
    # other fields

class MedicationHistory(models.Model):
    """ A model that handles all our patients detail medical history """
    user = models.ForeignKey('songs.User', on_delete=models.CASCADE)
    patients = models.ForeignKey(
        'PatientDetail', on_delete=models.CASCADE,
        verbose_name='Patient-detail')
    pharmacist = models.ForeignKey(
        "Pharmacist", on_delete=models.SET_NULL, null=True, blank=True)
    organization = models.ForeignKey(
        'leads.UserProfile', on_delete=models.CASCADE)    
    vital_signs = models.TextField()
    date_created = models.DateTimeField(auto_now_add=True)
     # other fields

my Views.py:

class MedicationHistoryCreateView(OrganizerPharmacistLoginRequiredMixin,
                                  CreateView):
    """ View responsible to display patient's medication history create medication records 
    if the admin/pharmacists wants. """

    template_name = 'pharmcare/medication_history/medication-history-create.html'
    form_class = MedicationHistoryForm

    def get_queryset(self):

        organization = self.request.user.userprofile
        user = self.request.user
        if user.is_organizer or user.is_pharmacist:
            queryset = MedicationHistory.objects.filter(
                organization=organization)
        else:
            queryset = MedicationHistory.objects.filter(
                pharmacist=user.pharmacist.organization
            )
            queryset = queryset.filter(pharmacist__user=user)

        return queryset.order_by('-date_created')

    def form_valid(self, form: BaseModelForm) -> HttpResponse:

        user = self.request.user

        form = form.save(commit=False)
        form.user = user
        form.organization = user.userprofile
        form.organization = user.pharmacist.organization
        form.save()
        return super(MedicationHistoryCreateView, self).form_valid(form)

    def get_success_url(self) -> str:
        messages.success(self.request,
                         "The patient's medication history was successfully created!")
        return reverse('pharmcare:medication-history')

# Update View:
class MedicationHistoryUpdateView(OrganizerPharmacistLoginRequiredMixin,
                                  UpdateView):
   
    form_class = MedicationHistoryForm
    template_name = 'pharmcare/medication_history/medication-history-update.html'
    context_object_name = 'med_history'

    def get_queryset(self):

        organization = self.request.user.userprofile
        user = self.request.user
        if user.is_organizer or user.is_pharmacist:
            queryset = MedicationHistory.objects.filter(
                organization=organization)
        else:
            queryset = MedicationHistory.objects.filter(
                pharmacist=user.pharmacist.organization
            )
            queryset = queryset.filter(pharmacist__user=user)

        return queryset.order_by('-date_created')

My Form:

class MedicationHistoryForm(forms.ModelForm):
    """ patients form for medication history """

    class Meta:
        model = MedicationHistory
        ordering = "-date_created"

        fields = [
            'vital_signs',
            'patients',

           # other fields
          
        ]

Thank you so much.

Rewording this to see if I understand what you’re looking to do:

(a) The MedicationHistoryForm has a field, patients, which is a ForeignKey field in the MedicationHistory model referencing the PatientDetail model. You want some instances of PatientDetail to not be included.

You wrote:

Please clarify which rows you want excluded. What determines whether an instance of PatientDetail fits into this category?

(b) You want the data to be ordered by date.

What data? What “user”? What defines “first 5 patients”?

I don’t want either of the users to see their previous input in the select-option icon of the patients → what I meant by the statement is that each user — organizer or pharmacist, should only see their isolated select-option icon of the patient form field respectively (at a time) because write now in my app, the pharmacist, for example, Bruno, if he creates a patientDetail instance, the organizer, for example, Blaise, will be able to see the field he created, and vice-versa. I don’t want that.

The row I would like to exclude/filter out is the patient rows that get mixed with what the organizer and pharmacist (users) created separately. In the model above, I added the pharmacist and organization as a Foreignkey, and each instance including the patientDetail is linked to them as their respective category. In the views.py above, you can see I used organization and pharmacist object (params) to filter them out, however, the underlying issue I stated in the first paragraph persists.

b) The data I want to be ordered by date sir, is the patients —which is part of the field from the MedicationHistoryForm class above.

c) the user - is organizer or pharmacist and I just want the 5 patients’ list field to be prepopulated to be Limit to 5.

Thank you!

Continuing to try and expand on this.

You wrote:

Are you saying that if Bruno creates a PatientDetail, then Blaise cannot assign a MedicationHistory to that Patient?

How do you “know” that Bruno has created the PatientDetail instance?

Which “field” are you talking about? (Or are you referencing a complete instance of something?)

It’s still not clear what operations you’re looking to perform on which objects, or what the constraints are on those object. Also, you’re now introducing an additional set of constraints by starting to talk about individual names as opposed to the “organizer” / “pharmacist” / “user” roles at the beginning. Are these filters to be applied by individual pharmacist or by the role?

Let me try rephrasing it this way -

You have a view, MedicationHistoryCreateView creating an instance of MedicationHistory. The MedicationHistoryForm contains the patients field, which is a reference to PatientDetail.

The only instances of PatientDetail that you want shown, are those only the instances created by:

  • The same person?
    or
  • The same role?

What information do I have in the PatientDetail to identify which person or role created that instance?

Exactly!

The business logic concept is more of the organizer, who owns the business, creates a userprofile instance of the pharmacist - which is the organizer’s role, invites them to log in, and once they do, the pharmacist → takes a full privilege of what the organizer can access in the pharmcare app - i.e. automatically can perform full CRUD operation independently without the organizer assigning any task to him/her. Thus, once is_pharmacist is set to True by the organizer - he is in charge of managing the organization (branch) that the organizer has given him access to. So, in the admin panel, I want the organizer to have access to all the pharmacists patientDetail instances they created, but not on the website (client side) that I created which I showed links above. I believe now, you have the idea of the information of who has performed which role once the organizer gives him/her (the person → the pharmacist - where I used Bruno as an example above) the full privilege. Please if you have a better way of approaching the business logic, I would appreciate you help me out in following the correct pattern. So please, I want some instances of PatientDetail to not be included and that instance is the patients field of the MedicationHistoryForm — let the pharmacist not see the organizer’s patient field and vice-versa, and I want the first 5 of the prepopulated filtered/cleaned field of either of the user to be ordered based on the most recent date. Thank you so much, sir.

Hello everyone, I have come up with the solution to my problem the way I wanted it based on the business logic of the app. I should have reported in the last 2 days ago after I solved the puzzle that hindered the progress of my work to you. Here is the solution I came up with comments to better illustrate how I arrived at it.

In my Form class of MedicationHistoryForm, I customized the customize the behavior of the form fields related to patient details:
class MedicationHistoryForm(forms.ModelForm):
    """ patients form for medication history """

    class Meta:
        model = MedicationHistory
        ordering = "-date_created"

        fields = [
            'patients',
            'goal_of_therapy'
            # other field
        ]
        labels = {
            'medication_list': " Enter your patient's medication list",
             # other fields

        }

    def __init__(self, *args, **kwargs):
        """ customize and manipulate the form field rendering behavior of the patient detail field, as well as its date created ordering. """
        # get the current user from the view
        user = kwargs.pop('user')

        super(MedicationHistoryForm, self).__init__(*args, **kwargs)

        # Filter patients based on user role (pharmacist or organizer)
        if user.is_organizer:
            self.fields['patients'].queryset = user.userprofile\
                .patientdetail_set.all()

        elif user.is_pharmacist:
            # self.fields['patients'].queryset = user.pharmacist.organization.patientdetail_set.all()
            self.fields['patients'].queryset = user.userprofile.patientdetail_set.all()

        # Order patients by most recent date  pharmacist__user=user
        self.fields['patients'].queryset = self.fields['patients'].queryset.order_by(
            '-date_created')

        # Limit patients selection to first 5
        self.fields['patients'].widget.attrs['size'] = 5

In the Create and UpdateView class of view.py file, I added this code snippet to allow us to return a dictionary of kwargs of the current user to the form if any:
    
    def get_form_kwargs(self):
      
        kwargs = super().get_form_kwargs()
        # Pass the user to the form
        kwargs['user'] = self.request.user
        return kwargs

I sincerely appreciate you @KenWhitesell for trying to help me out, your questions and follow-up questions were indeed helpful for me in solving my puzzle. Once again, thank you.