Re: Row based permissions: In DB or App? ... farewell pain

2017-08-11 Thread James Schneider
> My concern is that this python code can't return a queryset with all items
where a given permission+user tuple match.


def has_perm(obj, user):
if user.is_superuser:
return True

This means I need a SQL WHERE condition

For example MyModel.objects.filter(Q(...)|Q())

I never wanted business logic in the database. Sorry, if you misunderstood me.

has_perm() is not used for that purpose, so it isn't a fair comparison.

If you want items specific to a permission gradient, you'll need to
determine the logic to emulate it yourself. In most cases, with a correct
model design, it isn't terribly difficult.

For example, if user Joey can only see red widgets, then you would need to
specifically filter for red widgets in your view query set. The color (or
list of colors) may need to be pulled from a different table, causing a
second query. The ORM does have some advanced usages for filtering a model
based on values in an related model, in most cases using a JOIN to keep it
as a single cross-table query. If that's all you're trying to do, I doubt
any custom database procedure will be much faster than a good query set.

Do you have evidence of such queries being slow in the past? Profiling them
will lead you to the specific operations that may be slowing you down and
can likely be customized through more specific queries in a custom
authentication back end, or better direct querying within the views.

Guardian is a good package, but frankly it is a polar opposite
implementation (all Python, use of GFK's incurring multiple queries, etc.)
from the one you are proposing.

-James

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-users+unsubscr...@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/CA%2Be%2BciUUiVsat3Pwb%3DaJ7FSC_oUxJ1gv6dApGi-fOnOo6nq-VA%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.


Re: Row based permissions: In DB or App? ... farewell pain

2017-08-11 Thread guettli


Am Donnerstag, 10. August 2017 14:30:31 UTC+2 schrieb Vijay Khemlani:
>
> It's still implemented like that in the background, but I'm not sure why 
> do you call it slow.
>
> Did you run benchmarks? Profiling?
>
> Usually your own business logic will be the bottleneck of your 
> application, not your permission checking.
>
>
I can't provide details any more. It was long ago. Performance of 
PostgreSQL SQL optimizer increased a lot.

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-users+unsubscr...@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/0faa4721-86f8-4fef-9934-280e08521bec%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Row based permissions: In DB or App? ... farewell pain

2017-08-11 Thread guettli


Am Freitag, 11. August 2017 10:05:00 UTC+2 schrieb James Schneider:
>
>
>> My concern is that this python code can't return a queryset with all 
> items where a given permission+user tuple match.
>
>
> def has_perm(obj, user):
> if user.is_superuser:
> return True
>
> This means I need a SQL WHERE condition
>
> For example MyModel.objects.filter(Q(...)|Q())  
>
> I never wanted business logic in the database. Sorry, if you misunderstood me.
>
> has_perm() is not used for that purpose, so it isn't a fair comparison.
>
> If you want items specific to a permission gradient, you'll need to 
> determine the logic to emulate it yourself. In most cases, with a correct 
> model design, it isn't terribly difficult. 
>
> For example, if user Joey can only see red widgets, then you would need to 
> specifically filter for red widgets in your view query set. The color (or 
> list of colors) may need to be pulled from a different table, causing a 
> second query. The ORM does have some advanced usages for filtering a model 
> based on values in an related model, in most cases using a JOIN to keep it 
> as a single cross-table query. If that's all you're trying to do, I doubt 
> any custom database procedure will be much faster than a good query set.
>
>
I learned something during the last days. The question is not "Should 
permission checking be done at application level?" the question is "How to 
do the permission checking?"

Yes, I think like you. I guess using a database procedure or a django ORM 
filter() does not matter much. I guess it will have the same speed.




 

> Do you have evidence of such queries being slow in the past? Profiling 
> them will lead you to the specific operations that may be slowing you down 
> and can likely be customized through more specific queries in a custom 
> authentication back end, or better direct querying within the views.
>
>
Yes, here is the related issue: 
https://code.djangoproject.com/ticket/27260#comment:10

You can work-around this be using union() instead of sql-joins. 

I like python and in we did a lot of permission checking with code like 
this in the past "if ...: return True" - It needs some time to discover 
that this is a dead end if you want
a queryset of all items sooner or later.

don't get me wrong. I am not writing this because I complain.

I write here because I want to learn more, and I write here because I want 
to spread the things I learned.

This time, this topic is really ambivalent. Up to now I liked SQL but 
preferred python. Now I see that more and more source code moves to this 
simple set operations engine :-)

With "moves to .." I mean this:

My permission checks in the past: "if ...: return True"
My permission checks in the future: 
SomeModel.objects.filter(Q(...)|Q(...)).exists()




 

> Guardian is a good package, but frankly it is a polar opposite 
> implementation (all Python, use of GFK's incurring multiple queries, etc.) 
> from the one you are proposing.
>
>

I want a get_objects_for_user(). That's my goal. Up to now I am unsure 
which strategy fits best.

Regards,
  Thomas

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-users+unsubscr...@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/6381461b-ac40-41d2-bfe6-47fcb0acf64e%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Dynamic View Selection

2017-08-11 Thread Khai Weng Au Yeong
Not sure if this has been covered before, but I was thinking about this for 
awhile.

Is there a way to dynamically select a View to be used by a URL without 
having to replicate the URL dispatcher over and over via a "superceding" 
like method. Like for example, in my project (let's say it's generic), if I 
have "BaseEmailer" at ".emailer.views" and I have a client 
with a special-case need installed at 
".clients.emailer.views", can I get Django to dynamically 
select it just based off this logic: if client-app-name = base-app-name?

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-users+unsubscr...@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/bc82a384-dec5-4f0a-8cb4-2e4c642b3677%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Dynamic View Selection

2017-08-11 Thread Russell Keith-Magee
Yes - but it doesn’t depend on some hidden feature of Django. It’s 

A Django View is just a function that accepts a request + args, and returns a 
response. That view can, itself, call other functions - including other 
functions that can act as views. So, you could write a “switch statement” view:

def switch_view(request, arg1, arg2):
if client_app_name == ‘xxx’:
return xxx.view(request, arg1, arg2)
else:
return base_view(request, arg1, arg2)

The logic of exactly how to manage the “switch” is entirely up to you.

Depending on how you set up your client sub-packages, you might even be able to 
use import logic to your advantage:

def switch_view(request, arg1, arg2):
try:
client_module = importlib.import_module(‘project.%s.emailer.view’ % 
client_name)
return client_module.view(request, arg1, arg2)
except ImportError:
return base_view(request, arg1, arg2)

Yours,
Russ Magee %-)

> On 11 Aug 2017, at 5:32 am, Khai Weng Au Yeong  wrote:
> 
> Not sure if this has been covered before, but I was thinking about this for 
> awhile.
> 
> Is there a way to dynamically select a View to be used by a URL without 
> having to replicate the URL dispatcher over and over via a "superceding" like 
> method. Like for example, in my project (let's say it's generic), if I have 
> "BaseEmailer" at ".emailer.views" and I have a client with a 
> special-case need installed at ".clients.emailer.views", can I 
> get Django to dynamically select it just based off this logic: if 
> client-app-name = base-app-name?
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "Django users" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to django-users+unsubscr...@googlegroups.com 
> .
> To post to this group, send email to django-users@googlegroups.com 
> .
> Visit this group at https://groups.google.com/group/django-users 
> .
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/django-users/bc82a384-dec5-4f0a-8cb4-2e4c642b3677%40googlegroups.com
>  
> .
> For more options, visit https://groups.google.com/d/optout 
> .

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-users+unsubscr...@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/F5301BC5-CD27-4EC9-A62E-9E32DFB1B22C%40keith-magee.com.
For more options, visit https://groups.google.com/d/optout.


Tutorial help Blank Front page

2017-08-11 Thread Kareem Hart
I am currently doing the tutorial and I'm writing views.

I wrote my index.html file and updated the view to use a loader and add the 
extra code that they provided. It tells me next to load 
127.0.0.1:8000/polls and I should see a bulleted list containing the "whats 
up" question but my page is blank. 

Also when I point my browser towards the http://127.0.0.1:8000/, it gives 
me the following error.

Page not found (404)
Request Method: GET
Request URL: http://127.0.0.1:8000/

Using the URLconf defined in mysite.urls, Django tried these URL patterns, 
in this order:

   1. ^polls/
   2. ^admin/

The empty path didn't match any of these.


So I checked the code for mysite.urls.


from django.conf.urls import url, include

from django.contrib import admin


urlpatterns = [

url(r'^polls/', include('polls.urls')),

url(r'^admin/', admin.site.urls),

]

I ran the following command and got no issues.
$python manage.py check 



-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-users+unsubscr...@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/c7383a02-dd7f-407d-9ea0-297e8ca85c4b%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Tutorial writing views help

2017-08-11 Thread Kareem Hart
I am currently up to the "writing views" part of the tutorial and just 
wrote the polls/index.html template. I updated the view in polls/view.py as 
such:

from django.http import HttpResponse
from django.template import loader

from .models import Question

def index(request):
latest_question_list = Question.objects.order_by('-pub_date')[:5]
template = loader.get_template('polls/index.html')
context = {
'latest_question_list': latest_question_list,
}
return HttpResponse(template.render(context,request))

def detail(request,question_id):
return HttpResponse("You're looking at question %s." % question_id)

def results(request,question_id):
response = "You're looking at the results of question%s."
return HttpResponse(response % question_id)

def vote(request,question_id):
return HttpResponse("You're voting on question %s." % question_id)




I ran  $python manage.py check and the system identified no issues.
When I open the page *127.0.0.1:8000/polls/* I  get a blank page instead of 
a bulleted list of the questions I created.

Also I get the following error when I load *127.0.0.1:8000/polls/.*

Page not found (404)
Request Method: GET
Request URL: http://127.0.0.1:8000/

Using the URLconf defined in mysite.urls, Django tried these URL patterns, 
in this order:

   1. ^polls/
   2. ^admin/

The empty path didn't match any of these.


*mysite.urls*


from django.conf.urls import url, include

from django.contrib import admin



urlpatterns = [

url(r'^polls/', include('polls.urls')),

url(r'^admin/', admin.site.urls),

]

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-users+unsubscr...@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/452bc401-661b-4edd-950c-7ce90e0814e9%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Django admin raises CSRF verification failed when changing from DEBUG True - > False

2017-08-11 Thread Ruben Alves
Same problem here.

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-users+unsubscr...@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/6348e32f-7ba9-4029-a324-fe2e65d79796%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


How to insert a row in another table once a user is created

2017-08-11 Thread Prithviraj Mitra
I am a fresher in django. I am using django 1.10 with allauth app which 
takes care of frontend registration, sending user confirmation 
email,validation, login with email etc. So it all works in the frontend. In 
the backend I managed to change the user creation form by adding an extra 
field email.

The allauth app inserts 3 rows in 3 tables when a user is created in the 
frontend.

1. auth_user
2. account_emailaddress
3. account_emailconfirmation

When adding a user from admin it creates a row in auth_user and 
general_userprofile(extending django user model) table. I would like to 
insert a row in account_emailaddress table whenever a user is created via 
admin.

Fields in account_emailaddress are--

id
email
verified
primary
user_id

models.py looks like this --

from __future__ import unicode_literals

from django.db import models
from django.contrib.auth.models import User
from django.utils.translation import ugettext as _
from django.db.models.signals import post_save
from django.dispatch import receiver
from ciasroot.util import HashedPk
from phonenumber_field.modelfields import PhoneNumberField
import math, decimal, datetime, os


User._meta.get_field('email').blank = False
User._meta.get_field('email')._unique = True




class EmailAddress(models.Model):
verified = models.BooleanField(verbose_name=_('verified'), default=True)
primary = models.BooleanField(verbose_name=_('primary'), default=True)


class UserProfile(models.Model, HashedPk):
user = models.OneToOneField(User, unique=True, related_name ='profile')
job_title = models.CharField(max_length=128, blank=True, null=False, 
default="")
website = models.URLField(max_length=255, blank=True, null=True)
organisation = models.CharField(max_length=50, blank=True, null=True, 
default="")
phone_number = PhoneNumberField( blank=True, null=True)


@receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)




def __str__(self):
return self.user.get_full_name()


def save(self, *args, **kwargs):
super(UserProfile, self).save(*args, **kwargs)



How can I fetch userid and email under class EmailAddress and save it to 
the table.

Any help is highly appreciated.

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-users+unsubscr...@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/1e1057af-4abe-4f0c-aecf-a31cdc729bc8%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Tutorial help Blank Front page

2017-08-11 Thread Александр Христюхин (roboslone)
Hi,

You should open "http://127.0.0.1:8000/polls/ " 
instead of "http://127.0.0.1:8000/ ".
Take a look at the error Django gives you, all registered URLs are listed there.

> On 11 Aug 2017, at 20:56, Kareem Hart  wrote:
> 
> I am currently doing the tutorial and I'm writing views.
> 
> I wrote my index.html file and updated the view to use a loader and add the 
> extra code that they provided. It tells me next to load 127.0.0.1:8000/polls 
> and I should see a bulleted list containing the "whats up" question but my 
> page is blank. 
> 
> Also when I point my browser towards the http://127.0.0.1:8000/, it gives me 
> the following error.
> 
> Page not found (404)
> Request Method:   GET
> Request URL:  http://127.0.0.1:8000/
> Using the URLconf defined in mysite.urls, Django tried these URL patterns, in 
> this order:
> 
> ^polls/
> ^admin/
> The empty path didn't match any of these.
> 
> 
> 
> So I checked the code for mysite.urls.
> 
> 
> 
> from django.conf.urls import url, include
> 
> from django.contrib import admin
> 
> 
> 
> urlpatterns = [
> 
> url(r'^polls/', include('polls.urls')),
> 
> url(r'^admin/', admin.site.urls),
> 
> ]
> 
> 
> I ran the following command and got no issues.
> $python manage.py check 
> 
> 
> 
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "Django users" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to django-users+unsubscr...@googlegroups.com 
> .
> To post to this group, send email to django-users@googlegroups.com 
> .
> Visit this group at https://groups.google.com/group/django-users 
> .
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/django-users/c7383a02-dd7f-407d-9ea0-297e8ca85c4b%40googlegroups.com
>  
> .
> For more options, visit https://groups.google.com/d/optout 
> .

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-users+unsubscr...@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/BCAC4AAF-47EF-4D24-A25D-2B3013DA68F4%40gmail.com.
For more options, visit https://groups.google.com/d/optout.


Re: Django admin raises CSRF verification failed when changing from DEBUG True - > False

2017-08-11 Thread Ruben Alves
Same problem here.

I've created a ticket: https://code.djangoproject.com/ticket/28488

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-users+unsubscr...@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/08889fd6-89da-4c1b-8055-566a63db9c70%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Why does combining multiple annotations work in my case?

2017-08-11 Thread Marcin Gałązka

The documentation advises against combining multiple annotations in one query: 
https://docs.djangoproject.com/en/1.11/topics/db/aggregation/#combining-multiple-aggregations
 due to the infamous bug #10060: https://code.djangoproject.com/ticket/10060

And indeed, having tried the counter-example from the documentation, I can 
easily reproduce the bug.

However... To my astonishment... I produced a **working** example of combining 
multiple annotations. An example that, IIUC the aforementioned docu and bug 
report, should **not** be working.

Not that I'm complaining, actually my life has just became much, MUCH easier 
thanks to this query working... I only can't understand WHY is it working?

Here's my case: (not minimalised too much to improve the chances of failure):

file models.py:

from django.db.models import Model, CharField, PositiveSmallIntegerField, 
PositiveIntegerField, ForeignKey, CASCADE

# Create your models here.


class Province(Model):
name = CharField(max_length=64, primary_key=True)


class Municipality(Model):
name = CharField(max_length=64, primary_key=True)
province = ForeignKey(Province, on_delete=CASCADE)


class Ward(Model):
no=PositiveSmallIntegerField()
municipality = ForeignKey(Municipality, on_delete=CASCADE)
spoiled_votes = PositiveIntegerField()
did_not_vote = PositiveIntegerField()

class Meta:
unique_together = ('no', 'municipality')


class Candidate(Model):
first_name = CharField(max_length=64)
last_name = CharField(max_length=64)

class Meta:
unique_together=('first_name', 'last_name')


class Votes(Model):
ward = ForeignKey(Ward, on_delete=CASCADE)
candidate = ForeignKey(Candidate, on_delete=CASCADE)
amount = PositiveIntegerField()

class Meta:
unique_together = ('ward', 'candidate')

File tests.py:

from django.test import TestCase
from random import seed, randrange
from worksapp.models import Province, Municipality, Ward, Candidate, Votes
from django.db.models import Subquery, Sum, OuterRef, PositiveIntegerField
from operator import attrgetter

# Create your tests here.


class AnnotateTest(TestCase):
def test(self):
seed(1)

provinces = [
Province(name='Province'+str(i))
for i in range(0, 10)
]
Province.objects.bulk_create(provinces)

municipalities = [
Municipality(name='Municipality'+str(i), province=provinces[i//10])
for i in range(0, 100)
]
Municipality.objects.bulk_create(municipalities)

wards = [
Ward(
no=i%10, municipality=municipalities[i//10], pk=i,
spoiled_votes=randrange(0, 100), did_not_vote=randrange(0, 1000)
) for i in range(0, 1000)
]
Ward.objects.bulk_create(wards)

candidates = [
Candidate(first_name='name'+str(i), last_name='surname'+str(i), 
pk=i)
for i in range(0, 10)
]
Candidate.objects.bulk_create(candidates)

votes = [
Votes(ward=wards[i//10], candidate=candidates[i%10], 
amount=randrange(0, 100), pk=i)
for i in range(0, 1)
]
Votes.objects.bulk_create(votes)

multiple_annotate = Municipality.objects.annotate(
cand3votes=Subquery(
Votes.objects.filter(
candidate__first_name='name3',
candidate__last_name='surname3',
ward__municipality=OuterRef('pk')

).values('ward__municipality').annotate(res=Sum('amount')).values('res'),
output_field=PositiveIntegerField()
),
cand7votes=Subquery(
Votes.objects.filter(
candidate__first_name='name7',
candidate__last_name='surname7',
ward__municipality=OuterRef('pk')

).values('ward__municipality').annotate(res=Sum('amount')).values('res'),
output_field=PositiveIntegerField()
),
spoiled_votes=Sum('ward__spoiled_votes'),
votes_not_cast=Sum('ward__did_not_vote')
).get(name='Municipality'+str(83))

self.assertEqual(multiple_annotate.cand3votes, 
sum(map(attrgetter('amount'), votes[8303:8403:10])))
self.assertEqual(multiple_annotate.cand7votes, 
sum(map(attrgetter('amount'), votes[8307:8407:10])))
self.assertEqual(multiple_annotate.spoiled_votes, 
sum(map(attrgetter('spoiled_votes'), wards[830:840])))
self.assertEqual(multiple_annotate.votes_not_cast, 
sum(map(attrgetter('did_not_vote'), wards[830:840])))

multiple_annotate = Province.objects.annotate(
cand0votes=Subquery(
Votes.objects.filter(
candidate__first_name='name0',
candidate__last_name='surname0',
ward__municipality__province=OuterRef('pk')

).values(