How to set up raw_id_fields in django-rest-framework? - django-rest-framework

In Django admin, one can set up a raw_id_fields in order to have a search widget instead of a select box. This is very neat to spare up a lot of database queries when the foreign key table is huge.
What is the equivalent in the Django Rest Framework browsable views?

Django Rest Framework 3 no longer supports widget attribute on serializer field. But to get your browsable API even usable, try changing style attribute to use 'base_template': 'input.html' as in following example:
class CustomerAddressSerializer(serializers.ModelSerializer):
customer = serializers.IntegerField(source='customer_id' style={'base_template': 'input.html', 'placeholder': "Customer ID"})
class Meta:
model = models.CustomerAddress
fields = ('id', 'customer', 'street', 'zip', 'city')
This way your huge select tag with thousands foreign key options will change to simple text input. For more info check docs at http://www.django-rest-framework.org/topics/browsable-api/#handling-choicefield-with-large-numbers-of-items

There's nothing to support this currently. I'm pretty sure that pull requests would be welcomed.

Seconding what Carlton says, although it'd be worth discussing in a ticket prior to taking a stab at the implementation.
Alternatively, you might want to take a look at using an autocomplete widget...
http://www.django-rest-framework.org/topics/browsable-api/#autocomplete

Related

Best practice for custom REST actions with API Platform

This top-ranking Stackoverflow answer from 10 years ago suggests using POST /users/:user_id/reset_password to initiate a password reset.
I know the API platform recommends against using custom operations. The docs page for the Symfony Messenger integration uses a ResetPasswordRequest entity (with a username field). That makes sense to me. 
Say I have a User and Notification entity and maybe a joined UserNotification (with a hasRead) entity as well. I want to expose an endpoint on my API to mark all the notifications older than a month as read. So I might make a ClearOldNotification entity, again with a username field.
Another example might be I want a report showing Customers that haven't been contacted due to some criteria. So I want to join the tables in the server and return a custom JSON data object. Again I could make a CustomerNoContact entity.
The issue I see is that I now have a distinction between pure entities, like a User or Product, as opposed to these service type entities.
Is this method of making individual entities classes for actions the recommended, best practice for Symfony and API Platform?
Should I be name-spacing (or something) these entities differently within my app to distinguish them?
I could imagine on a really large and complex application you could have hundreds of these service entities, compared to the pure entities. Is that expected or desired?
Can anyone recommend some good resources on this pattern?
You're asking for a best practice for two different use cases. Let's break it down:
ClearOldNotification
I think you've already found the solution: using Messenger. As you've read, there is an example in the documentation for this use case:
#[ApiResource(collectionOperations: [
"post", "get", "delete",
"reset_password" => ["status" => 202, "messenger" => "input", "input" => ResetPasswordRequest::class, "output" => false, "method" => "POST", "path" => "/users/reset_password"]
]
)]
final class User
{
}
The ResetPasswordRequest class is a Data Transfer Object (DTO). In your ResetPasswordRequestHandler you should inject the service that is responsible for resetting the password and sending an email.
CustomerNoContact
This could be a Custom (Doctrine ORM) Filter.

Odoo Warning - Missing Record Record does not exist or has been deleted . While creating new customer

Here is the screenshot of the warning which is apperaing while creating customers
I am not able to create new customers in odoo.
Initially I have done some customization in my module ...after that customization my code worked absolutely right, I have created new customers also..but after I dont know why i am not able to create new customers...
please suggest me some solution.
Thank you
I've had a similar problem related to a customized module in Odoo 10. I did some pretty thorough research and the Odoo ORM is doing some things it probably shouldn't be and that I'm not smart enough to sort out.
The sections in the Odoo 10 ORM API Documentation about creating models and fields were kind of helpful, but the documentation on the ORM is severely lacking and in some cases incorrect.
I eventually fixed it by doing the insert manually with the self.env.cr psycopg2 cursor available in the model's custom methods.
That would look something like the
from odoo import models
class your_class(models.Model):
def custom_create_method(self):
self.env.cr.execute("""
INSERT INTO customer_model_name
(name, value, other_value)
VALUES
('{}', '{}', '{}')
RETURNING id;
""")
new_id = self.env.cr.fetchone()
This has the disadvantage of introducing the possibility of an SQL injection attack into your code, so you'll need to be careful of that.
This is definitely not the ideal solution, but it does work. I believe the problem to be related to the Odoo ORM's handling of computed fields, but that is just a not-really-all-that-educated guess at what's going on.
Hope this helps.
For some reason we found a pattern where we had to comment out one of the dependancies, reinstall/update the module in question, then put it back in. In this case it was res in the custom module's __manifest__.py
i.e.:
'depends': ['base', 'res', 'sale_management', 'account', 'account_payment'],
#'depends': ['base', 'sale_management', 'account', 'account_payment'],
Becomes:
#'depends': ['base', 'res', 'sale_management', 'account', 'account_payment'],
'depends': ['base', 'sale_management', 'account', 'account_payment'],
Then install, see if the error goes away, then shut down the server and flip the comment again

Should I use singletableview?

I'm learning about Django tables. I first wrote a basic example, here my view:
def people1(request):
table = PersonTable(Person.objects.filter(id=2))
RequestConfig(request).configure(table)
return render(request, 'people.html', {'table': table})
This way I've been able to easily display a table with a filter condition "filter(id=2))".
After that I found SingleTableView which is supposed to be an easier way to display database tables, as an example I wrote this view, which worked fine:
from django_tables2 import SingleTableView
class PersonList(SingleTableView):
template_name = 'ta07/comun.html'
model = Person
table_class = PersonTable
Questions are: how should I do to apply filters like in the first example? And is SingleTableView better than the basic way?
I'd say for now, you should only use it for the very basic use case. As soon as you need customizations from that, use your own.
Since filtering is a very common use case, I might consider adding that to the features of SingleTableView at some point. If you need it before that, feel free to open a pull request.

Update model attribute without refreshing database

I'm building a website listing poker tournaments. I would like to allow user mark some tournaments as his favourite and avoid forms or extra page with GET parameter - I would like to to update it without refreshing website. From what I understand, it's done by ajax and jquery. But there are many ajax libraries and I would like you to tell me, which one should I use and how to do this simple functionality best.
This is my tournament table:
I would like to have another column before event time, that would contain image for heart. It would be black (not favourite) and if user clicks on it, it would turn red (favourite).
I think m2m relationship should be used here. This is my tournament model.
class Tournament(models.Model):
favourite = models.ManyToManyField(User)
date = models.DateTimeField('Event time')
currency = models.CharField(max_length=5, choices=CURRENCIES, default='USD')
name = models.CharField("Tournament name", max_length=200)
prize = models.DecimalField(max_digits=20, decimal_places=2)
entry = models.DecimalField(max_digits=20, decimal_places=2)
fee = models.DecimalField(max_digits=20, decimal_places=2)
password = models.CharField("password", max_length=200)
type = models.ForeignKey('room.Type')
room = models.ForeignKey('room.Room')
requirements_difficulty = models.IntegerField('Tournament Difficulty',
validators=[MinValueValidator(1), MaxValueValidator(30)])
requirements_text = models.CharField("Requirements Description", max_length=1000)
recurrence = models.CharField(max_length=5,
choices=RECURRENCE_CHOICES,
default='NONE')
So how do I add m2m relationship between user and tournament? Do I use ajax code or dajax? How do I create this m2m without refreshing page?
So how do I add m2m relationship between user and tournament?
Assuming that you use the default django user model:
Class Tournament(models.Model):
user = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='user_tournament')
...
Do I use ajax code or dajax?
As #doniyor said, you should define your real problem and split your question. SO is not "do it for me", anyway, what I can do for you, is give you some good links ;)
W3 schools definition for ajax:
http://www.w3schools.com/ajax/ajax_intro.asp
Good ajax plugin for djando that seems you already know:
http://www.dajaxproject.com/
By the way, you should use dajax, is easy and faster to create ajax pages integrated with django (you just have to follow the tutorials, is pretty simple).
How do I create this m2m without refreshing page?
Using dajax

CakePHP, organize site structure around groups

So, I'm not quite sure how I should structure this in CakePHP to work correctly in the proper MVC form.
Let's, for argument sake, say I have the following data structure which are related in various ways:
Team
Task
Equipment
This is generally how sites are and is quite easy to structure and make in Cake. For example, I would have the a model, controller and view for each item set.
My problem (and I'm sure countless others have had it and already solved it) is that I have a level above the item sets. So, for example:
Department
Team
Task
Equipment
Department
Team
Task
Equipment
Department
Team
Task
Equipment
In my site, I need the ability for someone to view the site at an individual group level as well as move to view it all together (ie, ignore the groups).
So, I have models, views and controls for Depart, Team, Task and Equipment.
How do I structure my site so that from the Department view, someone can select a Department then move around the site to the different views for Team/Task/Equipment showing only those that belong to that particular Department.
In this same format, is there a way to also move around ignoring the department associations?
Hopefully the following example URLs clarifies anything that was unclear:
// View items while disregarding which group-set record they belong to
http://www.example.com/Team/action/id
http://www.example.com/Task/action/id
http://www.example.com/Equipment/action/id
http://www.example.com/Departments
// View items as if only those associated with the selected group-set record exist
http://www.example.com/Department/HR/Team/action/id
http://www.example.com/Department/HR/Task/action/id
http://www.example.com/Department/HR/Equipment/action/id
Can I get the controllers to function in this manner? Is there someone to read so I can figure this out?
Thanks to those that read all this :)
I think I know what you're trying to do. Correct me if I'm wrong:
I built a project manager for myself in which I wanted the URLs to be more logical, so instead of using something like
http://domain.com/project/milestones/add/MyProjectName I could use
http://domain.com/project/MyProjectName/milestones/add
I added a custom route to the end (!important) of my routes so that it catches anything that's not already a route and treats it as a "variable route".
Router::connect('/project/:project/:controller/:action/*', array(), array('project' => '[a-zA-Z0-9\-]+'));
Whatever route you put means that you can't already (or ever) have a controller by that name, for that reason I consider it a good practice to use a singular word instead of a plural. (I have a Projects Controller, so I use "project" to avoid conflicting with it.)
Now, to access the :project parameter anywhere in my app, I use this function in my AppController:
function __currentProject(){
// Finding the current Project's Info
if(isset($this->params['project'])){
App::import('Model', 'Project');
$projectNames = new Project;
$projectNames->contain();
$projectInfo = $projectNames->find('first', array('conditions' => array('Project.slug' => $this->params['project'])));
$project_id = $projectInfo['Project']['id'];
$this->set('project_name_for_layout', $projectInfo['Project']['name']);
return $project_id;
}
}
And I utilize it in my other controllers:
function overview(){
$this->layout = 'project';
// Getting currentProject id from App Controller
$project_id = parent::__currentProject();
// Finding out what time it is and performing queries based on time.
$nowStamp = time();
$nowDate = date('Y-m-d H:i:s' , $nowStamp);
$twoWeeksFromNow = $nowDate + 1209600;
$lateMilestones = $this->Project->Milestone->find('all', array('conditions'=>array('Milestone.project_id' => $project_id, 'Milestone.complete'=> 0, 'Milestone.duedate <'=> $nowDate)));
$this->set(compact('lateMilestones'));
$currentProject = $this->Project->find('all', array('conditions'=>array('Project.slug' => $this->params['project'])));
$this->set(compact('currentProject'));
}
For your project you can try using a route like this at the end of your routes.php file:
Router::connect('/:groupname/:controller/:action/*', array(), array('groupname' => '[a-zA-Z0-9\-]+'));
// Notice I removed "/project" from the beginning. If you put the :groupname first, as I've done in the last example, then you only have one option for these custom url routes.
Then modify the other code to your needs.
If this is a public site, you may want to consider using named variables. This will allow you to define the group on the URL still, but without additional functionality requirements.
http://example.com/team/group:hr
http://example.com/team/action/group:hr/other:var
It may require custom routes too... but it should do the job.
http://book.cakephp.org/view/541/Named-parameters
http://book.cakephp.org/view/542/Defining-Routes
SESSIONS
Since web is stateless, you will need to use sessions (or cookies). The question you will need to ask yourself is how to reflect the selection (or not) of a specific department. It could be as simple as putting a drop down selection in the upper right that reflects ALL, HR, Sales, etc. When the drop down changes, it will set (or clear) the Group session variable.
As for the functionality in the controllers, you just check for the Session. If it is there, you limit the data by the select group. So you would use the same URLs, but the controller or model would manage how the data gets displayed.
// for all functionality use:
http://www.example.com/Team/action/id
http://www.example.com/Task/action/id
http://www.example.com/Equipment/action/id
You don't change the URL to accommodate for the functionality. That would be like using a different URL for every USER wanting to see their ADDRESS, PHONE NUMBER, or BILLING INFO. Where USER would be the group and ADDRESS, PHONE NUMBER< and BILLING INFO would be the item sets.
WITHOUT SESSIONS
The other option would be to put the Group filter on each page. So for example on Team/index view you would have a group drop down to filter the data. It would accomplish the same thing without having to set and clear session variables.
The conclusion is and the key thing to remember is that the functionality does not change nor does the URLs. The only thing that changes is that you will be working with filtered data sets.
Does that make sense?

Resources