Upgrading from Django 1.3 to 1.5 - django

I'd like to upgrade an existing application to a more recent version of django. In 1.4 they changed the password hashing algorithm such that all my old passwords will no longer match when people try to login. Is there some way to upgrade but not require users to reset their passwords?

according to https://docs.djangoproject.com/en/dev/topics/auth/passwords/#auth-password-storage it will still check everything as usual.
if you are worried about storing everything as SHA1 by default, then put the hasher first in the list (this is not recommended though).
# settings.py
PASSWORD_HASHERS = (
'django.contrib.auth.hashers.SHA1PasswordHasher',
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
...
)
if you need to check for yourself, you can consider using virtualenv with the newer django==1.5 package and create a dummy project/app connected to the same database to try it out. If you have admin privileges and already use the admin interface, you can use that to login there.

I did the same upgrade last month and Django passwords still fully functional. The changes I made are basically in generic views( now all generic views are class based) , The logging in settings.py was changed and I have to put a ALLOWED_HOSTS list. For example: ALLOWED_HOSTS = ['.stackoverflow.com']
Particularly, I changed my urls calls cause I was using named urls without quotes in url tags and it's no longed supported by django. The right way is like this: {% url 'name_of_the_view' arg1 arg2%}
I suggest you to create another environment and try use django 1.5 just making this small changes.

Related

Django - 'myapp' vs 'myapp.apps.myappConfig' in settings.py Installed Apps

I know this might sound stupid but I was just wondering what's the difference if I just type 'myapp' instead of 'myapp.apps.myappConfig' in my Installed Apps list. Is it something related to models or what?
Regards
If you use myapp.apps.myappConfig, then you are explicitly telling Django to use that app config class.
Changing the app config class lets you change the behaviour of the application, for example, when you use the admin app, you can use django.contrib.admin.apps.AdminConfig which autodiscovers apps, or django.contrib.admin.apps.SimpleAdminConfig, which does not.
If you just use myapp, then Django will try to use default_app_config. If that isn't set, then it will use the default AppConfig.
A lot of the time, there isn't any customisation in myappConfig, or default_app_config is set, so you'll get the same behaviour whichever style you use in INSTALLED_APPS.
Ever since AppConfig was added in Django 1.7, the recommendation has been to use ``myapp.apps.myappConfigbecause it's explicit, and avoid usingdefault_app_config`.
However, in practice, it seems that users have preferred the simplicity of using myapp. Therefore, there's an open pull request which will remove default_app_config, and automatically select the app config class when there is only one.

django project derived from python-socketio django example unable to server other URLs (at least in django 1.11)

After playing with python-socketios django_example, and seeing that it worked great, I created a new django project, configured it just like the example, copied over the example app to the project (complete with it's overriding of the runserver management command). Everything worked fine, and I was able to make my a few changes so that you can set a nick, some redis stuff to lookup up the sid for a nick, and was able to support sending private messages to a nick. Everything was still working great.
I figured the next logical step was to, rather than having to manually set a nick, require the user to login, expose their username as a var in a script block in the template (I moved scripts/index.html to templates/index.html), and automatically have the javascript emit my custom 'set_nick' event with the username automatically upon connect.
I defined LOGIN_URL = '/accounts/login' in settings.py, included 'django.contrib.auth.urls' in my urls.py and wrapped the index view with #login_required.
It was only then that I noticed that no matter what URL you request, you always get the chat apps index view - no login page redirect, '/admin/' is ignored, etc.
EDIT Solved - See my answer below.
I noticed that the urls.py which I blindly copied over from the example looked like this:
url(r'', include('socketio_app.urls')),
url(r'^admin/', admin.site.urls),
and the r'' was the culprit (matches everthing). Changing this to:
url(r'^/', include('socketio_app.urls)),
url(r'^admin/', admin.site.urls),
However, I'm using Django==1.11. I believe Django 2 tends to suggest using path (or some similarly named function) rather than using url. I don't believe, however, that the semantics of url are different in Django 2, so this is probably an issue for Django 2 users as well.

Django Mixing State Between Forms

I have a strange issue I've never seen before and I'm a bit stuck at where to go next.
We have a fairly standard Django app, with some forms using class based views, and we're finding that state is getting mixed between forms in strange ways.
For example, User A is on the site and fills out form X and sets their postcode.
User B goes to another form altogether, form Y, but the postcode field is already populated with User A's postcode.
The fields share the same name, but are on totally independent forms. The field in this example is a standard Django CharField.
I haven't managed to replicate this behaviour using the Django dev server locally from a little trying. I've upgraded gunicorn to latest version, I've set it to use a single worker, I've disabled caching everywhere in the Django project that I can find.
It's stuck on Django 1.3.7, and it's not a trivial app to upgrade to a supported version. It's running with gunicorn 18 behind nginx.
I've noted the Django mentions of thread safety in class based views, but I don't see us passing any mutable objects to the view, and it's all a fairly plan view and ModelForm. Django's session store is the default (it was previously something else but I removed that to use the Django default which I believe is the db).
Any ideas where to go next to try and figure this out?
Thanks!
Figured it out - turns out it was to do with the behaviour of get_initial in 1.3, which was changed in Django 1.4
https://docs.djangoproject.com/en/dev/releases/1.4/#formmixin-get-initial-returns-an-instance-specific-dictionary
We changed our get_initial to use a copy of the dict rather than the default implementation, and now all is well :)

django: modifying/extending 3rd party apps

a newbie django question
I want to use 3rd party app, but I need to make some mods to it (in this case, the app is django-registration, and I need to change things such as allowing registration without confirmation email)
Initially, I simply installed the app in the general site-packages folder, and changed the code there. Now that I put my code on bitbucket I need a way to be able to keep my mods in the repository in a usable way, and uploading the full python code doesn't sound like a good idea.
I guess the best way would be to keep the 3rd party app in site-packages, and create an app in my project to keep my changes. In my case, I'd create my-django-registration in my project, and then import this when I need it in my code, rather than django-registration.
I also read about virtualenv, but I think that's mostly used for being able to use multiple environments in the same machine (in fact, somewhere it advises against changing the modules installed in the virtualenv), and doesn't help me with keeping my changes in a repository.
Any comments welcome!
Thanks
In general, you should reuse and override the behavior in 3rd party apps and not modify their sources.
What you'll most often encounter is that apps ship models that may not necessarily cover your needs, but do most of the work; you'll have forms that are almost perfect, but need that little something; you'll have views that would be perfect if you can just change one thing; you'll have URLs that are sane, but you need something more from them.
In most cases, that would just require that you create a custom app and rewire everything. Ship your own URLs that map to views that you've extended and overrode methods for custom behavior; supply it with a model form who's Meta is using the new model that you've extended from the original; so forth...
That's just the tip of the iceberg of what you can do, there's more ways when your creative. I can give you an example of how I've used the RegistrationProfile model, but shipped my own URL patterns and a custom class-based view that handled the registration process.
Now, where virtualenv comes into play is that you'll most likely be using pip to specify and supply your required dependencies in the requirements file format. That's when you want to say: "I've extended the django-registration app, but it won't work cleanly with just any version. It has to be of release X", or , "a checkout from the repository of commit Y".
This blog post that adresses this issue is extremely helpful. For convenience I copy-paste it here:
You don’t touch external app code
You are not supposed to edit the code from an external app. Unless you fork it first on github.
So, how to override without forking:
Overriding a template
If you want to override templates/userena/activate_fail.html, then all you have to do is create your own templates/userena directory and make your own activate_fail.html in it.
Overriding a url
Probably the first thing you should check in an external app is its urls.py. Views that are properly coded should support plenty of arguments. For example, userena has a signup view with such a signature (at the time of writing):
def signup(request, signup_form=SignupForm,
template_name='userena/signup_form.html', success_url=None,
extra_context=None):
This means that you can replace the form used by the signup view. To do so, open your urls.py, add what we are going to need at the top:
from userena import views as userena_views
from yourforms import YourSignupForm
Then, find the include the external app’s urls, something like:
url(r'^userena/', include('userena.urls')),
Before that, add your url override:
url(r'^userena/signup/$', userena_views.signup, {'signup_form': YourSignupForm}, name='userena_signup'),
url(r'^userena/', include('userena.urls')),
Now, your custom url definition will be the first to be hit when a visitor hits /userena/signup/. Which means that /userena/signup/ will use YourSignupForm instead of userena’s signup form.
This trick works with any view argument. The ones you should see the most often are:
template_name: lets you change the template name
extra_context: lets you add a dict that will be added to the
context
Almost every view should have these arguments.
Overriding a view
Overriding a view requires to override the url of the view you want to replace. If you want your own signup view to be used, then just override the url:
import yourviews
# ...
url(r'^userena/signup/$', yourviews.yoursignup, name='userena_signup'),
url(r'^userena/', include('userena.urls')),
Decorating a view
Decorating a view is like overriding a view, but reuses the external app’s view. Basically, it’s the same than overriding a view (see above), but your view will look like this
from userena import views as userena_views
def yoursignup(request):
# do stuff before userena signup view is called
# call the original view
response = userena_views.signup(request)
# do stuff after userena signup view is done
# return the response
return response
Forking an app
If you are not familiar with pip and virtualenv first, please read the post about using pip and virtualenv first.
For example:
You installed django-userena as such: pip install django-userena
First you should uninstall it: pip uninstall django-userena
Then go on the app’s github page
Click on the fork button
This will make you a repository with a copy of django-userena
Install it as such: pip install -e
git+git#github.com:your-username/django-userena.git#egg=django-userena
Then you can edit the code in yourenv/src/django-userena
Push your commits
Credits to the post writer!
I think the neatest way to accomplish what you look for would be to fork django-registration, and in your app use the fork instead of the original project.
That being said, you can have a non-email registration in django-registration without changing the code of the app. I've done it by creating a custom registration backend that sets the users as activated upon creation. Here you can see other ways to do the same.

How to disable django.contrib.auth completely?

Because I'm using my own authentication and authorization system (with my own User/Permission model), I would like to completely disable this standard app from Django.
I've tried removing the relevant lines from MIDDLEWARE_CLASSES and
INSTALLED_APPS, but when I use the syncdb command, the default tables
that come with the default authentication system are still being
created. Is there a way to prevent this from happening? My main problem is that the standard tables are overriding the tables that I want to use for my own auth system.
INSTALLED_APPS = (
'django.contrib.sessions',
'form_utils',
'org',
'auth',
'entities',
)
I have also tried prepending the apps with the project package, this had no effect.
Is there maybe another setting that I'm overlooking? Other possible
variables that could cause these standard apps to be enabled despite
my efforts?
I also don't use the built-in admin system, so I don't think that
could be a problem.
Additional information: I have recently upgraded Django 1.2 to 1.3. Could this be the cause of my problem?
Edit: Apparently, this issue is caused by a change in Django 1.3. The related ticket is here: http://code.djangoproject.com/ticket/15735
Any hints?
I believe that the authentication module is being pulled in by RequestContext.
By default, the setting TEMPLATE_CONTEXT_PROCESSORS includes django.contrib.auth.context_processors.auth.
I didn't have the issue of django creating the auth database tables, but it was inserting an AnonymousUser object into my context and my session under the 'user' key, even though I'd removed the auth modules from my INSTALLED_APPS and MIDDLEWARE_CLASSES settings.
I removed that item from TEMPLATE_CONTEXT_PROCESSORS and things started working the way I had been expecting.
The upgrade from 1.2 to 1.3 in your case might have meant you started using class-based generic views (which are awesome), or perhaps you otherwise started using RequestContext instead of ordinary context dicts. Either way, it seems that when auth is given as a context processor, django behaves as though auth were in your installed apps, whether you actually wanted it there or not.
I hope this is of assistance.