text:
= Backwards-incompatible changes = This section of the Django wiki documents all backwards-incompatible changes to Django from 0.96 to 1.0. '''If you're already running Django 1.0, you need not worry about anything on this page.''' Django historians, you can view pre-0.96 changes on the OlderBackwardsIncompatibleChanges page. For changes '''after version 1.0''', which are kept to a minimum due to our [http://docs.djangoproject.com/en/dev/misc/api-stability/ API stability policy], including changes in trunk, see the [http://docs.djangoproject.com/en/dev/releases/ release notes] in the official documentation. For future changes, see the [http://docs.djangoproject.com/en/dev/internals/deprecation/ Deprecation Timeline] [[TOC(inline, depth=1)]] == Changed 'spaceless' template tag to remove all spaces == As of [4885], the {{{spaceless}}} template tag removes *all* spaces between HTML tags instead of preserving a single space. For example, for this template code: {{{ {% spaceless %}
Foo{% endspaceless %} }}} The old output was this: {{{
Foo}}} The new output is this: {{{
Foo}}} As always, {{{spaceless}}} only affects space *between* HTML tags, not space within HTML tags or space in plain text. == Renamed `localflavor.usa` to `localflavor.us` == As of [4954], `localflavor.usa` has been renamed `localflavor.us`. This change was made to match the naming scheme of other local flavors. == Removed `LazyDate` == The `LazyDate` helper class was removed in [4985]. Default field values and query arguments can both be callable objects, so instances of `LazyDate` can be replaced with a reference to a callable that evaluates to the current date (i.e., `datetime.now`). For example, the following model using `LazyDate`: {{{ #!python class Article(models.Model): title = models.CharField(maxlength=100) published = models.DateField(default=LazyDate()) }}} can be redefined as: {{{ #!python from datetime import datetime class Article(models.Model): title = models.CharField(maxlength=100) published = models.DateField(default=datetime.now) }}} Note that the new model definition refers to the name of the `datetime.now()` function, but doesn't actually call the function. The call to `datetime.now()` is deferred until the value is actually required (i.e., when the model is saved). == MySQL Introspection Change == In [5042] a small change was made in the `mysql` backend in how it interpreted `CHAR(n)` columns in the database. They are now mapped to Django's !CharField class, rather than the previous !TextField. See ticket #4048 for details. This will only be apparent if you introspect a database table using 0.96 and again using [5042] or later: you will have slightly different Django models generated if there are any `CHAR(n)` columns. However, no real code changes should be necessary. == LOGIN_URL is now a setting == In [5072], we moved the LOGIN_URL constant from django.contrib.auth into the settings module. This was part of a broader change to make these URLs (including logout and post-login redirect) configurable. Code that previously read {{{ #!python from django.contrib.auth import LOGIN_URL }}} should be changed to refer to `settings.LOGIN_URL` instead. == Test Client `login()` method changed == The implementation of `django.test.Client.login()` operated as a wrapper around a series of GET and POST calls accessing a nominated login URL. This approach was fragile, and tightly bound to specific templates and login mechanims. In [5152], we changed the implementation of the `login()` method on the test Client. `login()` now accepts a list of credentials, and exercises these credentials directly on the cookies and Session objects of a site, without accessing or using a login page. This breaks the dependence on specific template formatting, and enables the login mechanism to work with any authentication backend, and any login decorator. Existing uses of `login()`, e.g.: {{{ #!python c = Client() c.login('/path/to/login','myuser','mypassword') }}} should be modified to read: {{{ #!python c = Client() c.login(username='myuser', password='mypassword') }}} The keyword arguments `username` and `password` *must* be given explicitly. If an alternate authentication scheme is in use, the credentials required by that scheme can be provided instead of `username` and `password`. == Generic relations have moved == In [5172], the various generic relation classes (!GenericForeignKey and !GenericRelation) have moved into the django.contrib.contenttypes module. This is because they will not work if contenttypes is not an installed app. Making the import path reflect the dependency should help remind people of this. Code using generic relations should change from saying things like {{{ #!python generic_field = models.GenericRelation(SomeOtherModel) }}} to using {{{ #!python from django.contrib.contenttypes import generic ... generic_field = generic.GenericRelation(SomeOtherModel) }}} No database changes or other model changes are required. == Newforms: clean_data changed to cleaned_data == If you are accessing form data that has been cleaned in newforms, you could previously use the {{{clean_data}}} attribute on the form. In [5237], this was changed to {{{cleaned_data}}} to avoid a name-clash (see [5231] for why the change was necessary). You will need to do a search-and-replace in your form code and replace clean_data with cleaned_data everywhere. == Test client removed special casing for file uploads == Before [5465], Django's client in the testing infrastructure had special casing for file uploads that matched the implementation of the !FileField datatype, making it simpler to use for this case. To allow for different methods of uploading files (e.g. newforms and oldforms), this has been removed--you will have to update your tests if you depended on this behavior (look at the HTML source to work out what the field names for posted data should be). == Renamed !FloatField to !DecimalField == In [5302], we fixed a slight inconsistency in Django's model field system. Previously, we had a !FloatField that had a maximum number of digits and decimal places. However, although it was stored in the database as a fixed precision value, it was stored in Python as a float, so precision was lost due to rounding problems. We now have a !DecimalField class that is the same as the old !FloatField, except that it is represented in Python by a Decimal type (and still stored as a fixed precision value in the database). We have also introduced a proper !FloatField that is represented as a float in Python and stored as a "double precision" field in the database. To make your code compatible with these changes, you need to change all occurrences of !FloatField in your code to !DecimalField. You only need to rename the field type -- all the parameters are the same. So change {{{ #!python class MyModel(models.Model): ... field_name = models.FloatField(max_digits=10, decimal_places=3) # old code! }}} to {{{ #!python class MyModel(models.Model): ... field_name = models.DecimalField(max_digits=10, decimal_places=3) # new code! }}} If you forget to make this change, you will see errors about !FloatField not taking a max_digits attribute in {{{__init__}}}, since the new !FloatField takes no precision-related arguments. If you are using MySQL or PostgreSQL, there are '''no further changes needed'''. The database column types for !DecimalField are the same as for the old !FloatField. If you are using SQLite, you need to force the database to view the appropriate columns as decimal types, rather than floats. To do this, follow this procedure for every application you have that contains a !DecimalField. Do this ''after'' you have made the change to using !DecimalField in your code and updated the Django code. '''Warning: Back up your database first! ''' For SQLite, this means making a copy of the single file that stores the database (the name of that file is the DATABASE_NAME in your settings.py file). For every application using a !DecimalField, do the following. We will use applications called {{{some_app}}} and {{{another_app}}} in this example {{{ ./manage.py dumpdata --format=xml some_app another_app > data-dump.xml ./manage.py reset some_app another_app ./manage.py loaddata data-dump.xml }}} Notes: 1. It is important that you remember to use XML format in the first step of this process. We are exploiting a feature of the XML data dumps that makes porting floats to decimals with SQLite possible. 2. In the second step you will be asked to confirm that you are prepared to lose the data for the application(s) in question. We restore this data in the third step, of course. 3. !DecimalField is not used in any of the apps shipped with Django prior to this change being made, so you do not need to worry about performing this procedure for any of the standard Django applications. If something goes wrong in the above process, just copy your backed up database file over the top of the original file and start again. == Urlpatterns now cached == In [5516], a speed improvement was made for reverse URL lookups, particularly. Part of this involved caching information that was unlikely to change: the {{{urlpatterns()}}} contents. If you were somehow relying on the fact that you could change your {{{urls.py}}} files and not have to restart Django, you can no longer do that. Edits require a restart. == Unicode merge == In [5609], the UnicodeBranch was merged into trunk. For any installations using ASCII data, this is fully backwards compatible. If you were using non-ASCII data, Django would have behaved unreliably in some cases previously and so backwards-compatibility was neither completely possible nor desirable. However, some people may have been able to get by with non-ASCII data successfully. They might now experience some different errors to previously. Porting code to work correctly with non-ASCII data is fairly simple. Follow [http://code.djangoproject.com/wiki/UnicodeBranch#PortingApplicationsTheQuickChecklist this checklist] for fastest results. == Changed {{{__init__()}}} parameters in syndication framework's Feed class == In [5654], we changed the {{{Feed}}} class' {{{__init__()}}} method to take an {{{HttpRequest}}} object as its second parameter, instead of the feed's URL. This allows the syndication framework to work without requiring the sites framework. This only affects people who have subclassed {{{Feed}}} and overridden the {{{__init__()}}} method, and people who have called {{{Feed.__init__()}}} directly from their own code. {{{Feed.__init__()}}} had not been documented. == PO files must be UTF-8 encoded == In [5708] we added the ability to use non-ASCII strings as input to the translation framework. This was a frequently requested feature by developers whose original strings were not in English. A consequence of this change is that we have to specify the encoding of the PO files (the files used by translators to create translations). Following common practice in other projects, we have chosen UTF-8 as the encoding. This change only affects third-party developers who are using Django's make-messages.py script to extract their strings for their own PO files. The PO files will need to be saved and edited as UTF-8 files and the ''charset'' set correctly in the header of the file. All of Django's core translation files already satisfy this requirement. Note that existing code and message catalogs will not break even if you update your code to [5708] or later. This change only takes effect the next time you run make-messages.py. == Added `interactive` argument to `run_tests` == In [5752] the parameter `interactive` was added to the run_tests method. This parameter allows tests to be added to automated build scripts where interactive questions (such as being asked if it is ok to delete an existing test database) cannot be asked. If you are using the default Django test runner, no change is required. However, if you have defined a custom test runner, you must be able to accept (and handle appropriately) the `interactive` argument to the test runner. For most test runners, the only change required will be to change the call to `create_test_db` to use the keyword argument `autoclobber=not interactive`. == Changed format for first argument to `run_tests` == In [5769], the first argument to `run_tests` was changed to allow end-users to invoke individual tests, rather than requiring that entire applications be tested. This change has no effect on most end users. However, it does require a significant change to the prototype of run_test, which will be backwards incompatible for anyone with a customized test runner. Previously, the first argument to `run_tests` was a list of application modules. These modules would then be searched for test cases. After [5769], the first argument to `run_tests` is a list of test labels. Whereas run_tests was previously given a list of already-loaded applications, it is now the responsibility of the test runner to load the appropriate applications. Anyone with a customized test runner will need to incorporate the appropriate calls to `get_app()` as part of their test runner. == Minor change to newforms arguments and data dictionary handling == In [5819], `FileField` and `ImageField` were added to newforms. Implementing these fields required some subtle changes to the way data binding occurs in newforms. This change will have no effect on most end users. The simple cases for binding forms do not change. However: * The second argument to a form instance is now taken by file data. As a result, if you implicitly relied upon the order of the keyword arguments `auto_id`, `prefix` and `initial` when instantiating forms, your forms will no longer interpret these options correctly. To overcome this problem, explicitly name these keyword arguments - for example, use: {{{ f = ContactForm(data, auto_id=True) }}} rather than: {{{ f = ContactForm(data, True) }}} * A `files` argument was added to the prototype for `value_from_datadict()` to allow for the processing of file data. If you have written any custom widgets that provide their own data dictionary handling, you will need to modify those widgets to accomodate the new argument. If your custom widget has no need to handle file data, all you will need to do is change the method definition from: {{{ def value_from_datadict(self, data, name): }}} to: {{{ def value_from_datadict(self, data, files, name): }}} == Changes to management.py commands == In [5898], we refactored {{{management.py}}}. This was partially to clean up a 1700-line file, but also to allow user applications to register commands for use in {{{management.py}}}. As a result, any calls to management services in your code will need to be adjusted. For example, if you have some test code that calls {{{flush}}} and {{{load_data}}}: {{{ >>> from django.core import management >>> management.flush(verbosity=0, interactive=False) >>> management.load_data(['test_data'], verbosity=0) }}} You will need to change this code to read: {{{ >>> from django.core import management >>> management.call_command('flush', verbosity=0, interactive=False) >>> management.call_command('loaddata', 'test_data', verbosity=0) }}} == Refactored database backends == In a series of commits from [5949] to [5982], we refactored the database backends (the code in {{{django.db.backends}}}) to remove quite a bit of duplication, make it easier to maintain and extend, and to lay the groundwork for advanced features such as database connection pooling. As a result, almost *all* of the backend-level functions have been renamed and/or relocated. None of these were documented, but you'll need to change your code if you're using any of these functions: || '''Old name/location''' || '''New name/location''' || || {{{django.db.backend.get_autoinc_sql}}} || {{{django.db.connection.ops.autoinc_sql}}} || || {{{django.db.backend.get_date_extract_sql}}} || {{{django.db.connection.ops.date_extract_sql}}} || || {{{django.db.backend.get_date_trunc_sql}}} || {{{django.db.connection.ops.date_trunc_sql}}} || || {{{django.db.backend.get_datetime_cast_sql}}} || {{{django.db.connection.ops.datetime_cast_sql}}} || || {{{django.db.backend.get_deferrable_sql}}} || {{{django.db.connection.ops.deferrable_sql}}} || || {{{django.db.backend.get_drop_foreignkey_sql}}} || {{{django.db.connection.ops.drop_foreignkey_sql}}} || || {{{django.db.backend.get_fulltext_search_sql}}} || {{{django.db.connection.ops.fulltext_search_sql}}} || || {{{django.db.backend.get_last_insert_id}}} || {{{django.db.connection.ops.last_insert_id}}} || || {{{django.db.backend.get_limit_offset_sql}}} || {{{django.db.connection.ops.limit_offset_sql}}} || || {{{django.db.backend.get_max_name_length}}} || {{{django.db.connection.ops.max_name_length}}} || || {{{django.db.backend.get_pk_default_value}}} || {{{django.db.connection.ops.pk_default_value}}} || || {{{django.db.backend.get_random_function_sql}}} || {{{django.db.connection.ops.random_function_sql}}} || || {{{django.db.backend.get_sql_flush}}} || {{{django.db.connection.ops.sql_flush}}} || || {{{django.db.backend.get_sql_sequence_reset}}} || {{{django.db.connection.ops.sequence_reset_sql}}} || || {{{django.db.backend.get_start_transaction_sql}}} || {{{django.db.connection.ops.start_transaction_sql}}} || || {{{django.db.backend.get_tablespace_sql}}} || {{{django.db.connection.ops.tablespace_sql}}} || || {{{django.db.backend.quote_name}}} || {{{django.db.connection.ops.quote_name}}} || || {{{django.db.backend.get_query_set_class}}} || {{{django.db.connection.ops.query_set_class}}} || || {{{django.db.backend.get_field_cast_sql}}} || {{{django.db.connection.ops.field_cast_sql}}} || || {{{django.db.backend.get_drop_sequence}}} || {{{django.db.connection.ops.drop_sequence_sql}}} || || {{{django.db.backend.OPERATOR_MAPPING}}} || {{{django.db.connection.operators}}} || || {{{django.db.backend.allows_group_by_ordinal}}} || {{{django.db.connection.features.allows_group_by_ordinal}}} || || {{{django.db.backend.allows_unique_and_pk}}} || {{{django.db.connection.features.allows_unique_and_pk}}} || || {{{django.db.backend.autoindexes_primary_keys}}}|| {{{django.db.connection.features.autoindexes_primary_keys}}} || || {{{django.db.backend.needs_datetime_string_cast}}}||{{{django.db.connection.features.needs_datetime_string_cast}}} || || {{{django.db.backend.needs_upper_for_iops}}} || {{{django.db.connection.features.needs_upper_for_iops}}} || || {{{django.db.backend.supports_constraints}}} || {{{django.db.connection.features.supports_constraints}}} || || {{{django.db.backend.supports_tablespaces}}} || {{{django.db.connection.features.supports_tablespaces}}} || || {{{django.db.backend.uses_case_insensitive_names}}} || {{{django.db.connection.features.uses_case_insensitive_names}}} || || {{{django.db.backend.uses_custom_queryset}}} || {{{django.db.connection.features.uses_custom_queryset}}} || == archive_year generic view no longer performs an order_by() on the passed queryset == In [6057], {{{archive_year}}} was changed NOT to perform an {{{order_by()}}} on the passed queryset. This is for consistancy with the other date-based generic views. Update your code by performing an explicit {{{order_by()}}} on the {{{QuerySet}}} you pass to {{{archive_year}}} or add an {{{ordering}}} option to your model's {{{class Meta}}}. == django-admin.py and manage.py now require subcommands to precede options == In [6075], {{{django-admin.py}}} and {{{manage.py}}} were changed so that any options (e.g., {{{--settings}}}) must be specified *after* the subcommand (e.g., {{{runserver}}}). This used to be accepted: {{{django-admin.py --settings=foo.bar runserver}}} Now, options must come after the subcommand: {{{django-admin.py runserver --settings=foo.bar}}} == django.views.i18n.set_language requires a POST request == In [6177], the {{{set_language()}}} view was changed to only change the caller's locale if called as a POST request. Previously, a GET request was used. The old behaviour meant that state (the locale used to display the site) could be changed by a GET request, which is against the HTTP specification's recommendations. Code calling this view must ensure that a POST request is now made, instead of a GET. This means you can no longer use a link to access the view, but must use a form submission of some kind (e.g. a button). == django.http.!HttpResponse now has case-insensitive headers == In a number of changes starting with [6212], {{{HttpResponse}}} headers were made case-insensitive. As a side-effect, could break code that accesses {{{response.headers}}} directly, and specifically broke the idiom {{{if header in response.headers:}}}. So {{{response.headers}}} has been renamed to {{{response._headers}}}, and {{{HttpResponse}}} now supports containment checking directly. You should now use {{{if header in response}}} instead of {{{if header in response.headers}}}. == Template tag loading respects dotted notation == In [6289], template tag loading was altered to respect dotted paths, just like Python imports. So {{{ {% load foo.bar %} }}} will now look for a file {{{foo/bar.py}}} under one of your templatetag directories. Previously, anything before the final dot was ignored. If you were using this for any decorative purpose (at least one package was, it turns out), you have to remove any unwanted prefix. == _() no longer in builtins == As of [6582], we no longer unconditionally install {{{_()}}} as an alias for {{{gettext()}}} in Python's builtins module. The reason for this is explained in the initial note in [http://www.djangoproject.com/documentation/i18n/#in-python-code this section] of the [http://www.djangoproject.com/documentation/i18n/ internationalization documentation]. If you were previously relying on {{{_()}}} always being present, you should now explicitly import {{{ugettext}}} or {{{ugettext_lazy}}} or even {{{gettext}}}, if appropriate, and alias it to {{{_}}} yourself: {{{ #!python from django.utils.translation import ugettext as _ }}} == `django.newforms.forms.SortedDictFromList` class removed == In [6668], the `SortedDictFromList` class was removed. Due to `django.utils.datastructures.SortedDict` gaining the ability to be instantiated with a sequence of tuples (#5744), `SortedDictFromList` was no longer needed. Two things need to be done to fix your code: 1. Use `django.utils.datastructures.SortedDict` wherever you were using `django.newforms.forms.SortedDictFromList`. 1. Since `SortedDict`'s copy method doesn't return a deepcopy as `SortedDictFromList`'s `copy` method did, you will need to update your code if you were relying on `SortedDictFromList.copy` to return a deepcopy. Do this by using `copy.deepcopy` instead of `SortedDict`'s `copy` method. == Auto-escaping in templates == In [6671] a long-awaited feature was committed to make default HTML template usage a bit safe from some forms of cross-site scripting attacks. For full details, read the [http://docs.djangoproject.com/en/dev/topics/templates/#automatic-html-escaping template author documentation] and the [http://docs.djangoproject.com/en/dev/howto/custom-template-tags/#filters-and-auto-escaping template filter documentation]. Automatic HTML escaping (henceforth ''auto-escaping'') affects any variables in templates. It is only applied to variables and not to template tags. {{{ {{ a_variable }} -- This will be auto-escaped. {{ variable|filter1|filter1 }} -- so will this {% a_template_tag %} -- This will not be; it's a tag }}} Also note that the {{{escape}}} filter's behaviour has changed slightly (it is only applied once and only as the last thing done to the output) and new filters {{{force_escape}}} and {{{safe}}} have been introduced if you need them. If you never intentionally insert raw HTML into your context variables, and if all your templates are supposed to output HTML, no changes will be needed. If you have any variables in your templates that do insert raw HTML output and you do ''not'' want this output automatically escaped, you will need to make some changes. There are two approaches here, the first one being the easiest (but not the safest) and can act as a temporary step whilst you do the more detailed second step. 1. '''Simple backwards compatibility:''' In every root template (such as your `base.html` template), wrap the entire contents in tags to disable auto-escaping: {{{ {% autoescape off %} ... normal template content here ... {% endautoescape %} }}} If one template extends from another template, the auto-escaping behaviour from the root template (the one in the {{{ {% extends ... %} }}} tag) will be inherited. So you only need to add these tags to your root templates. This is also the recommended approach for templates that produce, say, email messages or other non-HTML output. The `autoescape` template tag exists for this reason. Finally, change all calls to the 'escape' function to use 'force_escape' instead. The drawback of this method in templates that are destined for HTML output is that you receive none of the benefits of auto-escaping. 2. '''More detailed porting to take advantage of auto-escaping:''' There are two approaches to inserting raw HTML via variables into templates. One option is to pass the variable content through the {{{safe}}} filter. This tells the renderer not to auto-escape the contents: {{{ {{ variable_with_html|safe }} -- will not be auto-escaped. }}} The second and probably more robust way is to use {{{mark_safe()}}} where appropriate (see [http://docs.djangoproject.com/en/dev/howto/custom-template-tags/#filters-and-auto-escaping the documentation] for details) and go through each of your custom filters attaching {{{is_safe}}} and {{{needs_autoescape}}} attributes where necessary (again, the details are in the above documentation). Have a look at Django's default filters (in {{{django/template/defaultfilters.py}}}) for examples of how mixed filters (those which behave differently depending upon whether auto-escaping is in effect or not) can be written. The attributes on filter functions and the new {{{escape}}} behaviour mean that you can write templates and filters that will operate correctly in both auto-escaping and non-auto-escaping environments, so you're not forcing your decision onto users of your filters, if you distribute the code. == Removed unused session backend functions == In [6796] a couple of session backend functions that are no longer needed were removed. In the unlikely event your code was using {{{get_new_session_key()}}} or {{{get_new_session_object()}}}, you will need to switch to using {{{SessionBase._get_new_session_key()}}}. == Settings exception types changed == In [6832] we changed the possible exceptions raised when initializing Django's settings in order not to interfere with Python's {{{help()}}} function. If there is a problem such as not being able to find the settings module (via the {{{DJANGO_SETTINGS_MODULE}}} environment variable, for example), an `ImportError` is now raised (previously it was `EnvironmentError`). If you try to reconfigure settings after having already used them, a `RuntimeError` is raised (rather than the previous `EnvironmentError`). See #5743 for the details of this change. == Generic views' empty defaults == In [6833] the {{{allow_empty}}} parameter to the {{{archive_index()}}} and {{{object_list()}}} generic views were changed to be True by default. So viewing a list of objects that is empty will not raise a 404 HTTP error. Things like date-based views still raise a 404 when there is nothing to view (by default), since viewing a non-existent date is usually going to be an error. See #685 for details. == `MultipleObjectsReturned` exception instead of `AssertionError` == In [6838], `QuerySet.get()` was changed to raise a `MultipleObjectsReturned` exception rather than an assertion error when multiple objects are returned. Before: {{{ #!python try: Model.objects.get(...) except AssertionError: ... }}} After: {{{ #!python try: Model.objects.get(...) except Model.MultipleObjectsReturned: ... }}} == Change to APPEND_SLASH behaviour == Prior to [6852], if a URL didn't end in a slash or have a period in the final component of it's path, and {{{APPEND_SLASH}}} was True, Django would redirect to the same URL, but with a slash appended to the end. Now (from [6852] onwards), Django checks to see if the pattern without the trailing slash would be matched by something in your URL patterns. If so, no redirection takes place, because it is assumed you deliberately wanted to catch that pattern. For most people, this won't require any changes. Some people, though, have URL patterns that look like this: {{{ #!python r'/some_prefix/(.*)$' }}} Previously, those patterns would have been redirected to have a trailing slash. If you always want a slash on such URLs, rewrite the pattern as {{{ #!python r'/some_prefix/(.*/)$' }}} Now {{{/some_prefix/foo}}} will not match the pattern and will be redirected to {{{/some_prefix/foo/}}}, which will match. Your view function will be passed {{{foo/}}}, just as it was prior to [6852]. == !ModelForm's constructor now matches Form's == {{{instance}}} was moved from the first argument in {{{ModelForm}}}'s {{{__init__}}} method to the last. Also, {{{ModelForm}}} will instantiate a new model object if you don't give it an instance. The model it generates is specified by the {{{ModelForm}}}'s inner {{{Meta}}} classes {{{model}}} attribute. See #6162 for details. Before: {{{ #!python # for add forms obj = MyObj() form = MyForm(obj) # for change forms obj = MyObj.objects.get(pk=1) form = MyForm(obj) }}} After: {{{ #!python # for add forms form = MyForm() # for change forms obj = MyObj.objects.get(pk=1) form = MyForm(instance=obj) }}} == Raise errors if extends is not the first tag of a template == In [7082] we removed the possibility of putting extends below other tags (in [7089]). You may still put it below comment tags or whitespace. Otherwise it will raise a !TemplateSyntaxError. This is not technically a backward incompatible change because documentation has always specified that [http://docs.djangoproject.com/en/dev/topics/templates/#template-inheritance extends tags should be placed first in your templates], but it may break your code if you haven't followed those instructions. == Change es_AR to es-ar in LANGUAGES == In [7091] we fixed a bug that was inadvertently introduced recently with regards to parsing language preferences. The LANGUAGES list in the configuration file should use a hyphen to separate the locale main name and the variant (if any). The only slight consequence here is that the Argentinean Spanish was incorrectly specified as es_AR. If you are using Django's default language list, there is no change required, since the central list has been updated and specifying es-ar as the preference in your browser will still work. However, if you have created a custom LANGUAGES list in your settings file, overriding the list in global_settings, you will need to change "es_AR" to read "es-ar", otherwise your Argentinean Spanish readers will see English text, not Spanish. == Changed Field.get_internal_type() default == If you were subclassing an existing model field and were relying on the fact that the {{{Field.get_internal_type()}}} method would return your class name by default, you will need to alter your code to explicitly say that (i.e. to return the string you want). It seemed that most subclassing of existing fields (even in Django core) were using the parent's column type, so we've now set things up to exploit that. Thus, inheriting from a {{{CharField}}} results in {{{get_internal_type()}}} returning ''!CharField'', etc. == Changed decorators to inherit attributes of the function they wrap == If you were using one of Django's decorators and relying on decorated functions/methods to have the name (`__name__`), docstring (`__doc__`), or attributes (`__dict__`) of the decorator, then you need to change your code to work off the name, docstring, or attributes of the decorated function instead. If you are using Python 2.3, you don't need to worry about the changing of the decorated function's name since Python 2.3 does not support assignment to `__name__`. == Removed ado_mssql == The unmaintained `ado_mssql` backend was removed in [7364]. Since external database backends can be used with Django, people wishing to contribute to or utilise Django support on Microsoft's SQL Server should have a look at external projects such as: * http://code.google.com/p/django-mssql/ * http://code.google.com/p/django-pyodbc/ Django's maintainers do not make any recommendations as to which of these (or alternate projects) may be better at this time, since none of us regularly develop on Windows or with SQL Server. == Queryset-refactor merge == In [7477] the [QuerysetRefactorBranch queryset-refactor branch] was merged into trunk. This is mostly backwards compatible, but there are a few points to note. Rather than list them here, refer to the [QuerysetRefactorBranch#Backwardsincompatiblechanges backwards incompatible changes] section on the branch's wiki page. == Tightened up !ForeignKey assignment == [7574] tightened up restrictions on assigning objects to {{{ForeignKey}}} and {{{OneToOne}}} fields (i.e. assignments of the form {{{book.author = someinstance}}}). Specifically, Django will now: * Raise a {{{ValueError}}} if you try to assign the wrong type of object. Previously things like {{{book.author = Vegetable(...)}}} worked, which was insane. * Raise a {{{ValueError}}} if you try to assign {{{None}}} to a field not specified with {{{null=True}}}. * Cache the set value at set time instead of just at lookup time. This avoids race conditions when saving related objects along with their parents and was the original impetus for the change (see #6886). == Removed !OrderingField == In [7794], a model field that had no use was removed (!OrderingField). It was introduced in the magic-removal branch to support a feature that was never completed, so the code isn't useful in Django any longer. == Exact Comparisons Respect Case In MySQL == **This change is no longer applicable. See [#RestoredearlierexactmatchingforMySQL below] for details on when it was changed back.** The documented behaviour of the `__exact` comparison in Django's ORM is that it is case-sensitive. For case-insensitive searches, there is `__iexact`. On some MySQL installations (which includes most default installations), `__exact` was using case-''in''sensitive matching. This was changed in [7798] so that using `__exact` will respect the case of the argument, bringing it into line with all the other database backends. == !BooleanFields in newforms enforce "required" == In [7799], a bug was fixed that meant `required=True` is now enforced by the `newforms.BooleanField`. In this case, "required" means "must be checked" (i.e. must be True). This has been documented for quite a while, but was inadvertently not enforced by the validation code. Since `required=True` is the default behaviour for all form fields, if your code does not set `required=False` on a `BooleanField` and you do not require it to be checked in the HTML form, you will need to change your form definition. == Default User ordering removed == Since the `django.contrib.auth.models.User` class frequently has a lot of rows in the database and is queried often, we have removed the default ordering on this class in [7806]. If your code requires users to be ordered by their name, you will need to manually specify `order_by('name')` in your querysets. Note that the admin interface will still behave the same as prior to this change, since it automatically orders the users by their name, just as before. So no change will be noticable there. == Uploaded file changes == [7814] introduced changes to the way Django handles uploaded files. Most of the changes are in the form of added flexibility and performance (for details, see the [http://www.djangoproject.com/documentation/upload_handing/ upload handling documentation]). However, as part of the change, the representation of uploaded files has changed. Previous, uploaded files -- that is, entries in {{{request.FILES}}} -- were represented by simple dictionaries with a few well-known keys. Uploaded files are now represented by an [http://docs.djangoproject.com/en/dev/topics/http/file-uploads/#uploadedfile-objects UploadedFile object], and thus the file's information is accessible through object attributes. Thus, given {{{f = request.FILES['some_field_name']}}}: || '''Deprecated''' || '''Replacement''' || || {{{f['content']}}} || {{{f.read()}}} || || {{{f['filename']}}} || {{{f.name}}} || || {{{f['content-type']}}} || {{{f.content_type}}} || The old dictionary-style key access is still supported, but will raise a {{{DeprecationWarning}}}. [7859] further cleaned up and clarified this interface. It unfortunatly had to deprecate a couple of things added in [7814]: || '''Deprecated''' || '''Replacement''' || || {{{f.file_name}}} || {{{f.name}}} || || {{{f.file_size}}} || {{{f.size}}} || || {{{f.chunk()}}} || {{{f.chunks()}}} (note the plural) || The old attributes will still work, but will issue deprecation warnings. Finally, [7859] removed the {{{django.newforms.fields.UploadedFile}}} class, unifying the use of {{{django.core.files.uploadedfile.UploadedFile}}} everywhere in Django. This means a few API changes when using a form with a {{{FileField}}}. || '''Deprecated''' || '''Replacement''' || || {{{form.cleaned_data['file_field'].filename}}} || {{{form.cleaned_data['file_field'].name}}} || || {{{form.cleaned_data['file_field'].data}}} || {{{form.cleaned_data['file_field'].read()}}} || == Translation tools now part of `django-admin.py` == In [7844] the tools to extract strings for translations (formerly `make-messages.py`) and compile the PO files (formerly `compile-messages.py`) were moved into `django-admin.py`. The old executables still exist, but raise errors and point the caller towards the correct command to run (both of these files are designed to be run from the command line, not as part of other programs). || '''Old command''' || ''' New ''' || || {{{make-messages.py -l xx}}} || {{{django-admin.py makemessages -l xx}}} || || {{{compile-messages.py -l xx}}} || {{{django-admin.py compilemessages -l xx}}} || The options accepted by the new form are the same as the options accepted by the old commands, only the calling convention has changed (this reduced the number of executables Django has to install). == MySQL_old backend removed == In [7949] we removed the `mysql_old` backend. It was only available for backwards compatibility with a version of `MySQLdb` that was in popular use in some ISPs at the time. Since `MySQLdb-1.2.1p2` was released over 2 years ago and that version, or anything later, works with the `mysql` backend, we have now removed this formerly deprecated backend. == Changes to !ModelAdmin save_add, save_change and render_change_form method signatures == [7923] removed some places where model was being passed around for no reason - this will only affect you if you have custom ModelAdmin subclasses that over-ride those methods. == Generic views use newforms == [7952] makes the create/update generic views use newforms instead of the old deprecated "oldforms" package. You'll probably need to update any templates used by these views. == Merged newforms-admin into trunk == As of [7967] we have merged newforms-admin into trunk. Here is list of things that have changed: A lot has changed in this branch. Let's start with the syntax for URLconfs: {{{ #!python # OLD: from django.conf.urls.defaults import * urlpatterns = patterns('', (r'^admin/', include('django.contrib.admin.urls')), ) # NEW: from django.conf.urls.defaults import * from django.contrib import admin admin.autodiscover() urlpatterns = patterns('', (r'^admin/(.*)', admin.site.root), ) }}} Note that, in this above URLconf example, we're dealing with the object {{{django.contrib.admin.site}}}. This is an instance of {{{django.contrib.admin.AdminSite}}}, which is a class that lets you specify admin-site functionality. The object {{{django.contrib.admin.site}}} is a default {{{AdminSite}}} instance that is created for you automatically, but you can also create other instances as you see fit. We use the {{{admin.autodiscover()}}} call above to force the import of the {{{admin.py}}} module of each {{{INSTALLED_APPS}}} entry. This won't be needed if you use your own {{{AdminSite}}} instance since you will likely be importing those modules explicily in a project-level {{{admin.py}}}. This was added in [7872]. Previously, there was one "global" version of the admin site, which used all models that contained a {{{class Admin}}}. This new scheme allows for much more fine-grained control over your admin sites, allowing you to have multiple admin sites in the same Django instance. === Moved inner-model ```class Admin``` to ```ModelAdmin``` classes === The syntax to define your models in the admin has changed slightly. It is no longer in your model and is instead in an application level ```admin.py``` module. Here is a quick example showing you the change: {{{ #!python # OLD: # models.py from django.db import models class MyModel(models.Model): name = models.CharField(max_length=100) class Admin: pass # NEW: # models.py from django.db import models class MyModel(models.Model): name = models.CharField(max_length=100) # admin.py from django.contrib import admin from myproject.myapp.models import MyModel admin.site.register(MyModel) }}} If your old inner admin class defined options that controlled the behavior of the admin they have moved to class level in a ```ModelAdmin``` class. All options are the same with the exception of the ones noted in this section below. {{{ #!python # OLD: # models.py from django.db import models class MyModel(models.Model): name = models.CharField(max_length=100) class Admin: list_display = ('name',) # NEW: # models.py from django.db import models class MyModel(models.Model): name = models.CharField(max_length=100) # admin.py from django.contrib import admin from myproject.myapp.models import MyModel class MyModelAdmin(admin.ModelAdmin): list_display = ('name',) admin.site.register(MyModel, MyModelAdmin) }}} === Changed Admin.manager option to more flexible hook === The {{{manager}}} option to {{{class Admin}}} no longer exists. This option was undocumented, but we're mentioning the change here in case you used it. In favor of this option, a {{{ModelAdmin}}} class may now define a ```queryset``` method: {{{ #!python class BookAdmin(admin.ModelAdmin): def queryset(self, request): """ Filter based on the current user. """ return self.model._default_manager.filter(user=request.user) }}} === Changed prepopulate_from to be defined in the Admin class, not database field classes === The {{{prepopulate_from}}} option to database fields no longer exists. It's been discontinued in favor of the new {{{prepopulated_fields}}} option in a {{{ModelAdmin}}}. The new {{{prepopulated_fields}}} option, if given, should be a dictionary mapping field names to lists/tuples of field names. This change was made in an effort to remove admin-specific options from the model itself. Here's an example comparing old syntax and new syntax: {{{ #!python # OLD: class MyModel(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=30) slug = models.CharField(max_length=60, prepopulate_from=('first_name', 'last_name')) class Admin: pass # NEW: class MyModel(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=30) slug = models.CharField(max_length=60) from django.contrib import admin class MyModelAdmin(admin.ModelAdmin): prepopulated_fields = {'slug': ('first_name', 'last_name')} admin.site.register(MyModel, MyModelAdmin) }}} === Moved admin doc views into django.contrib.admindocs === The documentation views for the Django admin site were moved into a new package, {{{django.contrib.admindocs}}}. The admin docs, which aren't documented very well, were located at {{{docs/}}} in the admin site. They're also linked-to by the "Documentation" link in the upper right of default admin templates. Because we've moved the doc views, you now have to activate admin docs explicitly. Do this by adding the following line to your URLconf: {{{ #!python (r'^admin/doc/', include('django.contrib.admindocs.urls')), }}} You have to add this line before {{{r'^admin/(.*)'}}} otherwise it won't work. === Renamed 'fields' to 'fieldsets', and changed type of 'classes' value === 'Fields' is used to order and group fields in the change form layout.[[BR]] It is still available in the new admin, but it accepts only a list of fields. [[BR]] In case one uses fieldsets to organize the fields, one needs to use 'fieldsets' instead. [[BR]] Also, if 'classes' is specified in a field specification, then the type of its value needs to be changed from a string to a tuple of strings when migrating to the new 'fieldsets' specification. An example: {{{ #!python # OLD: class MyModelA(models.Model): class Admin: fields = ('field1','field2','field3','field4') class MyModelB(models.Model): class Admin: fields = ( ('group1', {'fields': ('field1','field2'), 'classes': 'collapse'}), ('group2', {'fields': ('field3','field4'), 'classes': 'collapse wide'}), ) # NEW: class MyModelAdmin(admin.ModelAdmin): fields = ('field1', 'field2', 'field3', 'field4') # Renaming is optional class AnotherModelAdmin(admin.ModelAdmin): fieldsets = ( ('group1', {'fields': ('field1','field2'), 'classes': ('collapse',)}), ('group2', {'fields': ('field3','field4'), 'classes': ('collapse', 'wide')}), ) }}} === Inline editing === We have significantly improved working with inlines. Here is an example: {{{ #!python # OLD: class Author(models.Model): name = models.CharField(max_length=100) class Book(models.Model): author = models.ForeignKey(Author, edit_inline=models.TABULAR) title = models.CharField(max_length=100) # NEW: # no longer need the edit_inline database field option above. just remove it. from django.contrib import admin class BookInline(admin.TabularInline): model = Book extra = 3 class AuthorAdmin(admin.ModelAdmin): inlines = [BookInline] admin.site.register(Author, AuthorAdmin) }}} Before you would define an {{{edit_inline}}} database field option and give it the value of the type of inline you wanted, either {{{models.TABULAR}}} or {{{models.STACKED}}}. This is now done with classes and gives you much more flexibility over the options of a specific inline. See [http://docs.djangoproject.com/en/dev/ref/contrib/admin/#inlinemodeladmin-objects the inlines documentation] to learn more. === Refactored inner Admin ```js``` option to media definitions === In [5926] a new method of dealing with media definitions was added. It is now much more flexible and allows media on more than just a {{{ModelAdmin}}} classes. An example: {{{ #!python # OLD: class MyModel(models.Model): # not relavent, but here for show field1 = models.CharField(max_length=100) class Admin: js = ( "/static/my_code.js", ) # NEW: # in admin.py class MyModelAdmin(admin.ModelAdmin): class Media: js = ( "/static/my_code.js", ) }}} One very subtle thing to note is previously with trunk the documentation stated: If you use relative URLs — URLs that don't start with {{{http://}}} or {{{/}}} — then the admin site will automatically prefix these links with {{{settings.ADMIN_MEDIA_PREFIX}}}. Which is still partially true with newforms-admin, but now when using relative URLs {{{settings.MEDIA_URL}}} is prepended and '''not''' {{{settings.ADMIN_MEDIA_PREFIX}}}. If you are still looking for the old behavior you can accomplish it by doing the following: {{{ #!python from django.conf import settings class MyModelAdmin(admin.ModelAdmin): class Media: js = ( settings.ADMIN_MEDIA_PREFIX + "some_file.js", ) }}} Make sure the value of {{{settings.ADMIN_MEDIA_PREFIX}}} is a proper absolute URL otherwise it will be treated the same as a relative URL. === Moved raw_id_admin from the model definition === The syntax is now separated from the definition of your models. An example: {{{ #!python # OLD: class MyModel(models.Model): field1 = models.ForeignKey(AnotherModel, raw_id_admin=True) class Admin: pass # NEW: class MyModelAdmin(admin.ModelAdmin): model = MyModel raw_id_fields = ('field1',) }}} === ```django.contrib.auth``` is now using newforms === ```django.contrib.auth``` has been converted to use newforms as opposed to using oldforms. If you are relying on the oldforms, you will need to modify your code/templates to work with newforms. === Moved radio_admin from the model definition === An example: {{{ #!python # OLD: class MyModel(models.Model): field1 = models.ForeignKey(AnotherModel, radio_admin=models.VERTICAL) class Admin: pass # NEW: class MyModelAdmin(admin.ModelAdmin): model = MyModel radio_fields = {'field1': admin.VERTICAL} }}} === Moved filter_interface from the model definition === An example: {{{ #!python # OLD: class MyModel(models.Model): field1 = models.ManyToManyField(AnotherModel, filter_interface=models.VERTICAL) field2 = models.ManyToManyField(YetAnotherModel, filter_interface=models.HORIZONTAL) # NEW: class MyModelAdmin(admin.ModelAdmin): filter_vertical = ('field1',) filter_horizontal = ('field2',) }}} == Moved newforms to forms == In [7971] Django's {{{newforms}}} library was finally renamed to just plain old {{{forms}}}. Imports of {{{django.newforms}}} will still work but will throw a {{{DeprecationWarning}}}. Deeper imports throw {{{ImportError}}}s. In general, you'll just need to change {{{from django import newforms as forms}}} to {{{from django import forms}}}. {{{django.oldforms}}} is still available, but really you shouldn't be using it. == Changed the way URL paths are determined == A long-awaited change was made in [8015] to the way Django works with HTTP URL strings. Web servers separate request URLs into two pieces, the `SCRIPT_NAME` and the `PATH_INFO` (there is also the `QUERY_STRING` for query parameters, but that is not relevant here). Prior to this change, Django was not using the `SCRIPT_NAME` at all, which caused a number of problems, including some portability issues. The main goal of this change is to make it possible to move a Django project from being served under, say, URLs of the form `/mysite/*` to `/my_other_site/*` without needing any changes in the ``URLConf`` file. The prefix (`/mysite/` and `/my_other_site/`) is the `SCRIPT_NAME` portion and Django only really needs to act on the `PATH_INFO` portion (the remainder of the URL). If your Django project handles all the URLs under `'/'`, you shouldn't have to make any changes in most cases. In all other cases, some alterations will be required. This change will have different effects for different web server setups. In all cases, you should remove the `SCRIPT_NAME` portion of the URLs from your `URLConf` file (they currently need to be included). === mod_python === If you are using mod_python and change nothing (not even `URLConf`), your code will still work and will be as non-portable as before. You may wish to leave things this way. However, if you wish to take advantage of the portability improvements, remove the script prefix from `URLConf` and set the prefix using the `django.root` option in mod_python's configuration. A configuration section that used to look like this: {{{


text:
- Don't try very hard. Seriously, do the bare minimum. You'll get home eventually. Just take your time.
- Choose your gear wisely. You can ride in a big gear or you can ride in a small gear, but you should never ride in LA Gear, since that's very early 90s and it wasn't especially energy efficient back then.
- Mind over matter. Try to stay out of your own hear. Namely, don't think about how tired you are. Embrace vacuity.
- Stop for snacks. I didn't do this today, but it's always fun to stop for snacks. Like, you could get tacos if there are roadside taco stands. Or maybe you could go into a CVS and clean them out of Sour Patch Kids and then eat all those kids and pucker like nobody's business. Or could maybe buy a Yoohoo because how many excuses do you have as an adult to drink a Yoohoo? "Naw man, I'm just drinking it for the calories. Totally bonking," you'll say as you secretly enjoy the fake chocolate milk before regretting it.
- Listicles are a great way to avoid putting in actual effort into a blog post. But that's neither here nor there. Well, technically, it's here.
I don't understand bus drivers and their relationship to bicyclists. They're an inconsistent bunch. Some are nice and some are downright hostile. I had a guy today who simply tried to ignore the fact that I was in the lane he was trying to merge into and he pulled his (out of service) bus over anyway, so I moved over, but then I got in front of him and then a driver (maybe an off-duty bus driver?) did the same thing and it was frustrating because I felt like the invisible man (Wells, not Ellison) and I'm pretty sure that I'm not invisible.
Saw a guy on a Brompton at Massachusetts and 23rd. That's two Bromptons in two days. Olympic fever (because the Olympics are in England and that's where Bromptons come from, not because there's folding bike diving or something. Though the idea of riding a bike off a springboard would be sort of awesome.)
Q Street to 14th to K Street to 15th. For those of you following along at home, that's me doubling back west one block, perhaps needlessly. Well, not exactly needlessly since 14th street at McPherson Square is one way and the wrong way and that would be a great place for a contraflow cycletrack, so let's make that happen. On 15th street, I saw a Razr Scooter commuter:
If bike lanes are a sign of gentrification (but, no), what would dedicated push scooter lanes symbolize? Presumably apocalypse.
These should be on the street, but they got knocked over and now they're protecting tourists from falling off the sidewalk into the cycle track. Awesome!
This little bollard when to market and this little bollard when home, this little bollard had roastbeef and this little bollard was knocked over by a driver who was incapable of avoiding a two foot tall plastic post and should probably be forced to surrender his license because honestly how could we trust that person not to injure someone through his inept handling of his car? No, I don't have kids. Why do you ask?
A little later down the road, I saw a Pedicab operator and then I heard him go "uh oh" and then I heard some laughter and I saw that his bike's chain had snapped. This is a picture of his passengers alighting:
Saw a good riding a cool orange bike and I rode behind him for a while and I tried to read the name on the side of his bike to identifying the make and model, but I couldn't do it, in spite of my weaving and I soon realized that he had a rearview mirror and that he probably thought that I was being some kind of jerk and weaving to try to get around him. My bad.
Tourists take Bikeshare everywhere. I cannot even imagine what it's going to be like in NYC. Ten times bigger, I guess. Eventually.
East Capitol to Kentucky to the store and I struggled for a little to figure out what to get for dinner, but it worked out and I rode home and I even mustered some gumption to try to catch the green light at Independence and I didn't even stop to buy a pretzel, but I sort of wanted one.
FCC tomorrow. That's an acronym for Friday Coffee Club. See you there.

subset: commoncrawl


text:
Press Release:
Celebrate 75 years of Batman with over 20 artists' interpretations of Bob Kane and Bill Finger's legendary creation as well as his infamous Rogues Gallery.
OPENING PARTY WILL BE FRIDAY MAY 23 from 8-10pm
Art on view from May 23rd – end of June
auction to follow in July
Artists include:
Ramona Fradon (Batman, Aquaman)
Christos Gage (yep, the writer) (Buffy, The Hulk)
Tim Bradstreet (Punisher, Vertigo)
Bob McCleod (DC, Marvel)
a limited edition Berni Wrightson print
Mark Grammel (Kolchak the Night Stalker, Moonstone)
Lindsay & Alex (Baman Piderman)
Veronica Fish (Pirates of Mars)
Andy Fish (Dracula)
Andy Hirsch (Regular Show, Darn Varmints)
and lots more!
Friendly Neighborhood Comics
191 Mechanic Street (Route 140), Bellingham, MA 02019


text:
UTS Library asked about
I'm trying to import records from an EndNote database, but the author names are all truncated. How do I fix this?
1 answer
34285 views
You will need to edit EndNote's RefMan (RIS) Export filter to export the full names in your database instead of truncating to initials.


text:
When I was much younger and new to working in the capital markets, an excellent mentor taught me a market maxim that has served me well. More money has been lost because of four words than at the point of a gun. Those four words are "This time is different." We are all too ready to view our situation as unique.
I vividly recall a CNBC interview in late 1999 with a geriatric money manager who claimed that in the then current environment, a portfolio with a 100 percent equity allocation was safer for retirees than more traditional investing choices because market inflows from 401(k) contributions and the like provided constant market support. Accordingly, in his view, it was almost impossible for the equity markets to take a major hit.
We all remember how that turned out.
In their great book, This Time is Different, Carmen Reinhart and Kenneth Rogoff examine financial crises throughout history. They document how whenever such crises arise, alleged experts claim that "this time is different" — that the new situation has little in common with past disasters.
Reinhart and Rogoff call this problem the "this-time-is-different syndrome." According to their analysis, "It is rooted in the firmly held belief that financial crises are things that happen to other people in other countries at other times; crises do not happen to us, here and now. We are doing things better, we are smarter, we have learned from past mistakes. The old rules of valuation no longer apply. The current boom, unlike the many booms that preceded catastrophic collapses in the past (even in our country), is built on sound fundamentals, structural reforms, technological innovation, and good policy. Or so the story goes."
We live in an overconfident, Lake Wobegon world ("where all the women are strong, all the men are good-looking and all the children are above average"). We are only correct about 80 percent of the time when we are "99 percent sure." Despite the experiences of anyone who has gone to college, fully 94 percent of college professors believe they have above-average teaching skills. Since 80 percent of drivers say that their driving skills are above average, I guess none of them drive on the freeway when I do. While 70 percent of high school students claim to have above-average leadership skills, only 2 percent say they are below average, no doubt taught by above-average math teachers.
In a truly terrifying survey result, 92 percent students said they were of good character and 79 percent said that their character was better than most people even though 27 percent of those same students admitted stealing from a store within the prior year and 60 percent said they had cheated on an exam. Venture capitalists are wildly overconfident in their estimations of how likely their potential ventures are to succeed. In a finding that pretty well sums things up, 85-90 percent of people think that the future will be more pleasant and less painful for them than for the average person.
Our overconfident tendencies are well-known of course and obvious in others if not to ourselves. The odds of playing college sports are long and the chances of an athlete reaching the pros are vanishingly small, yet every weekend astounding numbers of parents can be heard at their kids' games talking about little Sally or Sam inevitably winning an athletic scholarship. Marketers take advantage of these tendencies too (which explains the success of credit-card teaser rates, for example). Our biases constantly impact our decision-making, obviously. As Daniel Kahneman and Dan Lovallo put it in a 1993 paper, "decision makers are excessively prone to treat problems as unique, neglecting both the statistics of the past and the multiple opportunities of the future."
On the other hand, we are also highly loss-averse. This aversion is another well-known cognitive bias. Empirical estimates find that losses are felt between two and two-and-a-half times as strongly as gains. Thus the disutility of losing $100 is at least twice the utility of gaining $100. Loss aversion favors inaction over action and the status quo over any alternatives.
Therefore, when it comes time for us to act upon the facts and data we have gathered and the analysis we have undertaken about them, these biases — unjustified optimism and unreasonable risk aversion — conflict. As a consequence, we tend to make bold forecasts but timid choices.
Dealing with these conflicting biases is never easy. But we can start by recognizing the nature and extent of the problem.
These biases go a long way toward explaining what academics call the "annuity puzzle" — the idea that people buy income annuities to guarantee retirement income far less often than good sense says they should. For example, we tend to overestimate the likelihood of good future portfolio returns while underestimating the likelihood of major portfolio drawdowns such that we take no action to deal with longevity risk by purchasing an income annuity. In short, we tend to accept risks when we don't think we will have to bear them.
This reluctance to take clear and explicit responsibility for potential losses is both costly and powerful. As a result, as shown by political scientist Aaron Wildavsky in his famous book Searching for Safety, we are typically better off engaging in an active search for safety rather than relying upon a passive prevention program. An appropriately active response to longevity risk is to provide a guaranteed income source so that retirees can rest assured that they will not run out of money.
One way to overcome these biases is by framing the decision to be made differently. The "certainty effect" is a sharp discrepancy between the weights that are attached to sure gains and to highly probable gains in the evaluation of prospects. Thus, when an income annuity is positioned as a certain gain of guaranteed income for life rather than as a payment resulting in a loss of control of one's nest egg in exchange for future payments, it is more likely to be well-received.
We also tend to consider problems one at a time in isolation instead of aggregating the problems and the risks and looking at them together. If the benefits of an income annuity are examined in conjunction with longevity risk, market risk, sequence risk and health risk, it becomes a much more attractive proposition. As Kahneman and Lovallo affirm, "evaluations of single risky prospects neglect the possibilities of pooling risks and are therefore overly timid."
Similarly, we will often reject a single gamble but will accept multiple plays of that same gamble (for example, a gamble where we will either gain $200 or lose $100). Thus an income annuity framed as a one-time purchase pitting a fixed result against unlimited future possibilities is unlikely to be seen as desirable. Instead, prospect theory recommends broadening the decision frame. Outcomes should be evaluated in terms of final assets rather than gains and losses associated with each choice. For example, research by John Ameriks, Robert Veres, and Mark Warshawsky shows how income annuities need not be an all-or-nothing proposition (ideally they should not be). The authors do not try to find an optimal annuity amount, but they do show how annuitizing a portion of one's savings can help improve success rates for a 4.5 percent withdrawal rate.
The "annuity puzzle" remains a vexing problem for advisors who are intent upon the best interests of their clients. But if dealt with carefully and communicated fairly and well, the value of guaranteed income can be demonstrated to many consumers.


text:
But that being said as a traveler I pick and choose places I like to go based on how much enjoyment I get out of the location, and China is just one of those places where I don't mesh as well with the culture and the people, so I choose to visit the country less frequently than someplace like Japan or Europe. I'm not going to be one of those people who will complain about something and then expect somewhere to cater to my own personal preferences, instead I'll take the mature avenue and just not go. We all have choices...
ANYWAY... enough about my rant on cultural stuff, let's talk about the park! After our full second day we came away from the park once agian feeling like Pirates and Tron were the two absolutely stand-out attractions, and everything else was just a nice bonus. We got to do so much more today due to the lower crowds and we had a great time. On a slower day, I would put this park on par with Hong Kong, Paris, or Disneyland in California, but I'm not sure it ranks up there with Walt Disney World or Tokyo Disney. That's not a bad thing, keep in mind, because it's still going to end up being one of my favorite parks in the world, and I've been to a *LOT* of parks!
Let's go to some photos...
Yes, this is in a theme park!
Photos & video do not do this ride justice. All I know is I have zero interest in riding "old Pirates" now! See that scene in the poster? That ACTUALLY HAPPENS in the ride and it's just as "big" in real life as it is in the poster!
Just rode Tron again. It's growing on me. Liked it as a "coaster" much better the second time!
Some of the awesome Tron merchandise!
This is in the Tron queue! It's AMAZING! They do this "reveal" of the launch track:
Kristen from @OceanSprayInc shows Jack how to harvest cranberries! @WaltDisneyWorld #EpcotFoodFestival @WDWToday pic.twitter.com/UMnKfUdzS5— Theme Park Review (@ThemeParkReview) September 26, 2015
Yes! Even MORE Tron merchandise! How much of this do you want?
Waffle break!!! These are *almost* as good as the ones at Tokyo Disney!
Here is one major drawback to Shanghai Disneyland... disgusting Pepsi products. Such a shame, really.
This little show where Mickey Mouse conducts the Main Street marching band was super cute & fun!
Someone really loves the Tron ride!
This show where #Baymax teaches kids to exercise might be one of the cutest coolest theme park shows I've ever seen!
Yep, there is a Walt Disney "Partners" statue here, too!
The ropes course at Shanghai Disneyland is legit hardcore. Narrow ledge, waterfall, slippery rocks, 30' drop off!
How many 9 year olds can say they've been to ever Disney park on the planet?
We have taken a break from the park for a light lunch at Cheesecake Factory!
The castle walk-through attraction was an interesting display of projection effects and storytelling!
The Christmas tree out in front of the Shanghai Disneyland castle!
The handicap seat on Tron was awesome! Like a normal coaster car. What a great idea!
It's a lot quieter tonight than it was last night.
5 minute wait for Tron? SURE! I'll take that!!!
Another great ride on Tron!
I simply cannot say enough good things about Pirates. Photos don't come close to selling it!
The queue for Pirates was also insanely detailed and elaborate.
It was nice to have Seven Dwarfs Mine Train at this park. I really do like this ride a lot and feel it's the PERFECT "family" coaster especially if you have younger kids. This version is very similar to the one at Magic Kingdom although the MK one was slightly better as it had a more elaborate queue and a bit more landscaping and scenery that was missing from the Shanghai version.
Inside of the Shanghai Disneyland castle!
Who can tell us which Princesses all these flags represent?
Buzz Lightyear is a familiar yet totally different experience. The best version of this ride, easily!
You asked for some more castle detail photos... here ya go!
The park doesn't have a "rocket jets" ride but instead they have this "jet packs" ride.
Can someone tell me where I can get a Tron attraction poster???
Seriously, this #Baymax exercise shown was amazing and cute! Loved this!!!
Kristen from @OceanSprayInc shows Jack how to harvest cranberries! @WaltDisneyWorld #EpcotFoodFestival @WDWToday pic.twitter.com/UMnKfUdzS5— Theme Park Review (@ThemeParkReview) September 26, 2015
Who would like to get their picture with Santa Duffy?
We did find a good amount of Elissa approved merchandise at Shanghai Disneyland!
Crystal Grotto is Shanghai Disneyland's answer to "Storybook Boats" and spoiler alert, there IS an actual crystal grotto!
The lighting on the castle at night was just amazing!
Ignite The Magic is a castle projection/fireworks show worthy of the "nighttime spectacular" moniker. Between this Tokyo's version of Once Upon A Time and Paris' Disney Dreams these castle shows are some of my favorite night time Disney entertainment. I only wish that Magic Kingdom had a more elaborate castle show, but then again, MK has a really good fireworks show where this park only has the castle show in the evening.
And that wraps up our coverage from Shanghai Disneyland! My overal verdict? Now that I had a more "hassle-free" day at the park (which wasn't totally without cultural frustrations, keep in mind) I think it's a park I absolutely would recommend Disney fans check out, and it's a park I will be making a return visit to. Maybe not as frequently as some of the other Disney parks in the world, but it's "bucket list" material for sure!
Next park stop on this trip... Hong Kong Disneyland!
Click HERE for the next section of the report from our trip!


text:
FAQ | Usergroups | Profile | Register | RSS | Posting Guidelines | Recent Posts
MSMessenger to appear "off line"?
Users browsing this topic:0 Security Fans, 0 Stealth Security Fans
Registered Security Fans: None
|Tom Bair
SF Boss
Joined: 10 Aug 2002
Posts: 16776955
Location: Portland, Oregon USA
|All times are GMT + 2 Hours
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
Discuss your Windows Networking issues with thousands of other Windows Newtorking experts. Click here to join!


text:
PD housings must be mounted properly, using the correct tools. All the associated components must meet certain basic requirements and the support surface should meet the specifications provided under Housing support surface.
The housings have two markings (fig. 1):
- A "square" on one end denotes the position of the wider of the two bearing seats.
- A "triangle" on the other end indicates the direction in which the predominant axial load should be applied.
For information about mounting rolling bearings, refer to the SKF bearing maintenance handbook or skf.com/mount.
Mounting PDN series housings
The wave spring washers, supplied with smaller housings in the PDN series, should be inserted between the bearing and the cover on the housing end marked with a triangle. The rotary components (impeller, pulley, coupling etc.) must be arranged so that the axial load Fa produced in operation acts in the direction indicated by the triangle. SKF recommends using a hydraulic nut or press for these mounting operations.
Mounting PD units
Installing PD units is simple because the unit just needs to be bolted to the support surface. The rotary components are then mounted onto the finished shaft ends secured by the keys, end plates, and attachment screws (with spring washers) provided.
Support the shaft properly when pressing components onto the shaft to prevent the mounting force acting on the bearings. Mounting instructions are available on request.
Torque specifications
Cover bolts should be tightened to the torque values listed in table 1. The cover bolts are in accordance with ISO 4017:2014.
For information about attachment bolts, refer to Attachment bolt recommendations.


text:
There are no items in your cart at this time.
Equip your favorite pair of shoes with biologically engineered midsoles to keep aches at bay. For men, women and children, Footwear etc.'s insoles are meant to fit all types of shoes and help remedy a variety of serious foot conditions like plantar fasciitis and hammer toes. With inserts from Ecco, Superfeet, Spenco, Lynco, Vionic and Alegria, available benefits include shock absorption, antibacterial properties, prominent arch support and more. Treat your feet to true bliss with replacement insoles today.
Sign up to receive new arrival, sale & special event info from us.
Note: we do not share your personal information with anyone. Period.
"I felt compelled to email you after your company exceeded my expectations. I was late getting my wife a pair of UGGs for her birthday - your price was the best, your shipping was incredibly fast, and it was well packaged and exactly as she'd hoped. Easily the best online experience I've had this year (if not ever). Great work! Thanks!"
©2020 Footwear etc.. All Rights Reserved. For any questions or assistance call 1-800-720-0572.


text:
Round 1 Recommendations (ECHO)
Round 2 Recommendations (ECHO)
Round 3 Recommendations (ECHO)
Links to ECHO may take up to 10 seconds to load.
|State Enforcement Implementation
|Clean Air Act (CAA)
|Clean Water Act (CWA)
|Resource Conservation and Recovery Act (RCRA)
EPA implements enforcement and compliance programs not implemented by the states.You will need Adobe Reader to view some of the files on this page. See EPA's About PDF page to learn more.
- Round 1 Definitions (PDF)(3 pp, 177 K)
- Alaska Round 1 State Review Framework Report (PDF)(31 pp, 552 K)
- Round 2 Definitions (PDF)(3 pp, 88 K)
- Alaska Round 2 State Review Framework Report (PDF)(95 pp, 3 MB)
- Alaska Round 3 State Review Framework Report (PDF)(146 pp, 5 MB)


text:
Welcome to Sound ShelterX
Swipe through the best new releases, and find a store selling the music you want
We stand in solidarity with all protests against racism and police brutality.
The vast majority of the music we love is made by or highly influenced by black artists - music fans owe the black community a lot. We ask you to show your support through education, donations, signing petitions, spreading the word through social media, and physical protests.
Looking to help?https://blacklivesmatters.carrd.co/
Alex Attias / Sassy J / Javonntte / Luman Child / Sebastien Loopes
The Chromatic Universe Vol 2 Part 3


text:
Update – Sunday Morning Fire at Roseburg Forest Products [AUDIO]
Crews from Missoula Rural Fire, Missoula City Fire department and the Frenchtown Fire Department combined to knock down a fire at the Roseburg Forest Products plant on Razer Drive.
Assistant Fire Chief Brent Christofferson says the 9-1-1 call came in early Sunday morning, and found a fire in the air handling system in te baghouse.
Several engines were dispatched to the scene along with a battalion chief, and the fire was successfully knocked down.
Roseburg Forest Products Mark Allen says the fire started accidentally in an area called the refiners, and that damage to the facility was relatively minor...only about $10,000. He says the facility is back up to 100% capacity after about 24 hours of repairs and clean-up.
Assistant Missoula Rural Fire Chief Brent Christofferson


text:
Unified Products and Services (Contact: Ms. Sofia Macaraeg - Office) will cater not only traditional products but also to technology based services such as Remittance, Ticketing, Bills Payments and Loading.
Unified Products and Services offer various Dealership packages and Franchise hub that will empower global communities towards attaining financial freedom and economic stability.
Ups Express exists with the paramount purpose of providing business opportunities to everyone through our world class quality products and services.
Look for:
09507383596 TNT 09453426318 Globe
DO NOT GIVE ANY CASH MONEY TO ANY DEALER or FRANCHISE AGENT, ALL PAYMENTS MUST BE DEPOSITED TO ANY UNIFIED PRODUCTS AND SERVICES OR GLOBAL PINOY REMITTANCE SERVICES BANK ACCOUNT.


text:
Nurses call on federal government to scrap cuts to health-care coverage for refugees
TORONTO, May 30, 2012 – Ontario nurses are adding their voices to a growing list of health-care professionals who want the federal government to drop controversial changes that will limit health-care coverage for refugee claimants.
Members of the Registered Nurses' Association of Ontario (RNAO) issued an open letter to Prime Minister Stephen Harper this week, concerned that changes to the Interim Federal Health Program will threaten the lives and well-being of people who have already experienced trauma and hardship even before they arrived in Canada.
"Refugees who come to our country have tremendous challenges to contend with. Besides overcoming oppressive and abusive systems they've left behind, they have to deal with language barriers, finding shelter, and providing for themselves and their loved ones. Denying them proper access to primary health-care services is unconscionable," says Doris Grinspun, chief executive officer of RNAO, adding "this is not the Canada I know."
The changes, which take effect at the end of June, mean current and future refugees will no longer be eligible for vision, dental or supplemental health benefits. Access to prescription drug benefits will also be severely curtailed. Most refugees would also not have access to hospital services or care provided by a nurse or physician, except in urgent situations.
RNAO says the estimated cost savings used as the rationale for the change is an example of false economy. "There aren't many health-care professionals who agree that restricting access to primary care services is sound health or economic policy," says Rhonda Seidman-Carlson, president of RNAO, adding "this goes against every notion of what a health system should be."
The association has also begun a letter writing campaign urging its 33,000 members to send letters to Prime Minister Harper and Jason Kenney, Minister of Citizenship, Immigration and Multiculturalism, asking them to rescind the planned changes.
In its letter, Ontario nurses also call on Ontario Premier Dalton McGuinty to take an activist role by enlisting the help of other provincial and territorial leaders to advocate against the changes.
RNAO joins other health organizations in taking a stand against the cuts, including the Canadian Nurses Association, the Canadian Health Coalition, and the Canadian Medical Association.
The Registered Nurses' Association of Ontario is the professional association representing registered nurses in Ontario. Since 1925, RNAO has advocated for healthy public policy, promoted excellence in nursing practice, increased nurses' contribution to shaping the health-care system, and influenced decisions that affect nurses and the public they serve.
For more information about RNAO, visit our website at www.rnao.ca. You can also check out our Facebook page at www.rnao.org/facebook and follow us on Twitter at www.twitter.com/rnao.
To arrange an interview with a nurse or for more information, please contact:
Marion Zych, Director of Communications, RNAO
Cell: 647-406-5605 / Office: 416-408-5605
Toll free: 1-800-268-7199 ext. 209


text:
My Profile
My Profile
Don't have an account?Register
- Search
- Your Quote.: 0
Activate mobile nav
A table knife from the sleek Bourton range. Mirror-polished finish and made from specially hardened stainless steel.Read more
Bourton cutlery has a soft sleek profile and elliptical detailing at the neck. Spoons and forks are made using the highest quality 18/10 stainless steel. Knife blades are made from specially hardened stainless steel to provide the finest possible cutting edge.
All Bourton cutlery is available with a mirror finish, has a lifetime guarantee and is dishwasher safe.
Length: 236mm
To download or reveive a printed copy of our hospitality catalogue, please click belowRequest a brochure


text:
7 Months Of Warrantless 'Just Metadata' Paints A Clear Picture Of Your Personal Life
from the anyone-still-believe-this-info-shouldn't-be-protected? deptThe ACLU (along with the EFF and many others) has filed an amicus brief in a case of warrantless cell location tracking currently being considered by the Fourth Circuit Court of Appeals. It cites the obvious similarity between this and the U.S. vs. Jones decision, in which the justices concluded that a person's privacy is violated by long-term tracking of their movements.
In that case, a GPS device was attached to a vehicle. In this one, the privacy implications run much deeper.
People carry their cell phones with them all the time. Each time a cell phone makes or receives a call or text message, the wireless provider logs the cell towers the phone connected to during that communication. Cell phone tracking therefore allows the government to reach back into the past and pull up a record of where we have been on any given day.Lest we forget, this is the same sort of supposedly harmless, non-identifying "metadata" the NSA and FBI are collecting on millions of cell phone users every day, thanks to a very obliging FISA court. In the Jones case, the
In the case, United States v. Graham, the government obtained a staggering 221 days of historical cell site location information for two suspects. For one suspect, Aaron Graham, this timespan allowed the government to sweep up his location at 29,659 specific points.The amount of information that can be culled from these data points easily exceeds anything law enforcement should reasonably expect to obtain without a warrant. Aaron Graham worked with his provider and the ACLU in order to provide it with the same tracking information law enforcement had acquired. Here's what the ACLU found.
Mr. Graham's wife was pregnant during the records period. 29 calls during business hours began or ended in the sector where Mr. Graham's wife's OB/GYN's office is located, allowing the inference that they were at the doctor's office at these times.The ACLU points out that technological advancements have made it easier for law enforcement and others to easily collect large amounts of data on any person, making the protections of the Fourth Amendment more important than ever. Just because millions voluntarily use products and services utilizing invasive technology doesn't mean they're implicitly waiving their right to privacy. Nor should it be assumed the use of a cell phone means the "expectation of privacy" is no longer valid.
The most frequently occurring cell site and sector in Mr. Graham's records is the closest sector and tower to his home – nearly a third of all of his calls were placed or received in this sector. Of those 4,917 calls, 77 started in his home sector and ended elsewhere and 226 started elsewhere and ended when he was at home, providing information about his patterns of movements to and from home.
From July 10 to July 15, 2010, Mr. Graham's last call of the night and first call of the morning were either or both placed from his home sector, allowing the inference that he slept at home those evenings. However, on July 9, Mr. Graham's last call of the night and first call of the next morning were placed from a cell sector 30 minutes from his house. Although we have no reason to believe it to be the case here, this information could reveal private information about the status of a person's relationships and any infidelities.
Once again, it appears law enforcement's m.o. is "do it until someone makes you stop." One wonders what sort of information can be both so vital as to be obtained without the hassle of a warrant, yet still so elusive it could only be ascertained by gathering two-thirds of year's worth of location info. Hopefully, the court will find along the lines of the Jones decision, and continue rebuilding the protections the Fourth Amendment was written to provide.
Filed Under: gps, metadata, tracking, warrantless data


text:
COLORADO SPRINGS, Colo. (April 18, 2008) – Kim Willoughby (Napoleonville, La.), a three-time American Volleyball Coaches Association All-American and 2003 AVCA National Player of the Year, has been added to the U.S. Women's National Volleyball Team, according to Team USA Head Coach 'Jenny' Lang Ping.
Willoughby, a 6-0 outside hitter, recently completed her 2007-2008 professional season with Famila Chieri, a team in the top-tier Italian Serie A League. She tallied 306 points for Chieri while playing in 73 sets within 21 matches. Willoughby ranked 12th in points per set at 4.19, while her 3.82 kill average was eighth-best in the league.
As a senior at University of Hawai'i in 2003, Willoughby ranked second nationally in kills per game with 6.59 while adding averages of 2.99 digs and 0.62 aces per game. She hit .372 in her final collegiate season to help the Rainbow Wahine to the NCAA Division I Women's Volleyball Tournament semifinals for the second consecutive year. For her career, Willoughby averaged 5.91 kills per game, which ranked third-best in NCAA history at the time. She also contributed 1,440 digs, 194 aces and 291 blocks over 459 career games.
Willoughby is the third cousin of U.S. Women's National Team middle blocker Danielle Scott-Arruda (Baton Rouge, La.).
The U.S. National Team now has four players competing for a spot in the 2008 Olympic Games who earned AVCA National Player of the Year during their collegiate careers. Logan Tom (Salt Lake City, Utah) earned the honor twice, while Ogonna Nnanami (Normal, Ill.) and Foluke Akinradewo (Plantation, Fla.) captured the award once. Tom and Nnamani were four-time AVCA All-Americans with Stanford University, while Akinradewo will complete her senior year at Stanford in 2008.
In addition, Nellie Spicer (Barrington, Ill.) and Destinee Hooker (San Antonio) are no longer training with the team in its preparation for the 2008 Olympic Games.


text:
Their default mode is high-speed through 4-bit wide port but we're going to be working with the "legacy" SPI (two-wire) mode.
In SPI mode, the master device (our microcontroller) talks to the slave device (the sd card) using a data and a clock line. Every time the clock line goes from low-to-high (or, if you prefer, from high-to-low - you can change this to suit the application needs) the receiving device looks at the data line. If it's high, it receives the single-bit value 1, if it's low, zero.
in this example, when the clock line goes from low-to-high (sometimes called a rising edge trigger) as denoted by the red vertical lines in the clock timing diagram, the state of the data line is converted into a value
The great thing about SPI is that it's not time dependent. Because the master device sends the clock line along with the data, it can be speeded up and slowed down (this is not possible using methods such as UART/serial, which has a fixed data rate; ie. the data has to be moved within a specific time period).
Using this clock-and-data method, we can send commands to the sd card, to tell it to do specific things. So we can send a specific value (the sd format sets out specific values to send for specific commands) to get it to reset, for example.
When an SD card has received and understood a command, it can remain in a busy state for quite some time. It is important to wait until the card has finished doing whatever you asked it to do, before blasting more data or commands at it. To do this, we poll the card (continuously ask it for data) until it gives us a "ready" token.
SPI is actually a data exchange mechanism. There's no difference between reading and writing bytes between the devices. As one device sends a byte of data, so the other transmits one. After sending a single byte of data from an SPI buffer another (possibly different) byte may appear in it's place - this is the byte that has been received.
So to read a byte from the sd card, we have to send it a byte too. It's normal to send either all zeros (0x00) or all ones (0xFF in hex is 255 in decimal, which is 11111111 in binary) for "don't care" bytes - so if you're just reading data from the other device, and it's not important what data you send, it's common to either send 0x00 or 0xFF.
Whenever a command is sent to an SD card, it follows a specific format:
There is a single command byte
There are four "parameter" bytes - data which tells the recipient how to perform the command requested
There is a single CRC (checksum) byte to prove that the previous bytes have been transmitted correctly.
To send data to our SD card, we need a couple of functions:
UInt8 sdSpiByte(UInt8 data){
ssp1buf = data;
while(!(ssp1stat & (1<<BF)));
static inline void sdSendCommand(UInt8 cmd, UInt32 param){
UInt8 send[6];
send[0] = cmd | 0x40;
send[1] = param >> 24;
send[2] = param >> 16;
send[3] = param >> 8;
send[4] = param;
send[5] = (sdCrc7(send, 5, 0) << 1) | 1;
for(cmd = 0; cmd < sizeof(send); cmd++){
This provides us with a simple method of sending commands (and their parameters) to the SD card.
The first function simply puts a value into the hardware SPI buffer then waits for the SPI busy register value to go "not-busy" before returning the value it finds in the buffer (which is now the value received from the other device - data exchange remember!)
The second function actually sends commands to the sd card. Every command byte sent to an SD must have bit 6 set (so the device can recognise it as a command and not some data).
Bit 6 in binary is 01000000 which is 64 in decimal or 0x40 in hex.
So to make sure that every command byte has bit 6 set, we always OR the command byte with 0x40 (so when we send command zero, for example, it's actually transmitted as 0x40, command one is sent as 0x41 and so on).
But every time we send a command (and it's parameters), we have to wait for a not-busy response from the SD card. While the SD card is busy, it holds its "output pin" high - the data clocked out of it is always 11111111 (or 0xFF) So we build these little functions:
static inline UInt8 sdReadResp(void){
UInt8 v, i = 0;
v = sdSpiByte(0xFF);
}while(i++ < 128 && (v == 0xFF));
return v;
static UInt8 sdCommandAndResponse(UInt8 cmd, UInt32 param){
sdSendCommand(cmd, param);
ret = sdReadResp();
return ret;
This sdCommandAndResponse function sends a "dummy byte" to the sd card.
It then sends the command byte, followed by the 4-byte parameter value(s).
Next it calls the read-response function, which continuously sends the dummy byte 0xFF to the sd card, until the response back is not busy. When the response goes not busy, the response value is returned to the sdCommandAndResponse function. The response could either be "all ok" or it may be some kind of error code to explain why the command given could not be completed.
One last function to mention is the CRC generating function.
Strictly speaking, once we've told our card to work in SPI legacy mode, we don't actually need to generate the CRC values, but it's included here for completeness.
Note: We didn't actually create this function, we ported it from another sd card library for another platform:
static UInt8 sdCrc7(UInt8* chr,UInt8 cnt,UInt8 crc){
UInt8 i, a;
UInt8 Data;
for(a = 0; a < cnt; a++){
Data = chr[a];
for(i = 0; i < 8; i++){
crc <<= 1;
if( (Data & 0x80) ^ (crc & 0x80) ) {crc ^= 0x09;}
Data <<= 1;
return crc & 0x7F;
Before we can actually start sending data over SPI, we need to set up the PIC to use the hardware SPI peripheral. This means writing some values to particular registers in the chip. The names of these registers should be similar across different PIC models, but may not be exactly the same if you're using a different chip:
static void sdSpiInit(void){
ssp1add = 21; //slow clock down to < 400khz
ssp1con1 = 0b00101010; //spi master, clk=timer2
ssp1stat = 0b11000000; //CPHA = 0
The important registers here are the SSP1ADD (multiplier value) ad SSP1CON1 register.
When the last four bits of SSP1CON1 are 1010 this slows down the SPI clock speed - by how much depends on the value in the SSP1ADD register (and the actual speed, as in time taken to send each clock pulse, is dependent on the overall processor clock speed so will change with each chip model). When the last four bits are set to 0000, the SPI clock changes on every instruction cycle. When it's set to 1010, it changes on every x clock cycles, where x is the value held in the SSP1ADD register.
The SD card initialisation routine after powering up is:
- Set the clock speed to less than 400khz
- Hold the chip select line on the card low and send in about 80 clock pulses
- Pull the chip select line high to tell the card we're talking to it
- Send in the "soft reset" command (CMD0)
- Wait for the sd card to respond "ok" with the value 0x01
- Send in the "initialise card" command (CMD1)
- Repeat sending CMD1 until the card responds with an ok value of 0x00
- Set the sector size using CMD16 with a parameter 512 (each sector is 512 bytes)
- Turn of the CRC requirement by sending CMD59
- (all future transmissions do not require a valid crc value)
- The next time the card responds with an "ok" value, it has been initialised and we can ramp the clock up to full speed.
All of the initialisation routines have to be carried out at the relatively slow clock speed of not more than 400khz. So we need a couple of extra functions to enable us to set the clock speed and enable the chip select line:
static void sdClockSpeed(Boolean fast){
ssp1con1 = 0b11110000
ssp1con1 = 0b11111010
void sdChipSelect(bool active){
portc.3 = !active;
For debugging, we've written a simple "fatal error" function to let us know which part of the initialisation failed (if there are any problems). When a fatal error is hit, this function reports it, then puts the microcontroller into "sleep mode" so that the program flow is permanently interrupted.
void fatal(UInt8 val){ //fatal error: flash LED then go to sleep
UInt8 i, j, k;
for(j = 0; j < 5; j++){
for(k = 0; k < val; k++)
asm sleep
By using all these functions together, we can now write our sdInit routine:
Boolean sdInit(){
UInt8 v, tries = 0;
Boolean SD;
SD = false;
sdSpiInit(); // initialise SPI
sdClockSpeed(false); // slow clock
sdChipSelect(false); // CS inactive
for(v = 0; v < 20; v++) {
sdSpiByte(0xFF); //lots of clocks to give card time to init
sdChipSelect(true); // CS active
v = sdCommandAndResponse(0, 0, true);
if(v != 1){fatal(2);}
v = sdCommandAndResponse(1, 0, true);
for(int i=0;v != 0 && i<50;++i){
v = sdCommandAndResponse(1, 0, true);
v = sdCommandAndResponse(16, 512, true); //sec sector size
v = sdCommandAndResponse(59, 0, true); //crc off
// now set the sd card up for full speed
return true;
If this function successfully returns true, the SD card has been successfully initialised and the SPI lines set to run at maximum speed for the fastest (spi-based) data transfer.


text:
Sam Raimi's "Drag Me To Hell" has officially been rated PG-13. Apparently there are people surprised by this... haven't you seen the trailer?
Poster for that French zombie film "Mutants" I told you about last week. I'm sure it doesn't mean the same thing in English, but I was really intrigued by the words "PLUS TARD" on the poster. That's a new one.
Akroyd gives more details on "Ghostbusters 3". Apparently the "young recruits" we've mentioned will be "cadets" at some kind of academy. That is AWESOME. He also says that they are going to do everything they can to get Sigourney Weaver on board, who seems to be the last holdout in restarting the franchise.
The plot is pretty standard but the title isn't. Today's awesome indie title award goes to Albino Farm. That is all.
Ron Perlman says they'll probably be shooting "Bubba Nosferatu" this Fall. I still don't think he'll make a great Elvis, but since he's terrifying I'm pretty sure he wins every argument no matter what.
If you live in New York or Las Angeles, you will see a teaser for Rob Zombie's "H2" before "Crank 2" this weekend. If you're not in those areas, tough luck. You will see Amy Smart's boobs though, and that is the greatest gift anyone could ask for.


text:
Production Machining is rolling out a new e-newsletter called "Et Cetera." The newsletter is a compilation of our latest blog posts that will be delivered to your inbox each Friday. Sometimes you are too busy to visit our blog every day. That's okay. The newsletter enables you to quickly scan a weekly roundup of posts to see what catches your eye.
The blog and the newsletter are effective channels that support what's presented in Production Machining. They enable us to share our experiences (sometimes in a more lighthearted manner) as we engage with the businesses and personalities that apply machining technologies in innovative, creative ways.
We hope this will be an opportunity to engage and hear from you directly. What is your reaction to any of the posts you read here? Email any of the contributors your thoughts. What have you seen lately?
You can also find the blog any time by following the "Blog" link at the top our website.
You may opt out at any time by clicking the unsubscribe link provided at the bottom of each weekly newsletter.