I have a django project that I am working on. There are two models in this project. There is a user
and account
model. I am integreating the django rest framework viewsets. I will include them below. I am now integrating the Django Rest Framework in the project. I am trying to digure out how to do two things.
2 models:
Default django user
Account Model:
class Account(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
_id = models.CharField(max_length=45)
name = models.CharField(max_length=140)
balance = models.DecimalField(max_digits=100, decimal_places=2)
currency = models.CharField(max_length=12)
bank_name = models.CharField(max_length=120)
routing = models.CharField(max_length=8)
_class = models.CharField(max_length=22)
type = models.CharField(max_length=22)
active = models.BooleanField(default=True)
main = models.BooleanField(default=False)
synapse = models.BooleanField(default=False)
create_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.user.username + ' - ' + self.name + ': ' + str(self.balance)
1 => I want to be able to type in the endpoint /api/users/accounts/omarjandlai
and grab the single or many acounts with the omarjandali user foreignkey
2 => I want to be able to type into the following
api/users/accounts/
and return all of the accounts that are in the database
I tried 4 - 5 different ways to get this to work and I couldnt get it to work.
Here are my serializers and views
serializers:
class AccountSerializer(serializers.ModelSerializer):
class Meta:
model = Account
fields = ('user', '_id', 'name', 'balance', 'currency', 'bank_name',
'routing', '_class', 'type', 'active', 'main', 'synapse')
Views:
class AccountViewSet(viewsets.ModelViewSet):
queryset = Account.objects.all();
serializer_class = AccountSerializer
filter_backends = (filters.DjangoFilterBackend,)
filter_fields = ('user',)
what is happening is that when I do the
api/users/account
i see all the accounts
api/users/account/omarjandali
I get detail not found
urls:
router = DefaultRouter()
router.register(r'users', UserViewSet, basename='user')
router.register(r'accounts', AccountViewSet, basename='account')
urlpatterns = router.urls
I can see that you are using DefaultRouter´s default functionality. That way you only can access records detail by using theirs primary key. Since you didn't specify any field as primary key explicitly (primary=True
), Django sets field id, which is PositiveIntegerField
as the primary key of the model. So, if you want to access the detail of a record you must use api/users/account/112/
.
You can access records by name using filters: api/users/account/?search='omarjandali'
, but you need to add SearchFilter
.
from rest_framework.filters import SearchFilter
class AccountViewSet(viewsets.ModelViewSet):
queryset = Account.objects.all();
serializer_class = AccountSerializer
filter_backends = (filters.DjangoFilterBackend, SearchFilter)
filter_fields = ('user',)
search_fields = ('name',)
If you want to stick to the url pattern api/users/account/omarjandali/
, you have to add it to urls.py and use another viewset in order to let the original one to function accordingly to DefaultRouter definition:
urls.py:
router = DefaultRouter()
router.register(r'users', UserViewSet, basename='user')
router.register(r'accounts', AccountViewSet, basename='account')
urlpatterns = [
path('', include(router.urls)),
path('api/users/account/<str:username>/', views.GetRecordsByNameViewSet.as_view({'get': 'list'}),
]
views.py
from rest_framework.response import Response
class GetRecordsByNameViewSet(viewsets.ViewSet):
def list(self, request, username):
accounts = Account.objects.filter(user__username=username)
accounts_to_return = AccountSerializer(accounts, many=True).data
return Response(accounts_to_return)