Get the Current User

I have a model of a company and there is foreign key field which is the user that created the company. The field expects a default and I want to make the logged in user the default. How do I do that?
I created a method but when I make the method the default I am told it requires a required argument, which I don’t understand because I am specifying that argument in the method. Here is my code:

def logged_user(request):
    current_user = request.user
    return current_user

class Company(models.Model):
    user = models.ForeignKey(SbnUser, on_delete=models.CASCADE, default=logged_user)

What am I doing wrong or not understanding pls?

You would have this information in your view. Your proper hook for this is likely going to be in the view in which you create the Company.

The problem with trying to define this in the model is that the model can be invoked outside the context of a view - there’s no guarantee that there even is going to be a request available at the model layer.

Ken

I wouldn’t set this as a default value. Instead, I would update this value in either the view handling the company creation logic or inside an overwritten save method for a company.

Ok so I should make the default for the field in the model ‘None’ and then override that value in the view that will be used for creating the company?

I wouldn’t set a default value. Upon Company creation, whether it’s a functional view or a CBV, you’ll have access to the request in the view processing the company’s creation. From there, you can assign the company’s user.

If you’re using a CBV, you can override the form_valid function and assign the user from self.request.user.

Here’s the Django documentation on CBVs. I’d give that a look before randomly throwing code around until something works, personally :slight_smile:

https://docs.djangoproject.com/en/3.0/topics/class-based-views/

Or just not specify the default at all. That has an advantage that as a required field, it’s going to ensure that one of the methods creating that model is assigning a value to that field.

But yes, somewhere in the processing of the view is where you’d want it assigned.

Since you want it assigned regardless of the form content, I wouldn’t associate it with the form, either. It’s a view-level parameter. (But that decision is based upon this being a “who created this” type of field vs “who is the last person who edited this” kind of field. My answer is different between those two cases.)

Ken

But Django forces me to set a default. It says either it can set a default or I should, so what do I do then? I added the field and when I wanted to run makemigrations Django said set a default for that field or Django will do it for me, but it must have a default. Based on that I wanted to create a get user method, which I understand is better placed in a view cause that is where the action takes place.

Also I am using REST Framework so it provides the serializer which I can use to create the company with so how do I specify the user then?

I’m guessing it’s saying that because you didn’t have that field when you initially migrated that model. Objects already exist in the database on the Company table so when you put a new field, those objects in the database need a placeholder.

Regarding DRF, you should look up the documentation for DRF nested relationships or
SerializerMethodField :slight_smile:

https://www.django-rest-framework.org/api-guide/relations/

Ok yes sorry I forgot I already have two companies I created to test the Vue app. Let me just delete the whole db and start from scratch. For me this is my third month learning Python and Django (very part time) so excuse my lack of understanding. Thanks for your help

1 Like

Thank you I know I need to do a lot more reading. If only we could buy time (and I could sell it :rofl:)

That’s why we’re here :slight_smile: good luck!

Just as an FYI - if you’re creating a modification to an existing table by adding a ForeignKey field, you have (at least) two options you can use to do this without needing to delete your existing data.

  1. You can find a suitable default value. For example, you could have created that new field using your superuser’s account as the default. That would let you create the field - then you can go in and modify those entries to fix them to be what they need to be.

  2. You can create the field as optional (null=True) and then make and run your migration. Then edit those rows as appropriate, take off the null parameter, and make / run another migration.

The first method is handy in situations where the default you set is likely to be the right one. The second is handiest when you have a lot of data needing to be updated and need a way to quickly determine whether or not you’ve updated the data to the correct values.

Ken

Hi Ken how do I do this please?

Using either the admin or the shell, find the id value of the user you wish to use. Then use that number as the default value. (If you create the superuser as your first action on the database, it’ll have a user id of 1.)

e.g.
user = models.ForeignKey(SbnUser, on_delete=models.CASCADE, default=1)

The problem with Django or at least in my opinion is that you have to be so very careful with migrations because if you change a field and you do not make the migrations correctly and you run migrate you are kind of screwed because going back to fix a migrations mistake is a pain. For example so I added the user field to company after creating two companies and then I had this whole issue with the default value that Django wanted for the existing objects in the database. So I went and deleted a previous migrations file and now I sit with this error message 'no such column companies_company.user_id. So I feel the only way to fix this is by deleting the whole db. It seems I am going to delete the database many times in my quest to learn this.

This all fits into the generic category of the old joke:

Patient in doctor’s office: “Doctor, it hurts when I do this”.
Doctor’s response: “Then don’t do that!”

Now that you’ve explained more as to what happened, I’m guessing what the situation really was that in running the migration step, you got the prompt asking for the default value to use. So in this case, if my conjecture is true regarding this, then you had made the migrations correctly, and Django was doing exactly what it should have done and you were not in any sort of problem.

Had you asked at that point what to do, I would have suggested what I mentioned above - find the ID of your superuser, and use that numeric value as the default. You would have then been able to continue moving forward without issue, and you wouldn’t be facing this situation.

You don’t need to be “careful” with migrations, you just need to not intentionally break it, without knowing what you’re doing and what the side effects are.
(I do seem to remember an earlier conversation where you had emptied some tables that you shouldn’t have.)

I guess the best way to put it is, when you’re using migrations, you don’t own the database, Django does. You don’t own the tables, Django does. You don’t own those migration files, Django does.

But even beyond that, logically, it’s really not much different than if you were to arbitrarily delete any other file in your project. Delete your urls.py file? Not going to work. Delete your views.py file? Not going to work. So I’d think real hard about why I’d think that deleting a migration file - or any other file in the project - isn’t going to break something unless I take other actions as well.

You’re currently of the opinion that “the only way to fix this is by deleting the whole database”. That’s not true. Regardless of what you’ve done, it’s almost impossible to get to that point where the only way to fix it is dropping and recreating the database. It’s more an issue of how much time will it take to fix it, and in the development cycle, it may be significantly quicker to do that than anything else.

(And, if you’re going to go that route, it’s also a perfect time to delete all your existing migrations, so that when you do your initial makemigrations, you’re going to initially create a migration based upon the current state of your models rather than having to process x migrations to get to the current state.)

The problem came in when I added the new field and forgot I already had objects in the database and then instead of just accepting Django make a default I wanted to go and add the get current user as a default and then I messed up the migrations by deleting the previous ones and trying to run migrate. The biggest problem here is simply a lack of knowledge on my part and not understanding how this all fits in together. Still learning. Thanks for all the advice and input it’s highly appreciated

Yep, I understand the learning curve - everyone here has climbed it to one degree or another.

So I guess if there’s a concise lesson to be learned here it would be this:

Don’t delete anything unless and until you understand what’s going to break when you do.

Yes and an even a better lesson to learn here is, plan your models before you create them and try to avoid changing them in the midst of a project. Makes it easier with migrations and such. I also need to understand how the fields are related so for example I want a company to have a branch and every branch must have its own address, owner (maybe) and list of services (which is another model). So I need to carefully plan this and what field types to use for which field. As for example I want to be able to have Cities for the address be populated from the database and not be a Choices field where the choices are hard coded. Lots of things to consider and I need to be sure about what I use. Again your input is appreciated thanks Ken.