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
Related
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):
...
I have HCL AppScan CodeSweep installed on VScode and it picked up an SSL context vulnerability on one of my Django serializers and I was just wondering I can go about fixing it without changing my desired functionality.
class CategoryDetailSerializer(CategoryListSerializer):
products = serializers.SerializerMethodField()
class Meta:
model = Category
fields = (
'id',
'title',
'products',
)
def get_products(self, obj):
# The source of the SSL context override
return ProductListSerializer(obj.product_set.all(), many=True, context=self.context).data
class ProductListSerializer(serializers.HyperlinkedModelSerializer):
url = serializers.HyperlinkedIdentityField(
view_name='products:product-detail-view', lookup_field='slug')
class Meta:
model = Product
fields = (
'id',
'slug',
'title',
'price',
'image',
'url',
)
I'm currently doing the tutorial on Relationships and hyperlinked API's. However I've come across a strange problem that I can't seem to fix. My serializers.HyperlinkedIdentityField and serializers.HyperlinkedRelatedField doesnt seem to detect the namespace I'm using.
My serializers look like this
class SnippetSerializer(serializers.HyperlinkedModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username')
highlight = serializers.HyperlinkedIdentityField(view_name='snippets:snippet-highlight', format='html')
class Meta:
model = Snippet
fields = ('url', 'id', 'highlight', 'owner', 'title', 'code', 'linenos', 'language', 'style')
class UserSerializer(serializers.HyperlinkedModelSerializer):
snippets = serializers.HyperlinkedRelatedField(many=True, view_name='snippets:snippet-detail', read_only=True)
class Meta:
model = User
fields = ('url', 'id', 'username', 'snippets')
Which is pretty much the same as the tutorial except I am adding view_name='snippets:snippet-detail' in the serializer field.
I am creating my namespace as suggested by the Django documentation, by adding app_name = 'snippets' above my urlpatterns.
This is the error I'm getting
ImproperlyConfigured at /snippets/
Could not resolve URL for hyperlinked relationship using view name
"snippet-detail". You may have failed to include the related model in
your API, or incorrectly configured the lookup_field attribute on
this field.
As you see, I have approached the problem the same way other people have but without resolving the issue. Anyone have an idea about what I could try next?
Solved the problem after reading some more about Hyperlinks and noticing that I should add extra_kwargs for the url field SnippetSerializer
class Meta:
model = Snippet
fields = ('url', 'id', 'highlight', 'owner', 'title', 'code', 'linenos', 'language', 'style')
extra_kwargs = {
'url': {'view_name': 'snippets:snippet-detail'},
}
And UserSerializer
class Meta:
model = User
fields = ('url', 'id', 'username', 'snippets')
extra_kwargs = {
'url': {'view_name': 'snippets:user-detail'},
}
fix this issue by modify serializer.py
we can define url, such as:
url = serializers.HyperlinkedIdentityField(view_name='snippets:user-detail', lookup_field='pk')
or define in Meta, such as
extra_kwargs = {
'url': {'view_name': 'snippet:user-detail', 'lookup_field': 'pk'},
}
all serializer.py code:
from rest_framework import serializers
from snippets.models import Snippet
from django.contrib.auth.models import User
class SnippetSerializer(serializers.HyperlinkedModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username')
highlight = serializers.HyperlinkedIdentityField(lookup_field="pk", view_name='snippets:snippet-highlight', format='html')
class Meta:
model = Snippet
fields = ('url', 'id', 'highlight', 'owner', 'title', 'code', 'linenos', 'language', 'style')
extra_kwargs = {
'url': {'view_name': 'snippets:snippet-detail', 'lookup_field': 'pk'},
}
class UserSerializer(serializers.HyperlinkedModelSerializer):
snippets = serializers.HyperlinkedRelatedField(lookup_field="pk", many=True, view_name='snippets:snippet-detail', read_only=True)
url = serializers.HyperlinkedIdentityField(view_name='snippets:user-detail', lookup_field='pk')
class Meta:
model = User
fields = ('url', 'id', 'username', 'snippets')
# extra_kwargs = {
# 'url': {'view_name': 'snippet:user-detail', 'lookup_field': 'pk'},
# }
Try to pass lookup_field and lookup_url_kwarg arguments.
snippets = serializers.HyperlinkedRelatedField(many=True, view_name='snippets:snippet-detail',
lookup_field="",
lookup_url_kwarg="", read_only=True)
Refer HyperlinkedRelatedFieldDoc
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...
I have my User saved in two different models, UserProfile and User. Now from API perspective, nobody really cares that these two are different.
So here I have:
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ('url', 'username', 'first_name', 'last_name', 'email')
and
class UserPSerializer(serializers.HyperlinkedModelSerializer):
full_name = Field(source='full_name')
class Meta:
model = UserProfile
fields = ('url', 'mobile', 'user','favourite_locations')
So in UserPSerializer the field user is just a link to that resource. But form a User perspective there is really no reason for him to know about User at all.
Is there some tricks with which I can just mash them together and present them to the user as one model or do I have to do this manually somehow.
You can POST and PUT with #kahlo's approach if you also override the create and update methods on your serializer.
Given a profile model like this:
class Profile(models.Model):
user = models.OneToOneField(User)
avatar_url = models.URLField(default='', blank=True) # e.g.
Here's a user serializer that both reads and writes the additional profile field(s):
class UserSerializer(serializers.HyperlinkedModelSerializer):
# A field from the user's profile:
avatar_url = serializers.URLField(source='profile.avatar_url', allow_blank=True)
class Meta:
model = User
fields = ('url', 'username', 'avatar_url')
def create(self, validated_data):
profile_data = validated_data.pop('profile', None)
user = super(UserSerializer, self).create(validated_data)
self.update_or_create_profile(user, profile_data)
return user
def update(self, instance, validated_data):
profile_data = validated_data.pop('profile', None)
self.update_or_create_profile(instance, profile_data)
return super(UserSerializer, self).update(instance, validated_data)
def update_or_create_profile(self, user, profile_data):
# This always creates a Profile if the User is missing one;
# change the logic here if that's not right for your app
Profile.objects.update_or_create(user=user, defaults=profile_data)
The resulting API presents a flat user resource, as desired:
GET /users/5/
{
"url": "http://localhost:9090/users/5/",
"username": "test",
"avatar_url": "http://example.com/avatar.jpg"
}
and you can include the profile's avatar_url field in both POST and PUT requests. (And DELETE on the user resource will also delete its Profile model, though that's just Django's normal delete cascade.)
The logic here will always create a Profile model for the User if it's missing (on any update). With users and profiles, that's probably what you want. For other relationships it may not be, and you'll need to change the update-or-create logic. (Which is why DRF doesn't automatically write through a nested relationship for you.)
I just came across this; I have yet to find a good solution particularly for writing back to my User and UserProfile models. I am currently flattening my serializers manually using the SerializerMethodField, which is hugely irritating, but it works:
class UserSerializer(serializers.HyperlinkedModelSerializer):
mobile = serializers.SerializerMethodField('get_mobile')
favourite_locations = serializers.SerializerMethodField('get_favourite_locations')
class Meta:
model = User
fields = ('url', 'username', 'first_name', 'last_name', 'email', 'mobile', 'favourite_locations')
def get_mobile(self, obj):
return obj.get_profile().mobile
def get_favourite_locations(self, obj):
return obj.get_profile().favourite_locations
This is horribly manual, but you do end up with:
{
"url": "http://example.com/api/users/1",
"username": "jondoe",
"first_name": "Jon",
"last_name": "Doe",
"email": "jdoe#example.com",
"mobile": "701-680-3095",
"favourite_locations": [
"Paris",
"London",
"Tokyo"
]
}
Which, I guess is what you're looking for.
I would implement the modifications on the UserPSerializer as the fields are not going to grow:
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ('url', 'username', 'first_name', 'last_name', 'email')
class UserPSerializer(serializers.HyperlinkedModelSerializer):
url = serializers.CharField(source='user.url')
username = serializers.CharField(source='user.username')
first_name = serializers.CharField(source='user.first_name')
last_name = serializers.CharField(source='user.last_name')
email = serializers.CharField(source='user.email')
class Meta:
model = UserProfile
fields = ('mobile', 'favourite_locations',
'url', 'username', 'first_name', 'last_name', 'email')