How can I get current logged user profile in django, into models? - django

How can I get current logged user profile in django, into models ?
I have this code:
def save(self, *args, **kwargs):
profile = User.get_profile()
self.empresa_id = profile.idempresa
self.empresa_id = profile.id_comerx3c
super(Cliente, self).save(*args, **kwargs)
but doesn`t work..

If you're using a ModelForm, you have three choices:
Set the profile when you instantiate the form
Create the object instance in a view, but not commit it, then set the profile property and
commit the save
Pass the profile to the save method, and set the property before
calling super
If you're just dealing with a Model, you have two choices:
Pass the profile in when you instantiate the object
Set the profile on an instance of your object before you call save

Related

How do I make ManyToManyField limit_choices_to equal to request.user (Django)?

I should limit choices of manytomanyfield to logged in admin user profile, in django admin.
class News(models.Model):
title=models.CharField(max_length=200)
users=models.ManyToManyField(User, blank=True, limit_choices_to={"profile__school": "request.user.profile.school"})
I have tried to implement it in admin.ModelAdmin, where I can access request.user, but couldn't find a way to do it.
You don't do this in the model layer. Django's user layer is request unaware. Some code paths don't even have a request, for example if these are done through a Python script, or a Django management command.
You can limit the choices in the ModelAdmin by overriding get_form:
class NewsAdmin(ModelAdmin):
def get_form(self, request, obj=None, change=False, **kwargs):
form = super().get_form(request, obj=obj, change=change, **kwargs)
form.base_fields['users'].queryset = User.objects.filter(
profile__school__profile__user=request.user
)
return form
Note: It is normally better to make use of the settings.AUTH_USER_MODELĀ [Django-doc] to refer to the user model, than to use the User modelĀ [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.

Django admin save() doesn't get data from ManyToManyField

I'm trying to get chosen objects from affiliate_networks in Django admin when the user clicks the submit button.
When I choose one from affiliate_networks and submit it, the console prints an empty of affiliate_networks, and then I come back to the page and the chosen object is stored properly. So, I submit it again, then the console prints the chosen object. save() only receives objects that are already stored, not objects that I choose before saving.
Is there a way, that I can have save() to notice affiliate_networks to have any object chosen?
class Store(models.Model):
...
affiliate_networks = models.ManyToManyField(AffiliateNetwork, blank=True)
def save(self, *args, **kwargs):
print(self.affiliate_networks.all())
You can't do it in save() - as you have discovered, Django admin doesn't save ManyToMany objects until afterwards. You need to do it in the save_related method of ModelAdmin. See https://timonweb.com/posts/many-to-many-field-save-method-and-the-django-admin/
In admin.py:
...
class StoreAdmin(admin.ModelAdmin):
def save_related(self, request, form, formsets, change):
super(StoreAdmin, self).save_related(request, form, formsets, change)
print(form.instance.affiliate_networks.all())
...
admin.site.register(Store, StoreAdmin)

Model field level permission and Field value level permission in Django and DRF

I am doing a project which require some user to access (view) a model's field but they cannot update the field. Is there a way to do this?
This will not be used in the admin site.
Also, I want to provide permissions based on a model's field value. Is there a way to do this?
Thank you!
There are different possibilities to check the permissions, though they all require you writing the permission checking code yourself. There might be some django packages providing the functionality for you, but I don't know any.
You could create one permissions for each field that you would like to permit / deny in the model's META.permissions attribute and then check the permissions per user.
The checks can be done in different places. Either in your view directly, in the model's savemethod or in the form's clean_<field_name> method. I would prefer the clean_<field_name> method. e.g.:
class MyForm(forms.ModelForm):
class Meta:
model = <YOUR MODEL>
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user')
super(MyForm, self).__init__(*args, **kwargs)
def clean_myfield(self):
cd = self.cleaned_data
# check if the user has the required permission to change the field
if self.user.has_perm(<YOUR PERMISSION>):
return cd.get('myfield')
# if not, return the original value
if self.instance:
return self.instance.myfield
# If it can happen that there is no instance yet,
# you should return a sensible default here
return None
For this solution, you would need to pass the request.user to the form on instantiation.

django edit user and userprofile object

so i'm making a generic "accounts" page in django. I've used the django-registration plugin, and currently have a (djang-standard) User object, as well as a UserProfile and UserProfileForm object.
This is a question of style, or best-practices, i suppose. Is what i'm planning "right" or is there a "better/recommended/standard way" to do this?
What i'm planning on doing is creating the UserProfile from the request.user ie:
form = UserProfileForm(instance=User)
(and sending that form to the view), and in the UserProfileForm:
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
def __init__(self,*args,**kwargs):
super(UserProfileForm, self).__init__(*args, **kwargs)
if kwargs.has_key('instance'):
self.user = kwargs['instance']
where my UserProfile is pretty much like so:
class UserProfile(models.Model):
user = models.OneToOneField(User)
points = models.IntegerField(default=0) #how is the user going with scores?
and where User is of the django.contrib.auth.models variety.
Ok! The handling of the editing and saving will either be done via the mixin django stuff or, more likely because i haven't read up on mixins my own user-defined view that handles post and gets. But ignoring that - because i'm sure i should be using the mixins - is the above "right?" or are there suggestions?
cheers!
Take a look at user profiles on the django docs, the basics are listed there. You should also take a look at using a form in a view.
Some specific feedback:
You got the UserProfile model right, but you have to create an instance of one every time a new user is added (either through the admin interface or programmatically in one of your views). You do this by registering to the User post_save signal:
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
post_save.connect(create_user_profile, sender=User)
You should init the ModelForm with an instance of the UserProfile, not User. You can always get the current user profile with request.user.get_profile() (if you define AUTH_PROFILE_MODULE in settings.py). Your view might look something like this:
def editprofile(request):
user_profile = request.user.get_profile()
if request.method == 'POST':
form = UserProfileForm(request.POST, instance=user_profile)
if form.is_valid():
form.save()
return HttpResponseRedirect('/accounts/profile')
else:
form = UserProfileForm(instance=user_profile)
# ...
No need for the init override in your ModelForm. You will be calling it with a UserProfile instance, anyway. If you want to create a new user, just call the User constructor:
user = User()
user.save()
form = UserProfileForm(instance = user.get_profile())
# ...

Accessing request object from form.save

I'm using the pyfacebook module for Django to implement facebook Connect for one of my sites, I'm not using a local User object because I only want to use Facebook for login.
I understand that I can't access the request object from the save method on a Django form, so how would I access the facebook object that the provided middleware gives you?
I want to attach the users facebook UID to an object being created from a form, I could add it as a hidden field to the form but then people could just change it to make it appear that a question came from someone else.
What is the best way to pass in this uid to the save() method?
The correct way to do this is to use an instance of the object you're trying to save, like this:
question = Question(user=int(request.facebook.uid))
form = QuestionForm(request.POST, instance=question)
question = form.save()
question.put()
Do this in your view, NOT in the save() method of your object.
Watch out if any of the fields are required though, you'll have to specify them in the instance objector calling form.save will throw an exception.
You can set a variable on the form when you create it.
views.py
def myview(request):
form = FacebookConnectForm(request)
forms.py
class FacebookConnectForm(forms.Form):
def __init__(self, instance):
self.instance = instance
def save(self):
print self.instance
...