Handle a click event in django-tables2 - django

I am starting to use django-tables2 and I have added a column which should allow user to delete a record when the user clicks on the button. The code looks as follows:
class ReviewTable(tables.Table):
delete = tables.LinkColumn('review_delete', args=[tables.A('pk')], orderable=False,
empty_values=(), verbose_name='')
def render_delete(self, record):
url = static('remove.png')
href = '#'
return mark_safe('')
This basically enders the image fine in a column but all I can do is set the link to it. How can I get it to call some method where I can then filter by the record ID and delete the relevant record? Is this the correct way to do this?

When you generate HTML from code, you still have access to onclick events.
return mark_safe(''.format(href, url)
Now your delete_action can be a javascript function that gives you more control. Generated HTML is basically just any old type of HTML, so you can still use jquery event handlers with it
BTW, please note how string formatting has been used in stead of concatenation. This is more pythonic

Related

How to make filtering non model data in flask-admin

I have to make dashboard like view in flask-admin that will use data retrieved from external API. I have already written a functions that get date ranges and return data from that range. I should use BaseView probably but I don't know how to actually write it to make filters work. This is example function that i have to use: charts = generate_data_for_dashboard('164', '6423FACA-FC71-489D-BF32-3A671AB747E3', '2018-03-01', '2018-09-01'). Those params should be chosen from 3 different dropdowns. So far I know only how to render views with pre coded data like this :
class DashboardView(BaseView):
kwargs = {}
#expose('/', methods=('GET',))
def statistics_charts(self):
user = current_user
company = g.company
offices = Office.query.filter_by(company_id=company.id)
self.kwargs['user'] = user
self.kwargs['company'] = company
charts = generate_data_for_dashboard('164', '6423FACA-FC71-489D-BF32-3A671AB747E3', '2018-03-01', '2018-09-01')
self.kwargs['chart1'] = charts[0]
self.kwargs['chart2'] = charts[1]
return self.render('stats/dashboard.html', **self.kwargs)
But I need some kind of form to filter it. In addition date filter dropdown should have dynamic options : current_week, last_week, current_month, last_month, last_year. Don't know where to start.
You should use WTForms to build a form. You then have to decide if you want the data to be fetched on Submit or without a reload of the page. In the former case, you can just return the fetched information on the response page in your statistics_charts view. But if you want the data to update without a reload, you'll need to use JavaScript to track the form field changes, send the AJAX request to the API, and then interpret the resulting JSON and update your dashboard graphs and tables as needed.
I have not used it, but this tutorial says you can use Dash for substantial parts of this task, while mostly writing in Python. So that could be something to check out. There is also flask_jsondash which might work for you.

Django - Create new object in Form, update select box and save it

I think what I'm trying to achieve is not hard, but I have no clue how to do it hehehehe !
Basically what I need is the feature that we have in Django Admin, when you are creating a new object, if you have a Foreign Key, you can add new data (opening a pop-up), save it and then the select box updates automatically.
What I have is this form:
I know that would be easy to do it with some Javascript, but my point is, Django has some rules, and as far I know, I can't add new data to a form already created, right? Otherwise Django won't validate this form. How could I achieve this?
PS: "Local" is the select box where I want to add new data. The user should be able to create a new Local on this page, instead of going to another page to do it. Thanks :)
Here your question:
I can't add new data to a form already created, right? Otherwise Django won't validate this form. How could I achieve this?
Then the answer:
you are right, django will check values match form value rules. But:
realize that your main form is invoked for twice: on GET and on POST. Between both form executions you make changes on database values trhough your new form. That means that in second main form invocation the value added to database is available:
field1 = forms.ModelChoiceField(queryset= ***1*** )
***1***: on second invocation new value is already available on field1.
Then, you don't should to be afraid about this subject, the new value will be available on form on your main form POST request.
Nothing wrong with updating the value using javascript as long the key in your new combo box has the right key in the database then it should be ok.
Call this function after you saved the last entry.
function refreshLocal(){
$.get(window.location.href, '', function(html){
// change the id to the local combox's id
var serverLocalDropBox = $(html).find('#id_local');
if (serverLocalDropBox.length){
$('#id_local').replaceWith(serverLocalDropBox);
}
})
}
If you don't want to use javascript solution, you can post the form with refresh flag and on the server side if you see that flag just don't validate and return the form as is. Since you have a new entry in the foreignkey it will automatically update the queryset to include the new entry.
function serverRefreshLocal(){
var $form = $('#your_form_id');
$form.append('<input type="hidden" name="refresh" value="true" />');
// you can use ajax submit and ajax refresh here if you don't want to leave the page
$form.submit();
}
// Server Side
def your_form_post_view(request):
if request.POST.get('refresh', 'false') == 'true':
# initial is the trick to save user input
your_form = YourForm(initial=request.POST)
context = {
'form': your_form,
}
return render(request, 'your_template.html', context)
# your view code goes here

Django - how to pass more than one primary key to the view

I need to write a view to delete multiple objects in one go.
I have modified the HTML template, put checkboxes to select which objects (users) to delete and a button to delete them, but of course you need a view to perform the task.
When you have one item to select at a time, you pass its primary key to the view through the url, how can I extend this to pass more than one primary key?
You would absolutely not be doing this via the URL. If you have a set of checkboxes, then you have a form; since the form is doing destructive operations it will be submitted via POST: therefore your set of IDs is in request.POST.
What you can do is to send the data in a JSON format, which can easily be decoded by Django
On the frontend, you'd have a JavaScript for a button like so,
function delete_object(pks) {
var args = {type: "POST", url: "/delete/", data: {'pks': pks}};
$.ajax(args);
return false;
}
this function would take selected the primary keys from (which is passed in as pks) and POST it to the Django url ^delete/$. A Django view function can then handle the incoming data like so,
def delete(request):
object_pks = request.POST['pks']
Docs.objects.filter(pk__in=object_pks).delete()

Django Processing Form to other Form

I have a view that is an input form that people input their information in (name, address, that sort of thing). They will then click an "ok" button.
After people click "ok" I want them to be redirected to a page that has a table with their inputted information.
Any ideas on how to do this?
So far, I have the first view. When clicking OK all the information is stored in a database. I just don't know how to use it from there.
Note: ModelForms are used
If you look carefully the documentation : https://docs.djangoproject.com/en/dev/topics/forms/#processing-the-data-from-a-form
You could understand that, once you have treated (is_valid() - cleaned_data['']), you have to do a call to
render_to_response('template',{ 'name':name, 'last_name':last_name..}, context_instance=RequestContext(request))
And, in the template called, just make the data you need be shown, as usual..
you could try to pass your newly created object to the next view (which shows the new object) like this, the called view just has to accept your object as parameter.
# ... your form processing here
if form.is_valid():
# create and save your object code here
your_object.save()
return redirect('show_new_data_view', your_object=your_object)
Hope this helps.

Django, Tastypie and retrieving the new object data

Im playing a little bit with heavy-client app.
Imagine I have this model:
class Category(models.Model):
name = models.CharField(max_length=30)
color = models.CharField(max_length=9)
Im using knockoutjs (but I guess this is not important). I have a list (observableArray) with categories and I want to create a new category.
I create a new object and I push it to the list. So far so good.
What about saving it on my db? Because I'm using tastypie I can make a POST to '/api/v1/category/' and voilĂ , the new category is on the DB.
Ok, but... I haven't refresh the page, so... if I want to update the new category, how I do it?
I mean, when I retrieve the categories, I can save the ID so I can make a put to '/api/v1/category/id' and save the changes, but... when I create a new category, the DB assign a id to it, but my javascript doesn't know that id yet.
in other words, the workflow is something like:
make a get > push the existing objects (with their ids) on a list > create a new category > push it on the list > save the existing category (the category doesnt have the id on the javacript) > edit the category > How I save the changes?
So, my question is, what's the common path? I thought about sending the category and retrieving the id somehow and assign it to my object on js to be able to modify it later. The problem is that making a POST to the server doesn't return anything.
In the past I did something like that, send the object via post, save it, retrieve it and send it back, on the success method retrieve the id and assign it to the js object.
Thanks!
Tastypie comes with an always_return_data option for Resources.
When always_return_data=True for your Resource, the API always returns the full object event on POST/PUT, so that when you create a new object you can get the created ID on the same request.
You can then just read the response from your AJAX and decode the JSON (i dont know about knockout yet).
see the doc : http://readthedocs.org/docs/django-tastypie/en/latest/resources.html?highlight=always_return_data#always-return-data
Hope this helps