Django: предоставя динамично генерирани данни като прикачен файл при натискане на бутон

Преглед на проблема:

Създавам базиран на Django клиент с намерението да върна данни от уеб услуга. Целта на този проект е да върне данни на потребителя от уеб услугата въз основа на стойностите, избрани от потребителя във формуляр. При подаване на формуляра се генерира низ на заявка, изпраща се до уеб услугата и данните за страницата се връщат като низ. В момента тези данни се показват на потребителя в браузъра. Искам да осигуря функционалност, която ще позволи на потребителя да щракне върху бутон и да изтегли данните.

Въпрос:

Как мога да върна данните на потребителя, когато щракне върху бутон в своя браузър за изтегляне? Как да направя налични различни опции за едни и същи данни (т.е. приложение/json или текст/csv)?

Текуща (неработеща) реализация:

Опитвам се и не успявам да направя следното:

views.py

Връщане на обект render_to_response от моя шаблон. Към шаблона предавам формуляра и данните в него са различни форми.

def view(request):
    #Do stuff, get data as string

    #Get data into needed formats (see utils.py)
    jsonData  = jsonToJsonFile(dataString, fileName)

    return render_to_response('template.html', {'someForm'    : aForm,
                                                'regularData' : stringData,
                                                'jsonData'    : jsonData...})

utils.py

Съдържа функции за приемане на данните като низ и връщане на обекти за отговор. Тази част не съм сигурен дали правя правилно. Извиквам тези функции в изгледа, за да получа jsonData (и csvData) в правилните им формати от оригиналния низ с данни.

def jsonToJsonFile(dataString, fileName):

    #Get the data as json
    theData = json.dumps(dataString)

    #Prepare to return a json file
    response = HttpResponse(theData, mimetype = 'application/json')
    response['Content-Disposition'] = 'attachment; filename=' + str(fileName) + '.json'

    #return the response
    return response 

template.html

В момента предавам отговорите в шаблона. Това е мястото, където наистина съм изгубен и все още не съм започнал да намирам добро решение. Очаквам, че ще трябва да използвам javascript, за да върна променливите (jsonData и csvData) на потребителя, когато се щракне върху бутона. Опитах се да използвам действието onclick на anchor класа и след това използвах javascript, за да върна променливата django на отговора - но това наистина не работи.

<li class = 'button'>
    <a  href = "#dataButtons" onclick = "javaScript:alert('test');"> 
    TEST
    </a>
</li>
<li class = 'button'>
    <a  href = "#dataButtons"  onclick = "javaScript: var a = '{{ jsonData }}'; return a;"> 
    JSON
    </a>
</li>

Сложих тестовата част там, за да тествам дали предупреждението ще работи или не. Това го прави. Въпреки това, когато щракна върху бутона за json данните, нищо не се случва.

Напълно погрешно ли подхождам към това? Или има нещо малко, което ми липсва?


person mshell_lauren    schedule 11.10.2011    source източник
comment
Можете ли да публикувате и javascript, защото ако нищо не се случи, трябва да е от страна на клиента. Ако върнатите стойности са грешни и се показват в страница вместо изтегляне, това би било от страна на сървъра.   -  person Umur Kontacı    schedule 12.10.2011
comment
javascript е в секцията на моя шаблон. Всъщност това е само ред: onclick = javaScript: var a = '{{ jsonData }}'; връщане на a; където {{jsonData}} е django променливата на отговора. От това, което мога да кажа, стойностите, получени от уеб услугата, са правилни. Когато визуализирам променливата jsonData направо от изгледа (т.е. връщам jsonData), тя отваря файла за изтегляне, както трябва и данните са добре - което ме кара да вярвам, че вероятно е така, както го наричам в шаблона.   -  person mshell_lauren    schedule 12.10.2011


Отговори (2)


Решение:

След като разгледах проблема малко по-нататък и разговарях с колега за него, изглежда, че проблемът ми се крие в опит да предам обекта за отговор на javascript. За тези, които се интересуват, реших проблема с малко внимателно пренасочване на данните.

views.py

В моя views.py добавих няколко реда код в моя основен изглед, който ще зададе променливи на два допълнителни изгледа (един за csv, един за json) към обектите за отговор, съдържащи данните. След това тези два допълнителни изгледа ще бъдат извикани при натискане на съответните им бутони, връщайки httpresponse и подканвайки потребителя за изтегляне.

#MAIN VIEW FUNCTION
def view(request):
    #Do stuff, get data as string

    #Get data into needed formats 
    jsonData  = jsonToJsonFile(dataString, fileName)

    #Set values to external view ****NEW PART****
    returnJSON.jsonData = jsonData

    #Render main template
    return render_to_response('mainTemplate.html', {'someForm'    : aForm,
                                                    'regularData' : dataString})

#SECONDARY VIEW TO RETURN JSON DATA TO USER ****NEW PART****
def returnJSON(request):
    #Simply return the response
    return returnJSON.jsonData

template.html

След това, когато бутонът е натиснат от потребителя, котвата се свързва чрез url към вторичния django изглед, който ще представи опцията за изтегляне на потребителя.

<li class = 'button'>
    <a  href = "{% url client.views.returnJSON %}"> 
        JSON
    </a>
</li>

urls.py

И накрая, току-що посочих моите URL модели към изгледа.

urlpatterns = patterns('',
    (r'^somesite/$', views.view),
    (r'^somesite/json$',  views.returnJSON),
)

Досега този метод работи чудесно за мен! Ако някой има други предложения или по-добър метод, със сигурност ще бъда готов да го чуя.

person mshell_lauren    schedule 13.10.2011

Мисля, че трябва да промените своя javascript, за да започне изтегляне на файл - вижте този въпрос и отговор: стартиране на изтегляне на файл с JavaScript

person dustyneuron    schedule 11.10.2011
comment
хммм, благодаря, но нямам точно файл, който да съществува, където да мога да направя връзка. Предполагам, че мога да запазя данните във файл, но се надявам да стоя далеч от това като опция, тъй като добавя още едно ниво на сложност. Надявам се, че има начин да извлечете данните, без да извиквате изгледа. - person mshell_lauren; 12.10.2011
comment
А, разбирам какво имаш предвид. Нещо, наречено „URI адреси на данни“, може да помогне:stackoverflow.com/questions/3665115/ - person dustyneuron; 12.10.2011
comment
Това всъщност изглежда много полезно и ще го имам предвид за бъдещи проекти! След като разгледах няколко варианта обаче, мисля, че намерих доста добро решение за сега... - person mshell_lauren; 13.10.2011