How to pass manytomany PKs to post or put - django

class AlbumSerializer(serializers.ModelSerializer):
tracks = serializers.PrimaryKeyRelatedField(many=True, queryset=Track.objects.all(), )
class Meta:
model = Album
fields = ('album_name', 'artist', 'tracks')
what is the format for adding multiple tracks
tracks is a manytomany field
tried array, comma separated but no luck
If I pass
track = "Track1"
where "Track1" is the primary key of Track 1
How to add ['Track1', 'Track2']
Actual code
class TreatmentTemplateSerializer(serializers.ModelSerializer):
icds = serializers.PrimaryKeyRelatedField(read_only=False, many=True, queryset=ICD_10.objects.all())
class Meta:
model = Treatment_template
Screenshot 1
Postman supports array in above format??
Screenshot 2
Screenshot 3

Sending plain JSON objects
I would suggest testing complex request data (including arrays or nested objects) by directly sending JSON rather than form-data or x-www-form-urlencoded. To do this click on raw and paste your JSON object there.
To get a well-formatted JSON object to start with I usually first issue a GET request for a resource that already exists. Then I can just copy the response, change the request method to PUT, click the raw button and paste the json. Then I can start modifying the object and test the endpoint.
In the example above, does the following work?
{
"uuid": "the-long-uuid-here",
"icds": [
"A00",
"A001"
]
}
Update: Put multiple m2m ids with x-www-form-urlencoded
As I wasn't completely happy with not providing an alternative I tested a bit more (with the latest Postman which looks differently).
You can pass multiple values using x-www-form-urlencoded. To do that, add multiple rows with the same label icds and one value at a time.
Notice that I tested it with an endpoint that provides books, which would be icds in your use case. The data in the screenshot will be transmitted as books=1&books=3&last_name=foobar which gets correctly picked up by the DRF endpoint.
Screenshot Postman

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.

Change model-object at PUT and update before GET in django-rest-framework

Sorry about the confusing title, but I don't know how to describe it better.
I need to run a model-function on the object I am editing using PUT in Django-Rest-Framework, which uses some of the new data from the PUT to calculate some new values it should save in the same model.
Example:
An item with {'amount': 2, 'price': 0, 'total': 0} is already stored in the database.
I am then updating price to 1 using a normal PUT request using django-rest-framework.
The model have a helperfunction called update_total() which I need to call to update the total field in the database (to, in this case 2 (2*1)).
The item is updated in the database, but the response returned from django-rest-framework is still showing total=0. After getting the object on new, total will be 2 as expected.
I need the response to be 2 in the response from the PUT, not after a regrab of the object. But how?
I have tried several things (which all doesn’t work):
Updating attrs in a validator to the new value.
Using post_save() in ListCreateAPIView to update the data.
Using pre_save() in ListCreateAPIView
Updating instance in restore_object() (even though it isn't for this purpose)
Does this look like a bug? Or is there another trick?
I kinda found a solution, but it feels somewhat dirty..
In my serializers restore_object I put code like this:
new_values = instance.update_counters()
for k, v in new_values.items():
self.data[k] = v
and in my models update_counters() function, I am returning a dict of what I changed..

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

How to serialize to json format a queryset that use the 'extra' statement in Django?

I want to serialize a QuerySet that contains an extra statement:
region_list = Region.objects.extra(select={ 'selected': 'case when id = %s then 1 else 0 end' % (new_region.id)}).all()
I use the statement below to serialize
return HttpResponse(serializers.serialize('json', region_list), mimetype='application/json')
But when I obtain the json results in the browser, only the fields of the Region model appears, the selected field dissapear.
How can I fix that?
One slightly longwinded solution would be to to dump the objects to JSON via django-piston's JSONEmitter class. When you register your Region model with piston, you can say what fields to include, and mention 'selected' there, and then use your annotation to make sure that the queryset used in the piston handler contains all the info you want.
Or just look at how piston does it and, if you don't want all of piston, just mimic the bits you do.

django admin filter tweaking

I want to use django's admin filter on the list page.
The models I have are something like this:
class Location(model):
name = CharField()
class Inquiry(Model):
name = CharFiled()
location = ManyToManyField(Location)
Now I want to filter Inquiries, to display only those that contain relation to specific Location object. If I use
class InqAdmin(ModelAdmin):
list_filter = ['location', ]
admin.site.register(Inquiry, InqAdmin)
the admin page displays me the list of all Locations and allows to filter.
What I would like to get, is to get list of only those locations that have some Inquiries in relation to them (so I don't ever get the empty list result after filtering).
How can this be done?
You could create a custom manager for Locations that only returns Locations that have an Inquiry associated with them. If you make this the default manager, the admin will use it.
Only caveat is that you'll need create another manager that returns all Locations and use that in the rest of your app whenever you want to retrieve Locations that don't have an associated Inquiry.
The managers section in the Django docs is quite good, and should be all you need to get this set up.
EDIT:
sienf brings up a good point. Another way to accomplish this would be to define a subclass of django.contrib.admin.SimpleListFilter, and write the queryset method to filter out Inquiries with empty Locations. See https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_filter