Django creating model instances - Validation before creation? In manager class? What is manager class for? - django

Say I have a class "Book" and I want to hit an API to verify the book exists before creating my model.
Do I create my "BookManager" class, override create, hit the api, and throw an exception if not valid or create if valid?
Then in Book I'd write objects = BookManager()
And create a book with.
new_book = Book.objects.create(name)?
Basically, this feels like a good way to organize my code, but I'm not sure if this is intended use for the Manager class as opposed to only modifying the queryset.
Additionally, does anyone have a good reference on how to structure your django rest framework app? Folder structure etc

I will start with very basics. I am assuming you api calls are simple get requests for now which you can achieve with python http package.
(I am assuming the api is a third party api for now)
you can define a simple view let say view name be : bookM
Next you have defined you model with lets say a primary key, book_name, other_attrs, date
now when you hit you api within this view you can get the response from get request
requests.get(url = URL, params = PARAMS)
With this if you find the response sent back with some text or null you can act on model as below :
book= BookSave(
name = "book1",
)
book.save()
If this is not the case you can save error message in python variable and display while rendering html
You can use this view as api and do ajax call from web page, as well in this case you can just return back messages

Related

how to make list as a parameter in the [GET, POST] methods

I'm working on a data set of 'Human activity recognition using smart phones'
would like to link the data with an API using flask, which can be reflected on a web page.
so I want to create a list to take all the human body movements in the data set as a parameters in a list which If I pass it to the predict route in the flask through a web page enables the model to predict the human body activity.
Put the list in a JSON object. You can use jsonify for this.
#app.route('/get_fruits')
def get_fruits():
response = {"fruits": ["apple", "banana"]}
return jsonify(response)

Choosing correct Django delete view approach

I'm working on Django website and I have problem in figuring out correct/good way to handle delete view. From what I found out there are two ways to approach it:
1
class ObjectDeleteView(DeleteView):
model = Object
def get_success_url(self):
objectid = self.kwargs['object_id']
object = Object.objects.get(id = objectid)
container = object.container
containerid = container.id
url = reverse('Containers:showContainerContent', args=[containerid])
return url
def get_object(self):
return get_object_or_404(Object, pk=self.kwargs['object_id'])
2
def objectDelete(request, object_id):
object = Object.objects.get(id = object_id)
container = object.container
containerid = container.id
url = reverse('Containers:showContainerContent', args=[containerid])
return HttpResponseRedirect(url)
From what I can tell both are doing exactly the same thing - once object is deleted present user with page under Containers:showContainerContent.
The big difference I am experiencing is error I am getting when running unit test for this (simple call of the website and check of response code). With option 1 I end up getting error
django.template.exceptions.TemplateDoesNotExist: ContainerApp/object_confirm_delete.html
Which I understand - I don't have this template, this is default template for DeleteView, hence error is correct. The thing is I don't want to have any extra page. Just redirect user and that's it.
Also, I tested changing return url to return HttpResponseRedirect(url) in option 1, but result is the same.
What should I do here? Should I just continue with option 2? What are or might be the drawbacks for this approach?
There is a major difference between two class based delete view and function based view (the way you declared it).
CBV accepts get, post and delete http methods. When you send a get request to class based view, it does not delete the object. Instead it renders template with object to be deleted in context. This is basically used to have confirmation. For example you can send a get request and it will render a template with text "Do you really want to delete?" or "Please confirm blah blah..". And if you send a post or delete request, it will actually delete the object and redirect to next page.
FBV, on the other hand, give you full control over what you want to do. And as you declared it, it will accept any request type and delete the object and redirect to next page because you have not done any request type check in your view which is not a great idea IMHO. You should not allow deletion on get requests. They should be idempotent. There are plenty of otherthings that CBV provides. For example in case the object does not exist your FBV will crash. CBV, on contrary, will return proper 404 response if object does not exist.
So I think there is no bad in using FBV, but make is strong and secure enough that it handles every case (what if object does not exist?, what about confirmation?, GET should be idempotent only allow deletion with post? etc etc). Or simply use CBV.

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 "request" object

I just started learning Django and Python a few weeks ago and have been tasked with a project to manage form processing using a Django/Python/MySQL combination. My background is in C++, so if there are any C++ analogies in Python/Django syntax please feel free to reference them.
So far I understand what the HTTPRequest objects do, but can't understand this snippet of code:
#login_required(login_url="/some_directory/")
def xyz(request):
item1 = request.GET['item1']
user = request.user
page = Page.objects.get(title = item1)
item1info = {}
perm_all = get_perms(user,page)
item1info["industry"] = page.industry.split(',')
For the first line what does "#" do? Is "#login_required" a Django command or was was it defined by the coder already?
I know "def xyz(request)" defines a function, but is the parameter "request" something that's been pre-defined in another file (urls.py)?
What does request.GET['item1'] do? Is it retrieving the value of the element "item1" from the query string?
"#" is a Decorator. Login required is a decorator provided by Django that requires the current user (in request.user) to be logged in to visit this view.
The "request" parameter is passed to the View function when its called, by Django itself. Any valid view function must receive the request as a paramete
Request.GET is a python dictionary that contains all the parameters passed in the request by GET method (as part of the URL querystring).

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