Re: ManyToManyField not generating ON DELETE CASCADE clauses on (default) through table

2016-04-01 Thread Shai Berger
Hi Carlton,

I'm sorry that your mail was left unanswered for so long.

Generally, "is it a bug" questions are better suited to django-users than to 
this list. In particular, I believe this is not a bug: The behavior you see is 
Django's default way of defining foreign keys, and indeed, as you noticed, when 
you delete the objects using Django's API, it takes care to delete the 
dependent records as well.

The reason for Django's preference to delete the dependent records itself is, 
that this way we can fire signals for the to-be-deleted objects. The reason for 
not including ON DELETE CASCADE in the column definition is that this way, if 
there's a problem and for some reason an object that should be deleted is not 
deleted, it is found out early.

I don't think anything will break terribly if you add ON DELETE CASCADE to the 
FK constraints, but I have to wonder why you'd prefer to delete the records 
through SQL directly rather than through Python, where you have all the 
handlers ready.

But as noted, this discussion doesn't really belong on this list.

HTH,
Shai.

On Tuesday 15 March 2016 21:43:11 Carlton wrote:
> I have a query concerning the lack of a ON DELETE CASCADE clause to the
> foreign key constraints generated for PostgreSQL (using Django 1.8.11) on
> the default through tables generated for ManyToManyField.
> 
> 
> I was unable to find any related issues (”ManyToMany cascade” Search
> Results – Django
>  hangeset=on=on=on=on>) so I thought I’d ask before I
> open a ticket.
> 
> 
> I create an app called constraints in which I define two models:
> 
> 
> from django.db import models
> class A(models.Model):
>  name = models.CharField(max_length=200)
> 
> class B(models.Model):
>  name = models.CharField(max_length=200)
>  a_set = models.ManyToManyField(A, db_constraint=True)
> 
> 
> I then inspect the generated SQL:
> 
> $ ./manage.py sqlall constraints
> 
> BEGIN;
> 
> CREATE TABLE "constraints_a" (
> 
> "id" serial NOT NULL PRIMARY KEY,
> 
> "name" varchar(200) NOT NULL
> 
> )
> 
> ;
> 
> CREATE TABLE "constraints_b_a_set" (
> 
> "id" serial NOT NULL PRIMARY KEY,
> 
> "b_id" integer NOT NULL,
> 
> "a_id" integer NOT NULL REFERENCES "constraints_a" ("id") DEFERRABLE
> INITIALLY DEFERRED,
> 
> UNIQUE ("b_id", "a_id")
> 
> )
> 
> ;
> 
> CREATE TABLE "constraints_b" (
> 
> "id" serial NOT NULL PRIMARY KEY,
> 
> "name" varchar(200) NOT NULL
> 
> )
> 
> ;
> 
> ALTER TABLE "constraints_b_a_set" ADD CONSTRAINT "b_id_refs_id_4308660a"
> FOREIGN KEY ("b_id") REFERENCES "constraints_b" ("id") DEFERRABLE
> INITIALLY DEFERRED;
> 
> CREATE INDEX "constraints_b_a_set_b_id" ON "constraints_b_a_set" ("b_id");
> 
> CREATE INDEX "constraints_b_a_set_a_id" ON "constraints_b_a_set" ("a_id");
> 
> COMMIT;
> 
> 
> For the table constraints_b_a_set I am expecting the two foreign key
> constraints to include an ON DELETE CASCADE:
> 
>- "a_id" integer NOT NULL REFERENCES "constraints_a" ("id") ON DELETE
>CASCADE ...
>- ALTER TABLE "constraints_b_a_set" ADD CONSTRAINT
>"b_id_refs_id_4308660a" FOREIGN KEY ("b_id") REFERENCES "constraints_b"
>("id") ON DELETE CASCADE ...
> 
> I came across this running DELETE FROM ... SQL statements against a Django
> generated database.
> 
> 
> Using the example models if I run DELETE FROM "constraints_a";` (with
> related objects in place) I get an error:
> 
> 
> ERROR: update or delete on table "constraints_a" violates foreign key
> constraint "" on table "constraints_b_a_set"
> 
> DETAIL: Key (id)=(1) is still referenced from table "constraints_b_a_set".
> 
> 
> This is because the lack of the ON DELETE CASCADE means the through table
> record is not removed when the referenced row is deleted.
> 
> 
> For me this looks like a bug. *First question then is, is it a bug?* Or is
> it by design, and something that just needs working around? Does it need
> documenting?
> 
> 
> Second (related) question is, would anything break if I just added the
> constraint in SQL myself?
> 
> 
> I can work around this by an additional query to DELETE FROM the through
> table, and — whilst there’s a lot of logic there that made my head hurt
> — it looks as if Django does this in django/django/db/models/deletion.py —
> but it would be nice to let the database handle the constraint if possible.
> 
> 
> Would Django’s own logic break if we pushed it to the database level — or,
> conversely, is there room to do that?
> 
> 
> I’m happy to spend time on it.
> 
> 
> (No doubt, having raised it, the answer will be, *“No, not bug; not open to
> change, and documented HERE”* )
> 
> 
> Thanks for the input/guidance.
> 
> 
> Kind Regards,
> 
> 
> Carlton


Re: Feedback on Django Channels

2016-04-01 Thread Andrew Godwin
>
>
> Well, in that case I would consider defining the consumer as a required,
> but
> keyword (and keyword-only in Python3) argument, specified in the end by
> convention. Putting it between the channel and channel parameters is ugly
> IMO.
>
>
It would be easy enough to change all the docs and examples to work this
way - specifying "consumer=" as a kwarg will already work. I'm slightly
concerned about forcing keyword-only, though.

Andrew

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/CAFwN1uoDGBcAZKiV8zu-hwWg77YDRvtVGdw5oJ32rLy4wZ_fdQ%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.


Re: Feedback on Django Channels

2016-04-01 Thread Shai Berger
On Saturday 02 April 2016 00:38:31 Andrew Godwin wrote:
> On Fri, Apr 1, 2016 at 11:32 PM, Shai Berger  wrote:
> > Hi,
> > 
> > Finally found the time to go through this discussion.
> > 
> > The first note that comes to mind is:
> > 
> > Although it has already been pointed out more than once that positional
> > arguments cannot follow keyword arguments, you both (Andrew and Vincent)
> > keep
> > giving examples such as
> > 
> > # SYNTAX ERROR
> > route('sms.receive', sender=r'\+44(?P[0-9]+)$',
> > 
> > Consumer)
> > 
> > I believe the reason for that is the clash between the will to preserve
> > the current `route(channel, consumer)` syntax, which is like the
> > parallel `url(path_regex, view, **kw)` syntax, on one hand; and the
> > instinct that the
> > identifying parameters should be together, on the other hand.
> > 
> > I think that the latter consideration prevails; unlike the kw parameters
> > in url(), which are essentially parameters to the view, the kw
> > parameters proposed for channel help select the consumer; and so they
> > must be adjacent to
> > the channel name -- and hence, the consumer must be the first argument.
> 
> Ah, that's an interesting ordering I hadn't considered before - the problem
> is, I would have it (channel, kwargs, consumer) if I could, as generally
> when I'm reading the file I want to identify things by route. For that
> reason, I still like having the channel at the beginning as it makes it
> obvious what the rest of the line is dealing with (websocket? http? etc.)
> 

Well, in that case I would consider defining the consumer as a required, but 
keyword (and keyword-only in Python3) argument, specified in the end by 
convention. Putting it between the channel and channel parameters is ugly IMO.

> > A second thought is about multiple keyword arguments:
> > 
> 
> Is there something about this method you think is better than three
> includes? Remember, routing specifies the variable inside the module
> (unlike url includes, which only specify the module) so you can still keep
> the three routing sets in the one routing.py inside the app.
> 

I somehow missed this, it makes my entire argument moot. Agreed.

Thanks,
Shai.


Re: Feedback on Django Channels

2016-04-01 Thread Andrew Godwin
On Fri, Apr 1, 2016 at 11:32 PM, Shai Berger  wrote:

> Hi,
>
> Finally found the time to go through this discussion.
>
> The first note that comes to mind is:
>
> Although it has already been pointed out more than once that positional
> arguments cannot follow keyword arguments, you both (Andrew and Vincent)
> keep
> giving examples such as
>
> # SYNTAX ERROR
> route('sms.receive', sender=r'\+44(?P[0-9]+)$',
> Consumer)
>
> I believe the reason for that is the clash between the will to preserve the
> current `route(channel, consumer)` syntax, which is like the parallel
> `url(path_regex, view, **kw)` syntax, on one hand; and the instinct that
> the
> identifying parameters should be together, on the other hand.
>
> I think that the latter consideration prevails; unlike the kw parameters in
> url(), which are essentially parameters to the view, the kw parameters
> proposed for channel help select the consumer; and so they must be
> adjacent to
> the channel name -- and hence, the consumer must be the first argument.
>

Ah, that's an interesting ordering I hadn't considered before - the problem
is, I would have it (channel, kwargs, consumer) if I could, as generally
when I'm reading the file I want to identify things by route. For that
reason, I still like having the channel at the beginning as it makes it
obvious what the rest of the line is dealing with (websocket? http? etc.)


>
> A second thought is about multiple keyword arguments:
>
> It isn't clear if more than one keyword argument is allowed, and if so,
> what
> should be the semantics of the combination. When thinking about routing,
> it is
> almost obvious that if there are many kw arguments, they must all match for
> the whole route to match. But when thinking about includes, a different
> consideration arises: How do I specify routing in an app which deals with
> several incompatible channels?
>
> For argument's sake, let's say I have an app which can handle SMS's, mails
> and
> websocket.connect's. I want it to handle all of these if they come from
> within
> my company -- so, based on partial phone number, sender domain and client
> IP
> addresses, respectively. Would I need to have the app's routing.py module
> include()'ed three times? Or would it make more sense to give include() kw
> parameters an "or" semantics -- that is, match as soon as one argument
> matches?
>

The way I've done this in the chat example is two includes:

https://github.com/andrewgodwin/channels-examples/blob/master/multichat/multichat/routing.py
https://github.com/andrewgodwin/channels-examples/blob/master/multichat/chat/routing.py


>
> I think both of these solutions are bad, and the only solution that makes
> sense is to allow a more complex structure of argument -- so that multiple
> kw
> args are all required to match, and for a disjunction of channels we use
> positional channel-spec args -- something like,
>
> include('my_app.routing',
> chan_spec('sms.receive', sender=r'\1212555(?:[0-9]{4})$'),
> chan_spec('mail.receive', sender=r'^(?:\W+)@my_org.com$),
> chan_spec('websocket.connect', remote_ip='^172.10'),
> )
>
> where a set of kw parameters are considered to all belong to one implicit
> chan_spec.
>
>
I'm not entirely convinced this is better than just having three includes;
it would be basically the same number of lines, and would work just as you
suggest, with the added benefit of no extra thing to import.

Is there something about this method you think is better than three
includes? Remember, routing specifies the variable inside the module
(unlike url includes, which only specify the module) so you can still keep
the three routing sets in the one routing.py inside the app.

Andrew

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/CAFwN1uoZLb7vonqO80QyxhF2wmsaQQO4rjjLsHi1nRUup1ZMVA%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.


Re: Feedback on Django Channels

2016-04-01 Thread Shai Berger
Hi,

Finally found the time to go through this discussion.

The first note that comes to mind is:

Although it has already been pointed out more than once that positional 
arguments cannot follow keyword arguments, you both (Andrew and Vincent) keep 
giving examples such as

# SYNTAX ERROR
route('sms.receive', sender=r'\+44(?P[0-9]+)$', Consumer)

I believe the reason for that is the clash between the will to preserve the 
current `route(channel, consumer)` syntax, which is like the parallel 
`url(path_regex, view, **kw)` syntax, on one hand; and the instinct that the 
identifying parameters should be together, on the other hand.

I think that the latter consideration prevails; unlike the kw parameters in 
url(), which are essentially parameters to the view, the kw parameters 
proposed for channel help select the consumer; and so they must be adjacent to 
the channel name -- and hence, the consumer must be the first argument.

A second thought is about multiple keyword arguments: 

It isn't clear if more than one keyword argument is allowed, and if so, what 
should be the semantics of the combination. When thinking about routing, it is 
almost obvious that if there are many kw arguments, they must all match for 
the whole route to match. But when thinking about includes, a different 
consideration arises: How do I specify routing in an app which deals with 
several incompatible channels? 

For argument's sake, let's say I have an app which can handle SMS's, mails and 
websocket.connect's. I want it to handle all of these if they come from within 
my company -- so, based on partial phone number, sender domain and client IP 
addresses, respectively. Would I need to have the app's routing.py module 
include()'ed three times? Or would it make more sense to give include() kw 
parameters an "or" semantics -- that is, match as soon as one argument 
matches?

I think both of these solutions are bad, and the only solution that makes 
sense is to allow a more complex structure of argument -- so that multiple kw 
args are all required to match, and for a disjunction of channels we use 
positional channel-spec args -- something like,

include('my_app.routing',
chan_spec('sms.receive', sender=r'\1212555(?:[0-9]{4})$'),
chan_spec('mail.receive', sender=r'^(?:\W+)@my_org.com$),
chan_spec('websocket.connect', remote_ip='^172.10'),
)

where a set of kw parameters are considered to all belong to one implicit 
chan_spec.

My 2 cents,
Shai.


Re: Value of tightening URLValidator/EmailValidator regular expressions?

2016-04-01 Thread Zach Borboa
-1 on less strict validation. Saying we need less strict validation because 
emails are usually confirmed by sending an email to it, is akin to saying 
urls are only valid if the url can be fetched. "Looks vaguely like a url" 
would not be enough for validation purposes. I believe we should strive to 
keep a reasonably strict and correct email validator.

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/0e26ba75-4554-4d28-9865-9a1d9a176c9e%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[ANNOUNCE] Django bugfix releases issued: 1.9.5 and 1.8.12

2016-04-01 Thread Tim Graham
Details are available on the Django project weblog:

https://www.djangoproject.com/weblog/2016/apr/01/bugfix-releases/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/a49726cc-1f97-47ea-8719-ef3b2ecda0b7%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: A helpful ImportError for manage.py when Django isn't installed/available

2016-04-01 Thread Shai Berger
An idea: Catch the exception; in the handler, try to simply "import django". 
If this works, reraise, if it fails, print helpful message.

On Thursday 31 March 2016 20:15:05 Tim Graham wrote:
> Ben Welsh (palewire) raised a proposal on a GitHub pull request [0]:
> 
> I've seen newbies flounder when they receive this error after running
> manage.py.
> 
> $ python manage.py
> Traceback (most recent call last):
>   File "manage.py", line 7, in 
> from django.core.management import execute_from_command_line
> ImportError: No module named django.core.management
> 
> The root cause is almost always simple, like forgetting install Django with
> pip or neglecting to "activate" a virtual environment. But the Python
> jargon doesn't do much to help people new to our world connect the dots.
> 
> My proposal: Catch that error and print out a more verbose message that
> explains to the user exactly what's wrong. Here's my draft. I'd welcome any
> changes, but I think something along these lines could better welcome new
> people into Django.
> 
> Traceback (most recent call last):
>   File "manage.py", line 11, in 
> installed and available on your PATH variable?")
> ImportError: Couldn't import Django. Are you sure it's installed and
> available on your PYTHONPATH environment variable? Did you forget to
> activate a virtual environment?
> 
> 
> 
> -
> Claude says, "I'm not convinced about this. Aren't we hiding other possibly
> helpful import errors (at least on Python 2)?"
> Aymeric says, "I share Claude's concern. We've been constantly removing
> that sort of "helpful" exception wrapping from Django"
> Aymeric again, after further investigation, "Importing
> django.core.management doesn't ripple too far. Specifically it doesn't
> import any of the user's code. This reduces the likelihood of masking
> useful errors. It will mask exception info if Django is installed
> incorrectly, for instance because two installs happened in the same
> location (but I think that's less likely since pip/virtualenv became
> mainstream and since we added code to setup.py to detect existing
> installs).
> 
> Does anyone else have opinions on the change? I suppose another option
> could be to try to reraise the original exception with the "helpful
> message" added.
> 
> 
> [0] https://github.com/django/django/pull/6314