Update existing data, after admin approval?

I have been tasked with adding some new functionality to an existing view. Basically, on user signup if the company is already in the database, I am sending an email to an admin, saying “User wants to claim company”. If admin approves, that user will be added to the company, and I want to override the previous info (address, phone, etc.) with the info this user put in at registration. I thought the best way to do this was to add a field to the Account model, called is_approved and set it to False , and when the admin approves, they will set it to True and the new info will be stored, overriding the existing data. I have a Company model, and a Pending_Company model, both with the same exact info.

My view…

company_obj = Company.objects.filter(I am filtering the DB here) 

if not company_obj: 

    """If no company match, create new one"""              
    new_company = Company.objects.create(                 
        name=company.title(),                  
        zip=int(zip_code),                 
        primary_email=email,                 
        website=website,                 
        phone_no=phone_no,                 
        street=street,                 
        city=city,                 
        state=state, )             

        new_company.owner.add(user) 

else: 

    """Add employee to company, send email to admin for approval,              
    if approved, update company instance with new data.""" 

    # If DEBUG = True             
      send_mail('Test Subject', 'Test message', 'test@gmail.com',
                      ['testemail@gmail.com', ], fail_silently=False)

      pending_company = PendingCompanyDetail.objects.create(
                name=company.title(),
                zip=int(zip_code),
                primary_email=email,
                website=website,
                phone_no=phone_no,
                street=street,
                city=city,
                state=state,
            )
      pending_company.owner.add(user)

     if user.is_approved:
            company_obj = pending_company

the else statement is where I am getting confused, It is not updating the company_obj instance with the new pending_company info.

I kind of understand why, because on account creation the is_approved is defaulted to False . I’m really trying to figure out a work around for this, when that boolean is flipped to True , how can I trigger that override?

I’m assuming you’re going to create a separate function for an admin (or someone) to perform the “approval” function.

It’s in that view, where you want to take this action. When the person approving the assignment submits the approval, you copy the data to the company table.

Note: the statement company_obj = pending_company isn’t going to do you any good. Company_obj is just a name referring to an object in memory. That assignment statement is just going to reassign the name to the existing pending_company object, it is not going to perform a copy.

To do this, you need to do something like:

pend = (however you retrieve the pending_company object)
company_obj = Company(
    name = pend.name,
    zip = pend.zip,
    primary_email = pend.primary_email,
    ...
    )
company_obj.save()

I would also suggest dropping the PendingCompany model and utilizing a proxy model for it. This way, you don’t have a, in my opinion, redundant DB table, and you can still use the Django ORM on PendingCompany like you are already.

(If PendingCompany isn’t identical to Company then let me know).

– add a field to your company model like so:
pending = models.BooleanField(default=True)

– create a manager to use the pending boolean:

class PendingCompanyManager(models.Manager):
     def get_queryset(self):
          return super().get_queryset().filter(pending=True)

– create a proxy model for PendingCompany:

     class PendingCompany(Company):

        objects = PendingCompanyManager()

        class Meta:
             proxy = True

Now you can query PendingCompany instances without having another DB table and instead of creating a whole new object in your view, you can just tick off the ‘pending’ flag on the model :slight_smile:

Hope this helps,

–Austin

The problem with this suggestion goes back to an earlier conversation on this topic - How to match 2+ criteria in the database?

The database is designed to not allow duplicates when more than one field matches an existing entry. This would, in its current state, prohibit the addition of these pending entries to the same table. Approving this entry also implies the removal (or editing / replacement) of the existing entry.

Now, re-engineering that facility to allow for the pending flag is possible, but does extend beyond the immediate question being presented here.

Ken

1 Like

Assuming I’m the admin, or another co-worker. And we are just going into the admin manually and checking that is_approved to True. Will this still require a custom function outside of the signup/registration view?

I’m trying to get this up and running, in the most simple way possible, and enhance later on. I was hoping to keep the logic in the signup else view (basically saying there is a company match.). Shoot an email to admin, and if admin approves, update the company info.

https://docs.djangoproject.com/en/3.1/ref/contrib/admin/actions/

I was looking at admin actions, and if a custom function had to be made, I was thinking that this would be the place?

I’m assuming that it’s a different person submitting this entry than the person approving it. Is that correct?

If so, then yes, you’re talking about two separate actions. Person 1 (“submitter”) submits the form. Once they’ve submitted it, they are done. Person 2 (“approver”) can then switch the is_approved flag. These two options occur at different times by different people, so yes, they are different functions.

The registration view is done once the submitter has received their response. It’s no longer “live” or “active”.

If the submitter is going to approve multiple submissions at once, then yes, an action would be a great way to implement that.

Otherwise, if you’re looking at the detail view of a request, I’d override the save_model method in the ModelAdmin class to perform that function.

Ken

Yes, two different people. User & admin.

User is submitting the form. If there is a Company match, that will trigger an email to the admin. Then the admin can go into the admin page and switch that boolean to True, and when that happens overrides existing company data with the new PendingCompanyDetail info, basically I want to copy that info to the Company model.

This functionality can be achieved in the admin.py file, overriding the Company model’s save_model method?

Yes to part 2 (Admin going to the admin page). See the referenced docs on save_model.

Thank you! I definitely have a better understanding/direction on how to go about implementing something like this now!