Lista wstecznie niezgodnych zmian wprowadzonych w Django 1.0
6 September 2008
Comments
Ze względu na młody wiek frameworka (sprzed wydania 1.0) twórcy postanowili nie utrzymywać pełnej wstecznej zgodności, przekładając nad to rozwój Django. W porównaniu z wersją 0.96 pojawiło się szereg wstecznie niezgodnych zmian. Osoby używające Django-SVN zapewne znają większą, poza np. tymi wprowadzonymi niedawno jak newforms-admin. Począwszy od wersji 1.0 wsteczna zgodność będzie zachowywana najlepiej jak to możliwe. Szczegółowa lista zmian na wiki Django.
Zmiana taga szablonów 'spaceless' by usuwał wszystkie spacje
Tag {{ spaceless }} usuwa wszystkie spacje pomiędzy tagami HTML, a nie jak wcześniej zachowując jedną spację z wielu. Taki kod{% spaceless %}
<p>
<a href="foo/">Foo</a>
</p>
{% endspaceless %}
<p> <a href="foo/">Foo</a> </p>
<p><a href="foo/">Foo</a></p>
Zmiana `localflavor.usa` na `localflavor.us`
Usunięcie `LazyDate`
Pomocnik LazyDate został usunięty. Zastąpić można go obiektem datetime.now. Stary kod np:class Article(models.Model):
title = models.CharField(maxlength=100)
published = models.DateField(default=LazyDate())
from datetime import datetime
class Article(models.Model):
title = models.CharField(maxlength=100)
published = models.DateField(default=datetime.now)
Zmiany w obsłudze MySQL
W rewizji 5042 wprowadzono małą zmianę w obsłudze kolumn CHAR(n). Zmienia to nieco wynikowe tabele wygenerowane przez Django, lecz nie wymaga zmian w kodzie.LOGIN_URL opcją ustawień
W r5072 LOGIN_URL z komponentu autoryzacji został przeniesiony do ustawień umożliwiając elastyczniejszą zmianę. Stary kod w postaci:from django.contrib.auth import LOGIN_URL
Zmiana metody Test Client `login()`
django.test.Client.login() obecnie nie wykorzystuje specyficznych szablonów i formularzy logowania, lecz bezpośrednio próbuje tworzy odpowiednie ciasteczka i obiekty sesji umożliwiając wykorzystanie metody z dowolnym systemem logowania. Stary kod w postacic = Client()
c.login('/path/to/login','myuser','mypassword')
c = Client()
c.login(username='myuser', password='mypassword')
Przeniesienie ogólnych (Generic) relacji
GenericRelation i GenericForeignKey zostały przeniesione do django.contrib.contenttypes, jako że bez tej aplikacji nie będą działały.Newforms: clean_data zmienione na cleaned_data
Od rewizji 5237 sprawdzone (cleaned) dane z formularzy dostępne są przez cleaned_data.Usunięcie dodatków dla przesyłania plików z Test Client
Ze względu na różne formy przesyłania plików usunięto pomocnika w Test Client odpowiadającego typowi FileField.Zmiana FloatField na DecimalField
Zmieniono nazwę typu danych "FloatField" na "DecimalField", a także reprezentowanie jej w Pythonie jako typ Decimal, a nie Float (co wcześniej powodowało utratę dokładności ze względu na zaokrąglanie). W modelach należy zmienić nazwę pola. Wprowadzono także typ "FloatField" przechowujące dane jako Float. Uwaga: w przypadku baz SQLite należy wymusić wyświetlanie danych w typie Decimal, a nie Float. Zrób kopię bazy danych (skopiuj plik) i wykonaj operacje:./manage.py dumpdata --format=xml nazwa_aplikacji > data-dump.xml
./manage.py reset nazwa_aplikacji
./manage.py loaddata data-dump.xml
Keszowanie Urlpatterns
W celu zwiększenia szybkości działania frameworka reguły mapowania URLi są obecnie keszowane. Po ich zmianie konieczny jest restart Django.Obsługa Unikodu
W rewizji 5609 dodano kod z UnicodeBranch odpowiedzialny za obsługę unikodu w Django. W przypadku danych nie-ASCII będzie powodowało to problemy. Opis zapalnych miejsc opisano na wiki Django. W skrócie:- Modele muszą mieć metodę __unicode__ (jaks __str__)
- Nie należy stosować str(), a unicode()
- Napisy (np etykiety formularzy, pól modeli) muszą być unikodem:
stare = '%s tekst' % self.cośtam nowe = u'%s tekst' % self.cośtam
- Pomocne może być też ustawienie domyślnego kodowania Pythona na unikod tworząc plik sitecustomize.py w katalogu z instalacją Pythona, o kodzie:
import sys sys.setdefaultencoding('utf-8')
Zmiana parametrów __init__() klasy Feed
Metoda __init__ klasy Feed jako drugi argument może przyjąć obiekt HttpRequest, a nie URL feeda, co umożliwia wykorzystanie klasy bez komponentu Sites. Zmiana wpłynie jedynie na klasy dziedziczące klasę Feed, lub kod bezpośrednio wywołujący __init__().Pliki PO muszą być kodowane w UTF-8
Ujednolicając kodowanie stosowane w Django, a także przez tłumaczy operujących na plikach gettexta wybrano kodowanie UTF-8 jako jedyne dla plików *po.Dodano argument `interactive` do `run_tests`
Parametr `interactive` umożliwia dodanie testów do skryptów budujących, w których interaktywne pytania w czasie testów nie są możliwe do obsłużenia.Zmiana pierwszego argumentu `run_tests`
Pierwszym argumentem "run_tests" jest obecnie lista etykiet testów, a nie lista aplikacji, których testy mają zostać wykonane. Zmiana ta wpłynie na osoby używające zmodyfikowanych test_runnerów.Drobne zmiany argumentów i obsługi danych w newforms
Dodanie `FileField` i `ImageField` do newforms wymusiło drobne zmiany obsługi danych (łączenia). Zmiana ta nie będzie miała wpływu na większość użytkowników.Zmiana poleceń management.py
By umożliwić dodawanie innych poleceń, a także by odchudzić duży plik dokonano kilku zmian w management.py. Zmianie uległo wywoływanie poleceń z np:>>> from django.core import management
>>> management.flush(verbosity=0, interactive=False)
>>> management.load_data(['test_data'], verbosity=0)
>>> from django.core import management
>>> management.call_command('flush', verbosity=0, interactive=False)
>>> management.call_command('loaddata', 'test_data', verbosity=0)
Zmiany w bibliotekach obsługujących bazy danych
Wewnątrz bibliotek ORMa obsługujących różne bazy danych nastąpiło szereg zmian, przez co większość wewnętrznych funkcji została przeniesiona lub ich nazwa została zmieniona. Funkcje te nie są udokumentowane i zmiany wymaga jedynie specyficzny kod, których ich używał bezpośrednio.Generyczny widok archive_year nie wykonuje order_by() na przekazanym querysecie
Ujednolicając zachowanie generycznych widoków powiązanych z datą generyczny widok archive_year nie sortuje już wyników samodzielnie.django-admin.py i manage.py wymuszenie opcji po poleceniach
Opcje takie jak --settings muszą być podane po poleceniach takich jak runserver. Np:django-admin.py --settings=foo.bar runserver
django-admin.py runserver --settings=foo.bar
django.views.i18n.set_language wymaga żądania POST
Widok set_language() został zmieniony tak by przyjmować tylko żądania POST (a nie GET jak wcześniej), gdyż zmiana ustawień za pomocą żądania GET nie jest zalecana przez specyfikację HTTP.Nagłówki django.http.HttpResponse niezależne od wielkości liter
Tag szablonów load obsługuje wywołania z kropką
Tag load obsługuje ścieżki zawierające kropki (w stylu Pythona):{% load foo.bar %}
Funkcja _() nie jest domyślnie dostępna
Od rewizji 6568 należy samemu zaimportować odpowiednią funkcję gettexta przeznaczoną do obsługi fraz do tłumaczenia, np:from django.utils.translation import ugettext as _
Klasa `django.newforms.forms.SortedDictFromList` usunięta
Ze względu na obecność django.utils.datastructures.SortedDict usunięta została klasa django.newforms.forms.SortedDictFromList.Automatyczne enkodowanie danych w szablonach
Dane (zmienne) przekazane do szablonów będą miały enkodowane tagi HTML. By uniknąć enkodowania można użyć filtra |save lub autoescape: {% autoescape off %}
{{ zmienna }}
{% endautoescape %}
{{ zmienna|save }}
Usuniecie nieużywanych funkcji z obsługi sesji
Usunięto kilka nieużywanych funkcji z komponentu obsługi sesji.Zmiana typu wyjątku ustawień
Zmianie uległy typy wyjątków generowanych w przypadku problemu z ustawieniami (brak pliku określonego przez DJANGO_SETTINGS_MODULE itd)Generyczne widoki domyślnie mają allow_empty na True
Zmieniono domyślną wartość allow_empty na True dla archive_index() i object_list()`MultipleObjectsReturned` zamiast `AssertionError`
Jeżeli QuerySet.get() zwróci więcej niż jeden rekord zostanie wyrzucony wyjątek `MultipleObjectsReturned`.Zmiana zachowania APPEND_SLASH
Jeżeli APPEND_SLASH ustawione jest na True, a Django dostanie URL nie kończący się ukośnikiem / sprawdzi czy może dopasować taki odnośnik zanim przekieruje na odnośnik z zamykającym ukośnikiem.Ujednolicenie konstruktorów ModelForm's i Form's
Przed:# formularz dodania
obj = MyObj()
form = MyForm(obj)
# formularz edycji
obj = MyObj.objects.get(pk=1)
form = MyForm(obj)
# formularz dodania
form = MyForm()
# formularz edycji
obj = MyObj.objects.get(pk=1)
form = MyForm(instance=obj)
Wyrzucanie wyjątku jeżeli extends nie jest pierwszym tagiem użytym w szablonie
Jeżeli tag "extends" jest używany to musi znaleźć się przed innymi tagami.Zmiana es_AR na es-ar w LANGUAGES
Zmiana Field.get_internal_type()
Dekoratory dziedziczą atrybuty funkcji, na których są używane
Usunięcie ado_mssql
Sterownik do ado_mssql został usunięty ze względu na brak obsługi. Jako alternatywę można użyć http://code.google.com/p/django-mssql/ lub http://code.google.com/p/django-pyodbc/.Queryset-refactor
W rewizji 7477 dodano kod z gałęzi Queryset-refactor, co zmienia nieco korzystanie z ORM, np. relacji OneToOne. Zmiany opisane są w dokumentacji relacji/modeli.Ściślejsze przypisywanie do ForeignKey
Zwiększono restrykcje dotyczące obiektów przypisywanych do ForeignKey i OneToOne.Usunięto OrderingField
Usunięto pole OrderingField, które pojawiło się w gałęzi MagicRemoval, lecz nigdy nie zostało wykorzystane.Pola BooleanFields wymuszają "required"
Dla pól BooleanField opcja "required=True" oznacza iż pole musi zostać zaznaczone. Jeżeli zaznaczenie pola nie jest wymagane należy dodać required=False.Usunięcie domyślnego sortowania User
Ze względu na duże wykorzystanie tabeli związanej z django.contrib.auth.models.User usunięto domyślne sortowania.Zmiany przesyłania plików
Zmianie uległ sposób przesyłania plików. Przed zmianą request.FILES zawierał dane w słownikach, a obecnie dane dostępne są w odpowiednim obiekcie. Całość zmian opisana jest w dokumentacji przesyłania plików.Narzędzia do tłumaczeń częścią `django-admin.py`
Funkcje pełnione przez make-messages.py zostały przeniesione do django-admin.py:django-admin.py makemessages -l xx django-admin.py compilemessages -l xx
Usunięty sterownik MySQL_old
Usunięto sterownik dla przestarzałej wersji `MySQLdb`Zmiany w metodach save_add, save_change i render_change_form z ModelAdmin
Usunięto kilka wewnętrznych funcji, w których model był przekazywany bez celu.Generyczne widoki używają newforms
Generyczne widoki dodawania/edycji używają newforms.Panel Admina generowany przez komponent newforms-admin
Wraz z obsługą newforms w Panelu Admina wprowadzono liczne zmiany w funkcjonowaniu i konfiguracji Panelu Admina. Dla urls.py:# STARE:
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'^admin/', include('django.contrib.admin.urls')),
)
# NOWE:
from django.conf.urls.defaults import *
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
(r'^admin/(.*)', admin.site.root),
)
Przeniesienie z modelu ```class Admin``` do klas ```ModelAdmin```
Panel Admina dla danego modelu nie jest już konfigurowany przez podklasę Admin w modelu, lecz przez klasę umieszczoną w admin.py# STARE:
# models.py
from django.db import models
class MyModel(models.Model):
name = models.CharField(max_length=100)
class Admin:
pass
# NOWE:
# 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)
# STARE:
# models.py
from django.db import models
class MyModel(models.Model):
name = models.CharField(max_length=100)
class Admin:
list_display = ('name',)
# NOWE:
# 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)
Zmiana opcji Admin.manager
Klasa ModelAdmin może mieć zdefiniowaną metodę queryset:class BookAdmin(admin.ModelAdmin):
def queryset(self, request):
"""
Filtrowanie po obecnie zalogowanym użytkowniku
"""
return self.model._default_manager.filter(user=request.user)
prepopulate_from definiowane w klasie Admin, a nie w modelu
W klasie ModelAdmin dodano opcję prepopulated_fields, która zastąpiła prepopulate_from z modeli.# STARE:
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
# NOWE:
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)
Przeniesienie dokumentacji PA do django.contrib.admindocs
Zmiana 'fields' na 'fieldsets', zmiana wartości 'classes'
"Fields" jest używane do ustawiania kolejności w formularzu. Obecnie akceptuje jedynie listę pól. "Fieldsets" służy także do ich grupowania. Jeżeli "classes" jest podane w specyfikacji pola, to zwracana wartość musi być zmieniona ze stringa na tuplę stringów:# STARE:
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'}),
)
# NOWE:
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')}),
)
Edycja zależnych modeli (inline editing)
# STARE:
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)
# NOWE:
# edit_inline nie jest potrzebne
from django.contrib import admin
class BookInline(admin.TabularInline):
model = Book
extra = 3
class AuthorAdmin(admin.ModelAdmin):
inlines = [BookInline]
admin.site.register(Author, AuthorAdmin)
Zmiana opcji `js` na `media`
# STARE:
class MyModel(models.Model):
# not relavent, but here for show
field1 = models.CharField(max_length=100)
class Admin:
js = (
"/static/my_code.js",
)
# NOWE:
# in admin.py
class MyModelAdmin(admin.ModelAdmin):
class Media:
js = (
"/static/my_code.js",
)
Przeniesienie raw_id_admin z modelu
Składnia jest niezależna od modelu# STARE:
class MyModel(models.Model):
field1 = models.ForeignKey(AnotherModel, raw_id_admin=True)
class Admin:
pass
# NOWE:
class MyModelAdmin(admin.ModelAdmin):
model = MyModel
raw_id_fields = ('field1',)
```django.contrib.auth``` używa newforms
Przeniesienie radio_admin z modelu
# STARE:
class MyModel(models.Model):
field1 = models.ForeignKey(AnotherModel, radio_admin=models.VERTICAL)
class Admin:
pass
# NOWE:
class MyModelAdmin(admin.ModelAdmin):
model = MyModel
radio_fields = {'field1': admin.VERTICAL}
Przeniesienie filter_interface z modelu
# STARE:
class MyModel(models.Model):
field1 = models.ManyToManyField(AnotherModel, filter_interface=models.VERTICAL)
field2 = models.ManyToManyField(YetAnotherModel, filter_interface=models.HORIZONTAL)
# NOWE:
class MyModelAdmin(admin.ModelAdmin):
filter_vertical = ('field1',)
filter_horizontal = ('field2',)
Zmiana nazwy newforms na forms
Zmiana określania ścieżek URL
URLe dzielone są przez serwer na dwie części - `SCRIPT_NAME` i `PATH_INFO`. Od rewizji 8015 Django bierze pod uwagę `SCRIPT_NAME` umożliwiając łatwiejsze udostępnianie aplikacji pod różnymi odnośnikami w domenie np. www.strona.pl/django/serwis/*.mod_python
Można pozostawić konfigurację bez zmian i wszystko będzie działać, lecz można też zastosować wprowadzone zmiany. Standardowa konfiguracja typu:<Location "/mysite/">
...
</Location>
<Location "/mysite/">
PythonOption django.root /mysite # Nowa linia
...
</Location>
Apache + fastcgi
Wystarczy usunąć prefiks z URLi, nie trzeba zmieniać konfiguracji serwera.lighttpd + fastcgi (and others)
Lighttpd nie przekazuje pełnych danych do ustalenia SCRIPT_NAME. By to rozwiązać należy w settings.py wymusić wartość tej zmiennej, np:FORCE_SCRIPT_NAME="/"
Zmiany działania filtru __in=[] dla pól numerycznych
authors = Author.objects.filter(id__in=author_ids.split(','))
Ograniczenia typów wartości dla DecimalField
Django wyrzuci wyjątek jeżeli do pola DecimalField przypisana zostanie wartość typu Float.Zmiana systemu resetowania hasła
Zmianie uległ układ ogólnych widoków resetowania hasła. Obecnie do użytkownika wysyłany jest email z linkiem do formularza zmiany hasła. Token staje się nieaktywny po 3 dniach od wygenerowania lub po użyciu w tym czasie.Usunięcie przestarzałych funkcjonalności dla Django 1.0
- Sterownik keszu "simple" został usunięty. Zaleca się używanie "locmem"
- Klasa `ObjectPaginator` została usunięta. Zaleca się stosowanie klas Paginator/Page
- Argument `edit_inline_type` dla `ForeignKey` został usunięty.
- Klasy `QOperator`, `QNot`, `QAnd` i `QOr` zostały usunięte. Należy używać klasy Q.
- Argument `maxlength` usunięty (zastąpiony przez `max_length`)
Ograniczenie dostępu do obiektów żądania
- `request[key]` -> `request.REQUEST[key]`
- `key in request` -> `key in request.REQUEST`
- `request.has_key(key)` -> `request.REQUEST.has_key(key)`
Tag `url` nie pomija wyjątku NoReverseMatch
Signal refactoring
Zaszły liczne zmiany w podsystemie sygnałów i slotów, które znacząco poprawiły ich wydajność. Obecną budowę tego komponentu znajdziemy w dokumentacji.Nowe domyślne widżety w Panelu Admina
Zmiany w komponencie składowania plików
`save_add` i `save_change` usunięte z `ModelAdmin`
`save_add` i `save_change` zostały usunięte, a `response_add` i `response_change` zostały dodane.Usunięcie przestarzałych funkcjonalności dla Django 1.0
- Usunięto możliwość wyświetlania plików jako napisów. Należy używać django.core.files.base.ContentFile
- Usunięto dostęp do załadowanych plików przez słowniki. Należy używać django.core.files.uploadedfile.SimpleUploadedFile
- Właściwości `filename`, `file_name`, `file_size`, i `chuck` zostały usunięty z `UploadedFile. Należy stosować `name`, `size` i `chunks`
- Metody `get_FIELD_filename`, `get_FIELD_url`, `get_FIELD_size` i `save_FIELD_file` dla modeli z `FileField` zostały usunięte.
- Metody `get_FIELD_width` i `get_FIELD_height` dla modeli z `ImageField` zostały usunięte.
- Funkcje `connect`, `disconnect`, `send` i `sendExact` z "dispatchera" zostały usunięte.
- Funkcje form_for_model` i `form_for_instance` zostały usunięte na żecz `ModelForm`.
- Usunięto `django.utils.images` na żecz `django.core.files.images`
- Argument `follow` w ogólnych widokach `create_object` i `update_object` został usunięty. Należy stosować `form_class` z newforms.
Wewnętrzne zmiany w sterownikach baz danych
Zmianie uległa wewnętrzna konstrukcja sterowników do baz danych. Zmiana ta nie wpływa na działanie standardowych metod ORMa.Added parameter to session backend save() method
Własne sterowniki (backend) sesji muszą zawierać parametr "must_create" w metodach "save()". Domyślnie jego wartość ustawiona jest na False. W przypadku True nowy obiekt sesji musi zostać stworzony lub wyrzucony zostanie wyjątek.Czyszczenie danych sesji przy wylogowaniu
Zmiana nazw polskich pól z localflavour
Zmianie uległy nazw pól na lokalnych danych:- PLPESELField
- PLNIPField
- PLREGONField
- PLProvinceSelect
- PLCountiesSelect
Usunięcie walidacji z modeli i pól modeli
Poprawiono MultiValueDict.iteritems by zwracała elementy a nie listę
Poprawki filtrów taga "timesince"
Usunięcie polecenia adminindex z django-admin
Zmiana django.contrib.comments
Nieudokumentowany stary system komentarzy został zastąpiony zupełnie nową aplikacją.Usunięcie oldforms, validatorów i powiązanego kodu
!ModelForms made more like Forms
Nie można już uzyskać dostępu do pól ModelForm jako atrybuty. Można natomiast poprzez słownik.`create()` i `get_or_create()` nie zaktualizują istniejącego obiektu
reverse() i tag szablonów url nie przyjmują dodatkowych argumentów
RkBlog
Comment article