field name choice 'reference' is not a valid choice issue - python

I am trying to create a view set in which i want to filter all of the records that have the same reference number. there is a reference model field in the Member model, but it is telling me that it is an invalid field.
this is the viewset:
from groups.models import Member
from ..serializers import MemberSerializer
from rest_framework import viewsets
class MemberViewSet(viewsets.ModelViewSet):
queryset = Member.objects.filter(field_name='reference')
serializer_class = MemberSerializer
this is the models:
class Member(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE)
reference = models.CharField(max_length=22)
balance = models.DecimalField(max_digits=12, decimal_places=2)
open_tabs = models.IntegerField()
created = models.DateTimeField(auto_now_add=True)
this is the urls:
from groups.api.views.memberViews import MemberViewSet
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r'', MemberViewSet, base_name='member')
urlpatterns = router.urls
so i want to filter out all of the member objects with the same reference field value...

If you want Members that have a specific reference in your viewset, you should override the get_queryset method and add the parameter to the url.
in the viewset :
from groups.models import Member
from ..serializers import MemberSerializer
from rest_framework import viewsets
class MemberViewSet(viewsets.ModelViewSet):
serializer_class = MemberSerializer
def get_queryset(self):
reference = self.kwargs['reference']
return Member.objects.filter(reference=reference)
and in urls :
from groups.api.views.memberViews import MemberViewSet
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r'(?P<reference>[-\w]+)', MemberViewSet, base_name='member')
urlpatterns = router.urls
see the drf guide to filtering

Referring to QuerySet
Can you try using the following approach where 'SearchKey' is the reference number you want to query against?
queryset = Member.objects.filter(reference__contains='SearchKey')

Related

Could not resolve URL for hyperlinked relationship using view name "rest:campaign-detail"

A newbie here in the world of Django. I am struggling with creating a hyperlink for a nested route.
The error I am getting is:
Could not resolve URL for hyperlinked relationship using view name "rest:campaign-detail". You may have failed to include the related model in your API, or incorrectly configured the `lookup_field` attribute on this field.
Some project setup notes
Using django rest framework
using DRF-extensions to create the routes
Using ModelViewSet
Expected end points:
/accounts/
/accounts/< pk >/
/accounts/< pk >/campaigns/
/accounts/< pk >/campaigns/< pk >/
/accounts/< pk >/campaigns/adgroup/
/accounts/< pk >/campaigns/adgroup/< pk >/
Set a namespace of rest in urls.py
Using HyperlinkedIdentityField to create the hyperlink. It only works with the parent object i.e.
url = serializers.HyperlinkedIdentityField(view_name='rest:account-detail')
However fails with any nested object i.e.
url = serializers.HyperlinkedIdentityField(view_name='rest:campaign-detail')
The model is quiet simple, an Account can have many Campaigns, and a campaign can have many AdGroups. See code below:
models.py
from django.db import models
from django.db.models import Q
from model_utils import Choices
ORDER_COLUMN_CHOICES = Choices(
('0', 'id'),
('1', 'keyword'),
('2', 'status'),
('3', 'match_type'),
)
# Account
class Account(models.Model):
account_name = models.CharField(max_length=128)
def __str__(self):
return self.account_name
# Campaign
class Campaign(models.Model):
class Status(models.TextChoices):
Enabled = "Enabled"
Paused = "Paused"
account = models.ForeignKey(
to=Account, on_delete=models.CASCADE, related_name='campaigns'
)
campaign_name = models.CharField(max_length=128)
status = models.CharField(max_length=21, choices=Status.choices, default=Status.Paused)
def __str__(self):
return self.campaign_name
# AdGroup
class AdGroup(models.Model):
class Status(models.TextChoices):
Enabled = "Enabled"
Paused = "Paused"
campaign = models.ForeignKey(
to=Campaign, on_delete=models.CASCADE, related_name='adgroups'
)
adgroup_name = models.CharField(max_length=128)
status = models.CharField(max_length=21, choices=Status.choices, default=Status.Enabled)
def __str__(self):
return self.adgroup_name
views.py
from rest_framework import viewsets
from .serializers import *
from . import models
from rest_framework_extensions.mixins import NestedViewSetMixin
class AccountViewSet(NestedViewSetMixin, viewsets.ModelViewSet):
serializer_class = AccountSerializer
queryset = models.Account.objects.all()
class CampaignViewSet(NestedViewSetMixin, viewsets.ModelViewSet):
serializer_class = CampaignSerializer
queryset = models.Campaign.objects.all()
class AdGroupViewSet(NestedViewSetMixin, viewsets.ModelViewSet):
serializer_class = AdGroupSerializer
queryset = models.AdGroup.objects.all()
serializers.py
from rest_framework import serializers
from . import models
class CampaignSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name="rest:campaign-detail")
class Meta:
model = models.Campaign
fields = '__all__'
class AccountSerializer(serializers.HyperlinkedModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='rest:account-detail')
class Meta:
model = models.Account
fields = '__all__'
class AdGroupSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='rest:adgroup-detail')
class Meta:
model = models.AdGroup
fields = '__all__'
I have 2 URL files. The project is named Vanilla and an app named rest where the DRF logic sits.
Vanilla urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('', include('rest.urls', namespace='rest')),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework')),
path('admin/', admin.site.urls)
]
Rest urls.py
from django.urls import include, path
from . import views
from rest_framework_extensions.routers import ExtendedSimpleRouter
app_name = 'rest'
router = ExtendedSimpleRouter()
(
router.register(r'accounts',
views.AccountViewSet,
basename='account')
.register(r'campaigns',
views.CampaignViewSet,
basename='campaign',
parents_query_lookups=['account__id'])
.register(r'adgroups',
views.AdGroupViewSet,
basename='adgroup',
parents_query_lookups=['campaign__account', 'campaign'])
Thank You!
use hyperlinkedModelSerializer in all of your related serializer. that should work

Multiple view set into router Django rest framework

I have a problem with DRF
I have a model
from django.contrib.sites.models import Site
class Person(models.Model):
site = ForeignKey(Site, on_delete=models.CASCADE)
I want to create a viewset and serializer and I want to get the specific url:
/api/sites/{pk}/persons/
And get all persons that They have associate site
Or
/api/sites/{pk}/persons/{pk}
How can I do?
Try this
# serializers.py
from rest_framework import serializers
class PersonSerializer(serializers.ModelSerializer):
class Meta:
fields = '__all__'
model = Person
# views.py
from rest_framework.viewsets import ModelViewSet
class PersonViewset(ModelViewSet):
serializer_class = PersonSerializer
def get_queryset(self):
return Person.objects.filter(site_id=int(self.kwargs['site_id']))
router config will be as
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r'/api/sites/<site_id>/persons', views.PersonViewset)

Improperly configured django error

I have a simple django project and whenever i run it, it gives me an improperly configured error. Tells me my model is missing a query set:
Improperly Configured Error Image
Here's the code for my views.py. The functionality doesn't matter for now:
import random
from django.shortcuts import render
from django.http import HttpResponse
from django.views import View
from django.views.generic import TemplateView
from django.views.generic.list import ListView
class RestaurantList(ListView):
querySet = Restaurant.objects.all()
template_name = 'restaurants/restaurants_list.html'
class SpicyList(ListView):
template_name = 'restaurants/restaurants_list.html'
querySet = Restaurant.objects.filter(category__iexact='spicy')
class AsianList(ListView):
template_name = 'restaurants/restaurants_list.html'
querySet = Restaurant.objects.filter(category__iexact='asian')
Here's the code for my models.py
from django.db import models
class Restaurant(models.Model):
name = models.CharField(max_length=120)
loocation = models.CharField(max_length=120, null=True, blank=True)
category = models.CharField(max_length=120, null=True, blank=False)
timestamp = models.DateTimeField(auto_now=True)
updated = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
urls.py code:
from django.contrib import admin
from django.conf.urls import url
from django.views.generic import TemplateView
from restaurant.views import *
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', TemplateView.as_view(template_name='home.html')),
url(r'^restaurants/$', RestaurantList.as_view()),
url(r'^restaurants/asian/$', AsianList.as_view()),
url(r'^restaurants/spicy/$', SpicyList.as_view()),
url(r'^Contact/$', TemplateView.as_view(template_name='Contact.html')),
url(r'^About/$', TemplateView.as_view(template_name='About.html'))
]
It's only the urls containing 'restaurants' that give me this error. The rest are fine.
Here's a picture of my file structure at the side
File Structure
The queryset attribute should be lower case at all.
all your views contain querySet
replace them by queryset lower case
Or you can provide the model attribute model = ModelName
See more In the Official Documentation

Django REST Framework - Filtering against the URL

I am using the Django REST Framework toolkit with Django 1.11 and I am trying to filter the results against the url. Here is my setup:
models.py:
from django.db import models
class Package(models.Model):
name = models.CharField(max_length=255, unique=True)
def __str__(self):
return self.name
serializers.py:
from rest_framework import serializers
from .models import Package
class PackageSerializer(serializers.ModelSerializer):
class Meta:
model = Package
fields = ('name',)
views.py:
from rest_framework import viewsets
from .models import Package
from .serializers import PackageSerializer
class PackageViewSet(viewsets.ReadOnlyModelViewSet):
serializer_class = PackageSerializer
queryset = Package.objects.all()
urls.py
from django.conf.urls import url, include
from django.contrib import admin
from rest_framework import routers
router = routers.DefaultRouter()
router.register(r'package', views.PackageViewSet)
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api/v1/', include(router.urls)),
]
Currently when I use this I can filter the results by the id field:
http://127.0.0.1:8000/api/v1/package/1/
I am hoping to filter the results by the name field of my package model instead by using this:
http://127.0.0.1:8000/api/v1/package/basic/
How would I be able to accomplish this?
Set the lookup_field attribute in the viewset, see the documentation.
class PackageViewSet(viewsets.ReadOnlyModelViewSet):
serializer_class = PackageSerializer
queryset = Package.objects.all()
lookup_field = 'name'
Use filter_fields in views.
filter_fields = ('name',)
lookup field is used to set lookup by default it would be model pk
if you wish to make your URL,
my_url/filter_field/
set lookup_field = "name"
if you want search from URL like ,
my_url/?name=something
you need to set filter_fields in views.

How to deal with URL arguments in Django REST Frameworks

I am new to Django REST Frameworks and despite doing the tutorial twice and reading lots of documentation I can't work out exactly how to handle/access the arguments in a URL in the DRF ViewSet.
My URL looks like this:
/api/v1/user/<user-id>/<age>/update
In my base urls.py I have the urlpattern:
url(r'^api/v1/', include('api.urls'))
In the api/urls.py I have:
from django.conf.urls import url, include
from rest_framework import routers
from api import views
router = routers.DefaultRouter()
router.register(r'user', views.UserViewSet)
urlpatterns = [
url(r'^', include(router.urls))
]
My question is what should my UserViewSet look like to handle the url, extract the user id and age fields, and update the UserDetails model so the given user has the given age?
My model hasn't been created yet but will look something like this:
class UserDetails(models.Model):
user = models.ForeignKey(User)
age = models.BigIntegerField(blank=True, null=True)
In the serializers.py adde the ParameterisedHyperlinkedIdentityField as a serializer.
serializers.py
class UserSerializer(serializers.HyperlinkedModelSerializer):
url = ParameterisedHyperlinkedIdentityField(view_name='user-detail', lookup_fields=(('id', 'id'), ('age', 'age')), read_only=True)
class Meta:
model = UserDetails
urls.py
from .viewsets import UserViewSet
user_list = UserViewSet.as_view({'get':'list'})
user_detail = UserViewSet.as_view({'get':'retrieve'})
urlpatterns= [
url(r'^user/(?P<id>\d+)/(?P<age>[-\w\d]+)/update/$', user_detail, name='user-detail')
]
viewsets.py
class UserViewset(viewsets.ModelViewSet):
lookup_field = 'id'
serializer_class = UserSerializer
queryset = UserDetails.objects.all()

Categories