2014-05-09 13 views
6

Chcę utworzyć link, który otwiera stronę admin django dodaj stronę modelu z wypełnionymi polami.admin django "dodaj stronę" początkowa data-godzina z parametrów GET

sprawdziłem, że jest możliwe, aby dodać parametry do słownika GET formularza dodawania, jak w:

<a href='/admin/myapp/mymodel/add?name=John'>add new mymodel with name John</a> 

(właściwie uzyskać url {% url 'admin: myapp_mymodel_add' %} ale to jest po prostu jawne).

Teraz to działa dobrze z wartościami liczbowymi, wartościami tekstowymi i kluczami obcymi. Ale co z polami DateTime? Kiedy próbuję przekazać takie pole (próbowałem wielu formatów, jak na przykład "2014-05-09 10:10:00"), zawsze otrzymuję komunikat "błąd serwera" narzekający:

Obiekt "Unicode" nie ma atrybutu 'data'

w linii kodu:

django/formy/widgets.py w dekompresji, linia 902

def decompress(self, value): 
     if value: 
      value = to_current_timezone(value) 
      return [value.date(), value.time().replace(microsecond=0)] ... 
     return [None, None] 

gdzie zmienna "wartość" ma wartość, którą przekazuję pod adresem URL ...

Pytanie 1. Założę się, że kod serwera nie powinien wywoływać wyjątku w zależności od wartości przekazywanych przez użytkownika ... czy nie jest to błąd w bibliotekach django?

Pytanie 2. Jak mogę rozwiązać mój problem, tj. Przekazać początkową datę i godzinę za pomocą parametrów GET na stronę administratora "dodaj" modelu?

+0

Czy wypróbowałeś ten format: '2010-09-28 + 21: 00: 59'? – alecxe

+0

Próbowałem: ten sam błąd ... –

+0

OK, jeśli podzielisz datę i godzinę na 2 osobne parametry: '? Date_field_name_0 = 2010-09-28 i date_field_name_1 = 21: 00: 59', gdzie' date_field_name' to nazwa twoje pole datetime? – alecxe

Odpowiedz

3

Nie, to nie jest błąd; być może argument, że domyślne zachowanie można poprawić, ale istniejąca implementacja jest rozsądnym pierwszym krokiem (o czym świadczy fakt, że działa na liczbach całkowitych, łańcuchach, kluczach obcych itp.). Jest wystarczająco dużo metadanych na temat modelu i wystarczająco dużo kodu deserializacji, że byłoby to możliwe, aby zrobić nieco lepszą obsługę tutaj, ale nie sądzę, że jest to prosty błąd.

Dobrą wiadomością jest to, że istnieje oficjalny sposób poradzenia sobie z tym; na swojej klasie ModelAdmin zdefiniować:

def get_changeform_initial_data(self, request): 

Metoda ta przyjmuje wniosek, i konwertuje ten wniosek do wartości, które zostaną przekazane w jak initial argument do postaci na liście zmian (tj dodawać lub edytować strona w Admin). Jak można się spodziewać, domyślną implementacją tej metody jest "pobranie argumentów GET i przekonwertowanie ich na słownik"; Jeśli wykonasz dodatkowe operacje dla pól, które wiesz, że są datami, wówczas możesz w ogóle nie używać obiektu żądania. Alternatywnie, nie musisz w ogóle używać obiektu żądania. Jeśli wiesz, że obiekty „osoba” będzie zawsze mieć wstępną nazwę „Unknown”, a początkową datą rozpoczęcia dnia 1 stycznia 2014 roku, a następnie można po prostu napisać:

class PersonAdmin(ModelAdmin): 
    ... 
    def get_changeform_initial_data(self, request): 
     return { 
      'name': 'Unknown', 
      'start_date': date(2014, 1, 1) 
     } 

czyli nie zwracać żadnej uwagi do danych żądania, wystarczy wypełnić dane początkowe ręcznie. Ponieważ są to dane początkowe w formularzu, wszelkie istniejące dane na obiekcie zastąpią wartość podaną w initial, a początkowe dane zostaną użyte bez konieczności podawania przez użytkownika w ich żądaniu argumentów.

+0

Dzięki! Widzę, że ta metoda jest dostępna z django 1.7 niestety obecnie używam 1.5. O błędzie lub nie: ten problem dotyczy każdego interfejsu administratora opartego na modelu z polami daty. Nawet jeśli programista nie planuje używać parametrów GET (i być może nie jest świadomy tej możliwości), interfejs administracyjny udostępnia je i otwiera każdemu administratorowi możliwość wygenerowania błędu serwera. Przed wersją 1.7 jest to również bardzo trudne do naprawienia (myślę, że wymagałoby to przedefiniowania ModelAdmin.changeform_view). –

+0

W każdym razie jest to tylko dyskusja akademicka, ponieważ zgadzam się, że interfejs administratora powinien być używany przez wybraną klasę użytkowników, którzy mają już o wiele więcej "niebezpiecznych" uprawnień dostępu i modyfikowania bazy danych. Jednak myślę, że "poprawne" domyślne zachowanie dla aplikacji administratora powinno polegać na napisaniu do użytkownika komunikatu o błędzie, jak gdyby wartość została wstawiona z parametrem POST, lub może podnieść InvalidRequest zamiast ServerError. –

1

Wygląda na to, że problem polega na przekazywaniu ciągu znaków, gdy oczekuje on daty. Najpierw należy przekształcić ciąg znaków w datę.

Można użyć wbudowanego w Pythonie biblioteki datetime:

import datetime 
value = datetime.datetime.strptime(value, "%Y-%m-%d %H:%M:%S") 
def decompress(self, value): 
    ... 

Edycja: alecxe słusznie zauważył, że nie został poprawnie odpowiadając na pytanie. Przy odrobinie poszukiwań znalazłem coś, co może być bardziej trafne.

Zgodnie z tym answer, Django pozwala na wymianę słownika GET przed jego przetworzeniem. Pożyczki z tego przykładu, wydaje się możliwe, że możemy przejąć parametry GET i zastąpić daty ciąg z obiektami datetime w słowniku GET

def add_view(self, request, form_url='', extra_context=None): 
     // any extra processing can go here... 
     g = request.GET.copy() 
     g.update({ 
      'date':datetime.datetime.strptime(request.GET.get('date'), "%Y-%m-%d %H:%M:%S"), 
     }) 

     request.GET = g 
     return super(MyModelAdmin, self).add_view(request, form_url, extra_context) 
+0

Nie dotyczy problemu opisanego w pytaniu. – alecxe

+0

Nie zgadzam się. Emanuele Paolini zgłasza, że ​​odebrany komunikat o błędzie to "unicode" obiekt nie ma atrybutu "date" ". Jest to spowodowane próbą wywołania metody .date() na obiekcie unicode. – Del

+0

Nie kłócę się o to. Problem polega na tym, że nie jest to kod, który sam napisał. Jest częścią kodu źródłowego django. Jest to albo błąd, który należy zgłosić, albo powinien istnieć sposób (lub obejście), aby działał. – alecxe