A user is assigned to a student group and from the group remove delete_permission, but the below code returns true.
student_group = Group.objects.get(name='student')
content_type = ContentType.objects.get_for_model(Department)
department_permission = Permission.objects.filter(content_type=content_type)
user = User.objects.get(email='test#gmail.com')
student_group.user_set.add(user)
for perm in department_permission:
if perm.codename == "delete_department":
student_group.permissions.remove(perm)
print(user.has_perm("quiz.delete_department"), "Quiz Permission after")
Permissions are cached on the user object see Django documentation. Also refresh_from_db() won't work you need to fetch the user again see this issue.
In your case:
student_group = Group.objects.get(name='student')
content_type = ContentType.objects.get_for_model(Department)
department_permission = Permission.objects.filter(content_type=content_type)
user = User.objects.get(email='test#gmail.com')
student_group.user_set.add(user)
for perm in department_permission:
if perm.codename == "delete_department":
student_group.permissions.remove(perm)
# re-fetch the user from the database after permission change
user = User.objects.get(email='test#gmail.com')
print(user.has_perm("quiz.delete_department"), "Quiz Permission after")
Related
I am trying to create a social media type site that will allow a user to follow and unfollow another user. followers has a ManyToManyField because a user can have many followers.
models.py
class Follower(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, default="")
followers = models.ManyToManyField(User, related_name="followers")
views.py
def username(request, user):
#get user
user = get_object_or_404(User.objects, username=user)
posts = Post.objects.filter(user=user).order_by('-date_and_time')
#follow button code
follow_or_unfollow = ''
try:
following = get_object_or_404(Follower, Q(
user=user) & Q(followers=request.user))
print(following)
except:
following = False
if following:
follow_or_unfollow = True
else:
follow_or_unfollow = False
if request.POST.get('follow'):
follower = Follower.objects.create(user=request.user)
follower.followers.add(*user)
follow_or_unfollow = False
elif request.POST.get('unfollow'):
follow_or_unfollow = True
#following.delete()
When it gets the 'follow' POST request, I want it to add the user who sent it (the one that is logged in) to be added to the followers. Right now, I am getting this error when I try to do that.
TypeError: django.db.models.fields.related_descriptors.create_forward_many_to_many_manager.<locals>.ManyRelatedManager.add() argument after * must be an iterable, not User
I know it says that it has to be iterable, but is there any way to just add one object at a time. Also, how would you delete this particular object?
The * in the arguments converts a list to individual args. For example-
lst = [1,2,3,4,5]
function(*lst)
can be just read as
function(1,2,3,4,5)
You have used follower.followers.add(*user). Hence, user must be an iterable to be unpacked and passed as a list or arguments. But user is a single User object.
You should just use follower.followers.add(user) in this case.
I am using two slack API's, users.list() and users.getPresence(). I use users.list() to retrieve the user's names and IDs.
The users.getPresence() API takes the user ID as a parameter and only outputs their presence of 'active' or 'away' as it is shown here: https://api.slack.com/methods/users.getPresence
I tried taking the names I retrieved from users_list() and returning them along with the users_getPresence() API, but then I only got the list of names to repeat over each status.
client = slack.WebClient(API_KEY)
def users_list():
users_call = client.users_list()
users = users_call['members']
result = []
# loops for each user
for user in users:
uid = user['id']
name = user['profile']['real_name']
info = {"id": None, "name": None}
if users_call['ok']:
info['id'] = uid
info['name'] = name
result.append(info)
else:
return None
return result
def users_getPresence():
info = users_list()
users = []
for value in info:
uid = value['id']
users.append(uid)
presence = []
for user in users:
presence_call = client.users_getPresence(user = user)
if presence_call['ok']:
presence.append(presence_call['presence'])
else:
return None
return presence
Right now, the two API's have separate outputs, where users.list() returns ID and name while users.getPresence() returns presence.
How can I return the user's name and their status together?
Here is an updated version of your 2nd function that returns the list of all users with their presence status. Notice that I also added a sleep so you do not violate the rate limit of max 50 calls per minute.
def users_getPresence():
users = users_list()
for user in users:
presence_call = client.users_getPresence(user = user['id'])
sleep(1.2)
if presence_call['ok']:
user['presence'] = presence_call['presence']
else:
user['presence'] = None
return users
I also saw a couple of issues with your first function. Mainly checking for ok in the loop does not work, because if the method fails it will not contain any users and your script will fail before it reached the ok check.
I have models for Application and Role. Role is linked to a FK Role_type, which is linked by FK to Applications that can use those Role_types (this is a bit of an over-simplication for the question, but I think it suffices). I need a way to create a form to make a new Application, and also to create records assigning associated roles to people (although they can be left blank.)
I have gotten as far as creating the form for the Application and having the associated Role-Types appear on the page, with dropdowns to be populated with a user. Hitting submit, though, didn't create any of the associated Role records. All of my research seems to keep coming back to Inline Model Forms, but the docs aren't really making sense to me--the inputs in the example don't seem to correlate to what I need.
I know this may seem like a duplicate, but trust me when I say I've looked at every SO question that seems to relate to this!
EDIT: My POST looks like this: QueryDict: {u'roles-MAX_NUM_FORMS': [u'1000'], u'roles-1-role_type': [u'4'], u'roles-0-user': [u'1'], u'app-owner': [u'1'], u'app-name': [u'1234'], u'app-serviceTier': [u''], u'app-jiraProject': [u''], u'roles-TOTAL_FORMS': [u'2'], u'roles-1-user': [u''], u'roles-0-role_type': [u'3'], u'csrfmiddlewaretoken': [u'eGsDwtsSQJfl0'], u'roles-INITIAL_FORMS': [u'2']}>. Printing RolesFormSet gives me the exact same output (see comment below)
models.py
class Item(models.model):
name = models.CharField(max_length=255)
roles = models.ManyToManyField(User, through='Role')
class Application(Item):
other_assorted_attributes = foo
class RoleType(models.Model):
name = models.CharField(max_length=255)
class ItemTypeRoleMapping(models.Model):
''' pairs role-types (e.g., Developer) with an Item class they are relevant to'''
roleType = models.ForeignKey(RoleType)
itemType = models.CharField(max_length=255, choices=itemChoices)
class Role(models.Model):
role_type = models.ForeignKey(RoleType)
user = models.ForeignKey(User)
item = models.ForeignKey(Item)
views.py
def buildRolesFormset(itemClass):
''' given an item, build a form for all associated roles '''
roleTypesForItem = ItemTypeRoleMapping.objects.all().filter(itemType=itemClass.__name__)
applicable_roles = [{'role_type': roleType} for roleType in roleTypesForItem]
# formset = rolesFormSet(initial=initial, prefix='roles')
RoleFormSet = inlineformset_factory(Application, Role, extra=len(roleTypesForItem), can_delete=False)
formset = RoleFormSet()
for subform, data in zip(formset.forms, applicable_roles):
subform.initial = data
return formset
def new(request):
''' Create a new application '''
user = request.user
# check permission
if request.method == 'POST':
appform = AppForm(request.POST, prefix='app')
if appform.is_valid():
app = appform.save(commit=False)
rolesInlineFormSet = inlineformset_factory(Application, Role)
# pdb.set_trace()
rolesFormSet = rolesInlineFormSet(request.POST, instance=app, prefix='roles')
if rolesFormSet.is_valid():
rolesFormSet.save()
else:
print rolesFormSet.errors
app = appform.save()
# check rolesFormSet
return redirect(reverse('index'))
else:
appform = AppForm(prefix='app')
rolesFormSet = buildRolesFormset(Application)
return render(request, 'who/editapp.html',
{'appform': appform,
'rolesFormSet': rolesFormSet
})
Tricky to tell without more information, but it looks like you're not saving your rolesFormset in the view. You need to call rolesFormset.save() alongside your form.save() call. Additionally, I suppose you want to attach the roles to the created app? Something like this in your view should work:
if request.method == 'POST':
form = AppForm(request.POST)
rolesFormset = RoleForm(request.POST)
if form.is_valid() and rolesFormset.is_valid():
app = form.save()
roles = rolesFormset.save()
for role in roles:
app.roles.add(role)
return redirect(reverse('index'))
Update: Presuming the models.py is out-of-date, and Role does in fact have a foreignKey to User, the problem will be that you're setting a prefix here:
rolesFormSet = rolesInlineFormSet(request.POST, instance=app, prefix='roles')
but not in your buildRolesFormset function. In that function, do:
formset = RoleFormSet(prefix='roles')
I have a model like below:
class StaffProfile(models.Model):
user = models.ForeignKey(User)
maas = models.FloatField()
maas_gunu = models.CharField(max_length=5)
When I try to insert data with a code like below:
staffprofilesay = StaffProfile.objects.filter(user = user_id).count()
if staffprofilesay > 0:
staffprofile = StaffProfile.objects.get(user = user_id)
else:
staffprofile = StaffProfile()
staffprofile.user = user_id
staffprofile.maas = calisan_formu.cleaned_data["maas"]
staffprofile.maas_gunu = calisan_formu.cleaned_data["maas_gunu"]
staffprofile.save()
I get an error like this:
Cannot assign "u'1'": "StaffProfile.user" must be a "User" instance.
What am I supposed to do?
PS: I'm using Django's User model
You need to assign a User object e.g.
from django.contrib.auth.models import User
user = User.objects.get(id=user_id)
staffprofile.user = user
user needs to be an instance of the User model, not a unicode object (which is what you are passing it).
Yes you have to pass User instance in staffprofile.user = user_id user id place.
As #david-s pointed out in a comment, if you don't have a user instance, you have to fetch from DB with an additional query.
Instead you can directly do is
staffprofile.user_id = user_id because Django behind the scene append _id in table for foreign keys so staffprofile.user will end staffprofile.user_id
I am trying to have this function limit a user to only one vote per image. However it currently lets all votes through. If I change "if existing_vote != 0:" to "if existing_vote == 0:" it lets no votes through. Thoughts?
class VoteHandler(webapp.RequestHandler):
def get(self):
#See if logged in
self.Session = Session()
if not 'userkey' in self.Session:
doRender(
self,
'base/index.html',
{'error' : 'Please login to vote'})
return
#If user hasn't voted - if user doesn't have a vote on that image object
key = self.request.get('photo_id')
vurl = models.Image.get_by_id(int(key))
#pull current site vote total & add 1
existing_vote = models.Vote.all().filter('user=', self.Session['userkey']).filter('photo=',vurl).count()
if existing_vote != 0:
self.redirect('/', { })
else:
newvote = models.Vote(user=self.Session['userkey'], url=vurl)
vurl.votes += 1
vurl.put()
logging.info('Adding a vote')
#Create a new Vote object
newvote = models.Vote(user=self.Session['userkey'], url=vurl)
newvote.put()
self.redirect('/', { })
For the Models:
class User(db.Model):
account = db.StringProperty()
password = db.StringProperty()
name = db.StringProperty()
created = db.DateTimeProperty(auto_now=True)
class Image(db.Model):
user = db.ReferenceProperty(User)
photo_key = db.BlobProperty()
website = db.StringProperty()
text = db.StringProperty()
created = db.DateTimeProperty(auto_now=True)
votes = db.IntegerProperty(default=1)
class Vote(db.Model):
user = db.ReferenceProperty(User) #See if voted on this site yet
photo = db.ReferenceProperty(Image) #To apply vote to right URL
upvote = db.IntegerProperty(default=1)
created = db.DateTimeProperty(auto_now=True)
Looks like your filter on user is wiping out every existing vote, i.e., the equality there is never satisfied. And indeed I'm not sure how I'd satistfy an equality check on a reference propertly. Why not change
user = db.ReferenceProperty(User) #See if voted on this site yet
to, e.g.,
useraccount = db.StringProperty() # account of user who cast this vote
Then the comparison becomes a simple equality check between strings and is sure to work without any complication -- simplicity is generally preferable, when feasible.
On this line here:
existing_vote = models.Vote.all().filter('user=', self.Session['userkey']).filter('photo=',vurl).count()
You need to put a space between the 'photo' and the '=' in the filters - otherwise, it's attempting to filter for a property called 'photo='. This should work:
existing_vote = models.Vote.all().filter('user =', self.Session['userkey']).filter('photo =',vurl).count()