I'm creating an event following/signup system that uses Django REST Framework and can't figure out how to properly set this up.
In my events model I have:
followers = models.ManyToManyField(get_user_model(), related_name='following')
Ideally, an authenticated user could use a POST or PATCH to add or remove themselves from the followers record for a given event. Though I'm not really sure what the best way to do that would be.
My current thinking would be to create a serializer that only exposes the followers field, then create an APIView using that serializer with login in the get and post/patch methods to add or remove the specific user.
I'm getting the feeling that this is over-complicating things though. Is there an easier way to do this?
What do you think about using a 'through' model for the M2M relation?
I mean:
class Follower(...:
user = FK user
event = FK event
...
followers = models.ManyToManyField(get_user_model(), through=Follower ...)
...
In this case you are able to create quickly a model serializer and a generic view for the model Follower. In order to add or remove a user to an event you just send POST or DELETE requests to this resource
Related
I was wondering what would be the best approach . I've been agonizing on what is the best way to accomplish a given task. It is a project with a react frontend and django rest framework backend. I am working on the backend with the django rest framework .
Task:
To query a user by their phonenumber which is stored as the username field.
To add a user to a profile model and add an extra field which is required by the profile model
To create the new profile with the user as the profiles user .
e.g
Profile Model:
User - ForeignKey
ExtraField - Charfield
My question is which of these solutions is better .
Should I build a url like this : domain/users/{phonenumber} and post the Extra field
and query the user like this.
def get_object(self):
return get_object_or_404(User,username=self.kwargs['phonenumber'])
user= get_object()
or
Should I post both the phonenumber and the extrafield and query the user from the backend like this.
user = get_object_or_404(User,username=request.data.get('phonenumber'))
both work but which would be the best practice if it even matters at all.
If you just starting a django project the best way would be to create a custom user model with only fields you need for your user.
See docs here.
I'm creating an API with Django Rest Framework (DRF) and wondering where I should handle object level authorization.
So far I've created an Organization model and a custom user model with email being the unique identifier instead of username. Organizations and users are currently connected through a many-to-many field.
What I'd like to do is make sure that when a user hits my API they're only able to do the standard CRUD actions on the models that are linked to the users respective organization. As an example here's my current UserViewSet where I've overriden then get_queryset method to filter the User queryset to only return other users who are apart of the same organizations as the user calling the API:
class UserViewSet(viewsets.ModelViewSet):
serializer_class = UserSerializer
def get_queryset(self):
User = get_user_model()
user = self.request.user
organizations = user.organization.all()
return User.objects.filter(organization__in=organizations)
What's considered best practice to extend these limitations to other viewset actions? For example, if I want to make sure that the user can only create and add other users into the organizations they're linked to, should I override the create method in the viewset and perform a validation there that the organization which was passed in the request data is the same as the organization that the user calling the API belongs to?
My gut feeling is that I'd end up breaking DRY this way, because I'd be overriding all the viewset actions and repeating nearly identical overrides. Is this intuition wrong? I guess I could separate the "validations" into a separate services.py file and call them in the overriden actions. Should I instead offload these checks to custom permissions? Or should I disregard the views completely and put the validation into the serializers?
Actually, you need different tools for different DRF CRUD actions. Personaly, I love to use rules package
name=XXX-list : /XXX/
list : permissions through get_queryset() filtering
create : permissions through rules and payload validation with serializer
name=XXX-detail : /XXX/{id}
retrieve : permissions through get_queryset() filtering
partial_update, update and destroy : permissions through rules and get_queryset() filtering
You will probably need to write a custom DjangoObjectPermission class to integrate rules
I have a quite complex Django model that is connected to my ReactJS frontend through a DRF API. Inside this model, many instances are ForeignKey or CharFields that include an array of options to be selected. Can you please tell me if there's a way I can have my React form to inherit the information of all the fields, instead of writing out the form manually?
I'd need the frontend form in React to "read" through the right API call and get all the fields from there. How can I achieve this?Thank you very much in advance!
you can achieve that by using RetrieveUpdateAPIView from DRF
class GetDateAndUpdate(RetrieveUpdateAPIView):
queryset = YOURMODEL.objects.all()
serializer_class = YOURMODELSerializer
permission_classes = [IsAuthenticated,IsOwner]
# in urls.py
url(r'^(?P<pk>[-\w]+)/update/$',
GetDateAndUpdate.as_view(),
name='update',
),
you can find more here
http://www.django-rest-framework.org/api-guide/generic-views/#retrieveupdateapiview
Lets say for example I have a Model called "Client" and a model called "PhoneNumbers"
class PhoneNumbers(models.Model):
number = forms.IntegerField()
class Client(models.Model):
number = forms.ManyToManyField(PhoneNumbers)
Client has a ManyToMany relationship with PhoneNumbers. PhoneNumbers has almost 500,000 records in it so when it comes to editing a Client record from a model form with a MultiSelect widget that comes with a M2M filed, it takes forever to load. In fact, it never does. It just sits there trying to load all of those phone objects I am assuming.
My workaround was to so some tedious things with ajax and jquery to edit only the phone numbers in a Client record. Before wasting my time with all of that I wanted to see if there is somehow another way to go about it without having my page hang.
You need to create a custom widget for this field that lets you autocomplete for the correct record. If you don't want to roll your own: http://django-autocomplete-light.readthedocs.io/
I've used this for its generic relationship support, the M2M autocomplete looks pretty easy and intuitive as well. see video of use here: http://www.youtube.com/watch?v=fJIHiqWKUXI&feature=youtu.be
After reading your comment about needing it outside the admin, I took another look at the django-autocomplete-light library. It provides widgets you can use outside the admin.
from dal import autocomplete
from django import forms
class PersonForm(forms.ModelForm):
class Meta:
widgets = {
'myformfield': autocomplete.ModelSelect2(
# ...
),
}
Since Django 2.0, Django Admin ships with an autocomplete_fields attribute that generates autocomplete widgets for foreign keys and many-to-many fields.
class PhoneNumbersAdmin(admin.ModelAdmin):
search_fields = ['number']
class ClientAdmin(admin.ModelAdmin):
autocomplete_fields = ['number']
Note that this only works in the scope of Django admin of course. To get autocomplete fields outside the admin you would need an extra package such as django-autocomplete-light as already suggested in other answers.
Out of the box, the model admin has a raw_id_fields option that let your page load much quicker. However, the user interface of raw id fields isn't very intuitive, so you might have to roll your own solution.
We use this 3rd party widget for this:
https://github.com/crucialfelix/django-ajax-selects
Btw, your 'example' above is really bad DB design for a bunch of reasons. You should just have the phone number as a text field on the Client model and then you would have none of these issues. ;-)
In Django, on a recommended setup, a UserProfile instance is linked by a OneToOneField with its User instance.
class UserProfile(models.Model):
user = models.OneToOneField(User)
data = ...
What is the most efficient way inside a view for retrieving both, user and profile?
Can I do a select_related() inner join query, to get both objects with one database hit? Or does it always come down to two separate calls? Possibly, Django's auth middleware retrieves the user instance even before the view is called ... does anybody know?
The user profile can be retrieved using get_profile().
See documentation: https://docs.djangoproject.com/en/dev/topics/auth/#storing-additional-information-about-users