Django query taking too much time - django

I'm using django and django rest framework to make a query from all users in data that have a permission sent as a url parameter but this query is taking too long.
I'm user pycharm debugger how can I try to check why is it taking to long, this is the function:
#list_route(url_path='permission/(?P<permission>.+)')
def read_permission(self, request, *args, **kwargs):
serializer = self.get_serializer_class()
qs = get_user_model().objects.filter_by_permission(self.kwargs.get('permission'))
qs = qs.order_by(Lower('username'))
return Response(serializer(qs, many=True).data)
Update
Adding the serializer
class UserSerializer(UserLabelMixin):
user_permissions = serializers.SlugRelatedField(many=True, read_only=True, slug_field='codename')
class Meta:
model = get_user_model()
fields = ['id', 'email', 'is_superuser', 'is_staff', 'label',
'full_name', 'first_name', 'last_name', 'username',
'teams', 'date_joined', 'last_login',
'user_permissions', 'groups', 'ui_preferences', 'internal_project',
'staff_id', 'oem_id', 'oem_email', 'oem_department', 'comment']
read_only_fields = fields

This may help you
get_user_model().objects.prefetch_related("user_permissions", "groups").filter_by_permission...

Related

Add additional field to response in pytest-django

I'm new to testing and I spent a day finding a solution for my problem but I couldn't find any.
this is my serializer
serilaizer.py
class LeadSerializer(serializers.ModelSerializer):
def create(self, validated_data):
user = self.context['user']
return Lead.objects.create(organizer=user.organizeruser, **validated_data)
class Meta:
model = Lead
fields = ['id', 'first_name', 'last_name', 'age', 'agent', 'category', 'description', 'date_added',
'phone_number', 'email', 'converted_date'
]
I have two types of users, organizer, and agent. organizer can create a lead but agent can't. and as you see I don't have organizer field. authenticated user will be added to the organizer field when a Lead is created.
test.py
def test_if_lead_exist_return_200(self, api_client, leads_factory, user_factory):
user = user_factory.create(is_organizer=True)
api_client.force_authenticate(user=User(is_staff=True))
lead = leads_factory.create()
serializer = LeadSerializer(context={'request': user})
print(serializer)
# here I can see the user
response = api_client.get(f'/api/leads/{lead.id}/', )
assert response.status_code == status.HTTP_200_OK
assert response.data == {
'id': lead.id,
'first_name': lead.first_name,
'last_name': lead.last_name,
'age': lead.age,
'organizer': lead.organizer.id,
'agent': lead.agent.id,
'category': lead.category.id,
'description': lead.description,
'date_added': lead.date_added,
'phone_number': lead.phone_number,
'email': lead.email,
'converted_date': lead.converted_date,
}
because there is no organizer field in the serialzier test won't pass and this is the result of the test
what can I do here? can I pass the organizer user to the response?
You should add the organizer into the fields.
class LeadSerializer(serializers.ModelSerializer):
class Meta:
model = Lead
# here I added the `organizer` field
fields = ['id', 'first_name', 'last_name', 'age', 'agent', 'category', 'description', 'date_added', 'phone_number', 'email', 'converted_date', 'organizer']
def create(self, validated_data):
...

Email field with unique constraint prevents PUT method of serializer from saving. django rest_framework

When creating an object in my api view it seems fine but whenever I update the object even I didn't change my email field it says user with this Email Address already exists. I am using generics.RetrieveUpdateView for my view.
I thought generics.RetrieveUpdateView automatically handles this. What am I missing?
my model looks like this:
class User(AbstractUser):
email= models.EmailField(unique=True)
...
my serializer looks like this:
class UserListForProfileSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['id', 'username','email','last_login', 'date_joined','is_active', 'is_student', 'is_staff', 'is_teacher', 'is_registrar', 'is_superuser']
read_only_fields = ('username','date_joined', 'last_login','is_active', 'is_student', 'is_staff', 'is_teacher', 'is_registrar', 'is_superuser')
class StaffProfileDetailSerializer(CreateProfileSerializer):
user = UserListForProfileSerializer(many= False)
class Meta:
model = StaffProfile
fields = ['user','first_name', 'middle_name', 'last_name', 'gender', 'employee_number', 'date_of_birth', 'mobile_number','dob_month','dob_day','dob_year','address',]
read_only_fields = ('date_joined', 'last_login',)
my view looks like this:
class UserProfileDetail(generics.RetrieveUpdateAPIView):
authentication_classes = [SessionAuthentication, BasicAuthentication]
permission_classes = [IsAuthenticated]
serializer_class = StaffProfileDetailSerializer
def get_queryset(self, *args, **kwargs):
userid = self.request.user.id
return StaffProfile.objects.filter(pk= userid)
urls.py:
urlpatterns = [
path('api/', apiOverview, name='apioverview'),
path('api/user/profile/detail/<int:pk>/', UserProfileDetail.as_view(),
name='userprofile-detail'),
...
]

Don't work cleaned_data in Django

This is my code:
class HighschoolForm(forms.ModelForm):
class Meta:
model = Highschool
fields = ['id', 'dni', 'name', 'address', 'city', 'country', 'phone', 'mobile', 'mail', 'website', 'contact', 'entrydate']
def clean_mail(self):
mail = self.cleaned_data.get('mail') #self.cleaned_data['mail']
mail_base, proveedor = mail.split('#')
dominio, extension = proveedor.split('.')
if extension == 'ptn':
raise forms.ValidationError('Does not allow Pluton mails....')
return self.cleaned_data['mail']
However when I introduced data in ModelForm in the admin view a mail with a "ptn" extension, Django doesn't refused the data and record in the database.
Which is the problem? I read de Django 2.0 documentation and I don't find the failure.
Thanks

tastypie check for missing fields in json

I am creating an api using tastypie. Code is as follows. I have inspected code using ipdb.
class UserProfileResource(ModelResource):
class Meta:
queryset = User.objects.all()
resource_name = 'userprofiles'
excludes = ['password', 'is_active', 'is_staff', 'is_superuser']
filtering = {
'username': ALL,
}
class UserResource(ModelResource):
user = fields.ForeignKey(UserProfileResource, 'user', full=True)
class Meta:
queryset = User.objects.all()
resource_name = 'users'
list_allowed_methods = ['get','post']
allowed_methods = ['get', 'put', 'patch', 'delete']
authentication = ApiKeyAuthentication()
serializer = Serializer(formats=['json', 'jsonp', 'xml', 'yaml', 'html', 'plist'])
def post_list(self, request, **kwargs):
print 'post list method'
mandatory_fields = ['username', 'email', 'first_name', 'last_name', 'address', 'city', 'pin']
fields_apicall = request.GET.keys()
#import ipdb;ipdb.set_trace();
print request.POST
if set(mandatory_fields).issubset(fields_apicall):
print request.GET.keys()
create_object = True
else:
print 'NO'
err_dict = { 'error':'Mandatory Fields Missing.' }
return HttpResponse(json.dumps(err_dict))
def obj_create(self, bundle, **kwargs):
print 'obj_create() '
mandatory_fields = ['username', 'email', 'first_name', 'last_name', 'address', 'city', 'pin']
fields_apicall = bundle.data.keys()
# import ipdb;ipdb.set_trace();
if set(mandatory_fields).issubset(fields_apicall):
bundle.obj = self._meta.object_class()
else:
err_dict = { 'error':'Mandatory Fields Missing.' }
return HttpResponse(json.dumps(err_dict))
I want to create nested user object, ie user object together with userprofile. For that I have to make sure all fields exists in the json. I tried overriding hydrate(),dehydrate(),and post_list() methods. Among these only post_list() get invoked on a post request.
I can check for fields in request json by overriding post_list() method but is this a good way to check for missing fields? I have googled and have gone through many SO posts but I didn't find any posts mentioning to override post_list() to check for missing fields some of them said to override hydrate(). Also is it necessary to override obj_create() method to create objects using tastypie?
obj_create() seems like the best place to do it. Something like this should work:
def obj_create(self, bundle, **kwargs):
mandatory_fields = ['username', 'email', 'first_name', 'last_name', 'address', 'city', 'pin']
for field_name, field_object in self.fields.items():
if field_name not in mandatory_fields:
err_dict = { 'error':'Mandatory Fields Missing.' }
return HttpResponse(json.dumps(err_dict))
super(SomeResource, self).obj_create(self, bundle, **kwargs)

Django: Make certain fields in a ModelForm required=False

How do I make certain fields in a ModelForm required=False?
If I have:
class ThatForm(ModelForm):
class Meta:
widgets = {"text": Textarea(required=False)}
Or if I have:
class ThatForm(ModelForm):
text = Textarea(required=False)
Django returns:
__init__() got an unexpected keyword argument 'required'
following from comments. Probably yes:
class ThatForm(ModelForm):
def __init__(self, *args, **kwargs):
# first call parent's constructor
super(ThatForm, self).__init__(*args, **kwargs)
# there's a `fields` property now
self.fields['desired_field_name'].required = False
you ought to add blank=True to the corresponding model
The documentation says
If the model field has blank=True, then required is set to False on the form field. Otherwise, required=True.
Also see the documentation for blank itself.
When we need to set required option on a bunch of fields we can:
class ThatForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for field in self.Meta.required:
self.fields[field].required = True
class Meta:
model = User
fields = (
'email',
'first_name',
'last_name',
'address',
'postcode',
'city',
'state',
'country',
'company',
'tax_id',
'website',
'service_notifications',
)
required = (
'email',
'first_name',
'last_name',
'address',
'postcode',
'city',
'country',
)
the following may be suitable
class ThatForm(ModelForm):
text = forms.CharField(required=False, widget=forms.Textarea)
You could try this:
class ThatForm(ModelForm):
class Meta:
requireds =
{
'text':False,
}
requireds must be under Meta.