I find message return in google, not find.
Whats my code not post values correct?
I need help for solution correct.
As use form based generic views?
Im desenv an restAPI, i not understanding problem in my code, i running and return:
I retrieve message, flow.
views.py :
from snippets.models import Equipamento, Colaborador
from snippets.serializers import EquipamentoSerializer, ColaboradorSerializer
from rest_framework import mixins
from rest_framework import generics
class EquipamentoList(generics.ListCreateAPIView):
serializer_class = EquipamentoSerializer
def get_queryset(self):
queryset = Equipamento.objects.all()
id = self.request.query_params.get('id', None)
if id is not None:
queryset = queryset.filter(id=id)
return queryset
# class ColaboradorList(generics.CreateAPIView):
# queryset = Colaborador.objects.all()
# serializer_class = ColaboradorSerializer
# def get_queryset(self):
# queryset = Colaborador.objects.all()
# id = self.request.query_params.get('id', None)
# if id is not None:
# queryset = queryset.filter(pk=pk)
# return queryset
# def create(self, request, pk):
# queryset = Colaborador.objects.all()
# return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
# class ColaboradorDetail(generics.RetrieveUpdateDestroyAPIView):
# queryset = Colaborador.objects.all()
# serializer_class = ColaboradorSerializer
class ColaboradorList(mixins.ListModelMixin,
mixins.CreateModelMixin,
generics.GenericAPIView):
queryset = Colaborador.objects.all()
serializer_class = ColaboradorSerializer
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
class ColaboradorDetail(mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
generics.GenericAPIView):
queryset = Colaborador.objects.all()
serializer_class = ColaboradorSerializer
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)
serializers.py
from rest_framework import serializers
from rest_framework.validators import UniqueValidator
from snippets.models import Equipamento, Colaborador, Propriedade, MotivoParada, Apontamento
class EquipamentoSerializer(serializers.Serializer):
id = serializers.IntegerField(read_only=True)
cod_equip = serializers.IntegerField(validators=[UniqueValidator(queryset=Equipamento.objects.all())])
desc_equip = serializers.CharField(allow_blank=True, max_length=15, required=False)
def restore_object(self, attrs, instance=None):
"""
Create or update a new snippet instance, given a dictionary
of deserialized field values.
Note that if we don't define this method, then deserializing
data will simply return a dictionary of items.
"""
if instance:
# Update existing instance
instance.id = attrs.get('id', instance.id)
instance.cod_equip = attrs.get('cod_equip', instance.cod_equip)
instance.des_equip = attrs.get('desc_equip', instance.desc_equip)
return instance
# Create new instance
return Equipamento(**attrs)
class ColaboradorSerializer(serializers.Serializer):
id = serializers.IntegerField(read_only=True)
cod_colab = serializers.IntegerField(validators=[UniqueValidator(queryset=Colaborador.objects.all())])
nome_colab = serializers.CharField(max_length=30)
def restore_object(self, attrs, instance=None):
"""
Create or update a new snippet instance, given a dictionary
of deserialized field values.
Note that if we don't define this method, then deserializing
data will simply return a dictionary of items.
"""
if instance:
# Update existing instance
instance.id = attrs.get('id', instance.id)
instance.cod_colab = attrs.get('cod_colab', instance.cod_colab)
instance.nome_colab = attrs.get('nome_colab', instance.nome_colab)
return instance
# Create new instance
return Colaborador(**attrs)
class ApontamentoSerializer(serializers.Serializer):
id = serializers.IntegerField(read_only=True)
criado = serializers.DateTimeField(read_only=True)
apont_inicio = serializers.TimeField()
apont_fim = serializers.TimeField()
duracao = serializers.TimeField()
equipamento = serializers.PrimaryKeyRelatedField(queryset=Equipamento.objects.all())
colaborador = serializers.PrimaryKeyRelatedField(queryset=Colaborador.objects.all())
propriedade = serializers.PrimaryKeyRelatedField(queryset=Propriedade.objects.all())
m_parada = serializers.PrimaryKeyRelatedField(queryset=MotivoParada.objects.all())
def restore_object(self, attrs, instance=None):
"""
Create or update a new snippet instance, given a dictionary
of deserialized field values.
Note that if we don't define this method, then deserializing
data will simply return a dictionary of items.
"""
if instance:
# Update existing instance
instance.id = attrs.get('id', instance.id)
instance.criado = attrs.get('criado', instance.criado)
instance.apont_inicio = attrs.get('apont_inicio', instance.apont_inicio)
instance.apont_fim = attrs.get('apont_fim', instance.apont_fim)
instance.duracao = attrs.get('duracao', instance.duracao)
instance.equipamento = attrs.get('equipamento', instance.equipamento)
instance.colaborador = attrs.get('colaborador', instance.colaborador)
instance.propriedade = attrs.get('propriedade', instance.propriedade)
instance.m_parada = attrs.get('m_parada', instance.m_parada)
return instance
# Create new instance
return Apontamento(**attrs)
class PropriedadeSerializer(serializers.Serializer):
id = serializers.IntegerField(read_only=True)
cod_prop = serializers.IntegerField(validators=[UniqueValidator(queryset=Propriedade.objects.all())])
desc_prop = serializers.CharField(max_length=30)
def restore_object(self, attrs, instance=None):
"""
Create or update a new snippet instance, given a dictionary
of deserialized field values.
Note that if we don't define this method, then deserializing
data will simply return a dictionary of items.
"""
if instance:
# Update existing instance
instance.id = attrs.get('id', instance.id)
instance.cod_prop = attrs.get('cod_prop', instance.cod_prop)
instance.des_prop = attrs.get('desc_prop', instance.desc_prop)
return instance
# Create new instance
return Propriedade(**attrs)
class MotivoParadaSerializer(serializers.Serializer):
id = serializers.IntegerField(read_only=True)
cod_mparada = serializers.IntegerField(validators=[UniqueValidator(queryset=MotivoParada.objects.all())])
desc_mparada = serializers.CharField(max_length=30)
def restore_object(self, attrs, instance=None):
"""
Create or update a new snippet instance, given a dictionary
of deserialized field values.
Note that if we don't define this method, then deserializing
data will simply return a dictionary of items.
"""
if instance:
# Update existing instance
instance.id = attrs.get('id', instance.id)
instance.cod_mparada = attrs.get('cod_mparada', instance.cod_mparada)
instance.des_mparada = attrs.get('desc_mparada', instance.desc_mparada)
return instance
# Create new instance
return MotivoParada(**attrs)
urls.py
from django.conf.urls import url
# from snippets.views import EquipamentoList, ColaboradorList, ColaboradorDetail
from snippets import views
from rest_framework.urlpatterns import format_suffix_patterns
urlpatterns = [
# url(r'^snippets/$', views.snippet_list),
# url(r'^snippets/(?P<pk>[0-9]+)/$', views.snippet_detail),
# url('^equipamento/(?P<id>.+)/$', EquipamentoList.as_view()),
#url('^colab/(?P<id>.+)/$', ColaboradorList.as_view()),
url('^colab/$', views.ColaboradorList.as_view()),
url('^colab_add/(?P<pk>[0-9]+)/$', views.ColaboradorDetail.as_view()),
]
urlpatterns = format_suffix_patterns(urlpatterns)I find message return in google, not find solv problem?
Help.
Whats my code not post values?
I need help for solution correct.
The error message is pretty straightforward. Your serializers use the restore_object method, which is deprecated in Rest Framework 3. Either downgrade your Django Rest Framework version to 2.x, or (recommended) rewrite your code to make it compatible with Rest Framework's latest version.
Related
I have this singal
#receiver(post_save, sender=Organization)
def save_tags(sender, instance, **kwargs):
from .views import post
text_input_tags = post.getlist('tags1')[0]
text_input_tags = text_input_tags.strip()
text_inputs_tags = text_input_tags.split(' ')
for tag in text_inputs_tags:
if not tag.startswith('#') :
tag = '#' + tag
tag_obj = Tag.objects.get_or_create(name = tag)[0]#.organization_set.set([obj,])
tag_obj.save()
instance.tags.add(tag_obj)
print(instance.tags.all())
from the views I am importing the post data to use inside the signal.
There is a manytomany relationship between two models Organization and Tag.
I am trying to get some attributes from the post request and create a Tag object from them, then after that add that Tag object into the ManyToMany relationship of the instance of the Organization.
when I print the tags of the organization instance
print(instance.tags.all())
I get the added instances in the QuerySet, but it's not saved in the organization instance and I don't understand why...
I tried to make that same functionality inside a method of UpdateView of the Organization, but it did the exact same thing and didn't work.
This is the UpdateView and its methods that doesn't work with this functionality
class OrganizationUpdate(UpdateView):
model = Organization
'''fields = [
'name',
'slug',
'bio',
'avatar_thumbnail',
'location',
'tags',
'contact_information'
]'
'''
form_class = forms.OrganizationForm
def get_object(self):
obj = Organization.objects.get(slug = self.kwargs.get('slug'))
if self.request.user not in obj.moderators.all() :
raise exceptions.PermissionDenied()
return obj
def save(self, *args, **kwargs):
org = self.get_object()
POST = self.request.POST.copy()
text_input_tags = POST.getlist('tags1')[0]
text_input_tags = text_input_tags.strip()
text_inputs_tags = text_input_tags.split(' ')
for tag in text_inputs_tags:
print(tag)
if not tag.startswith('#') :
tag = '#' + tag
tag_obj = Tag.objects.get_or_create(name = tag)[0]
tag_obj.save()
org.tags.add(tag_obj)
return super().save(*args, **kwargs)
def post(self, request, *args, **kwargs):
# same functionality in save()
return super().post(request, *args, **kwargs)
def form_valid(self, form):
# same functionality in save()
return super().form_valid(form)
Actually all I needed to do is to implement this functionality after all the saving of the instance has been done, so the post or form_valid methods don't apply here, I needed to implement it inside a method that happens in the last parts of the updateview, my choice was inside the get_success_url, the code looks like the following:
def get_success_url(self):
org = self.get_object()
POST = self.request.POST.copy()
text_input_tags = POST.getlist('tags1')[0]
text_input_tags = text_input_tags.strip()
text_inputs_tags = text_input_tags.split(' ')
for tag in text_inputs_tags:
print(tag)
if not tag.startswith('#') :
tag = '#' + tag
tag_obj = Tag.objects.get_or_create(name = tag)[0]
tag_obj.save()
org.tags.add(tag_obj)
return super().get_success_url()
serialize() method included in the django Tools_booked class but while trying to access that method it shows error.
'QuerySet' object has no attribute 'serialize'
models.py
from django.core.serializers import serialize
class UpdateQuerySet(models.QuerySet):
def serialize(self):
print("*****Entered the serizlize inside the UpdateQuerySet models **********")
qs = self
return serialize('json', qs, fields=('auto_increment_id','user','component','booked'))
class UpdateManager(models.Manager):
def get_queryset(self):
return UpdateQuerySet(self.model, using=self._db)
class Tools_booked(models.Model):
auto_increment_id = models.AutoField(primary_key=True)
user=models.ForeignKey(Profile, on_delete=models.CASCADE)
component = models.CharField(max_length=30, blank=True)
booked = models.DateTimeField(auto_now_add=True,blank=True)
objects = UpdateManager()
def __str__(self):
return self.component
def serialize(self):
json_data = serialize("json", [self], fields=['auto_increment_id','user','component','booked'])
stuct = json.loads(json_data)
print(struct)
data = json.dump(stuct[0]['fields'])
return data
views.py
class SerializedDetialView(View):
def get(self, request, *args, **kwargs):
print("*****Entered the SerializedDetialView **********")
obj_list= Tools_booked.objects.filter(auto_increment_id=1)
json_data = obj_list.serialize()
return HttpResponse(json_data, content_type='application/json')
class SerializedListView(View):
def get(self, request, *args, **kwargs):
json_data = Tools_booked.objects.all().serialize()
return HttpResponse(json_data, content_type='application/json')
The error traceback
json_data = Tools_booked.objects.all().serialize()
AttributeError: 'QuerySet' object has no attribute 'serialize'
But this works.
class SerializedDetialView(View):
def get(self, request, *args, **kwargs):
obj_list= Tools_booked.objects.filter(auto_increment_id=1)
json_data = serializers.serialize("json", obj_list )
return HttpResponse(json_data, content_type='application/json')
class SerializedListView(View):
def get(self, request, *args, **kwargs):
qs = Tools_booked.objects.all()
json_data = serializers.serialize("json", qs )
return HttpResponse(json_data, content_type='application/json')
How to use the serialize() method inside the models.py ,Tools_booked class.
You should either use Django-rest frameworks serializers with many=True or use values() function of Django queryset. There is no need to write a function in models. It will work like this
class YourSerializer(serializers.ModelSerializer):
class Meta:
model = "You Model Here"
fields = "write list of your model fields here or user __all__ for all fields"
you can serialize your query like this
queryset = Your_Model.objects.all()
serialized = YourSerializer(queryset, many=True).data
Other way to do so is like this
serialized = Your_Model.objects.all().values()
This method look simple but if you are writing rest apis, you should use serializers. You can look into details of serializer here.
Here is what's working for me:
from django.core.serializers import serialize
from django.db import models
class UpdateQuerySet(models.QuerySet):
def serialize(self):
print("*****Entered the serizlize inside the UpdateQuerySet models **********")
return serialize('json', self, fields=('component','booked'))
class UpdateManager(models.Manager):
# define here methods only needed inside this manager
pass
class Tools_booked(models.Model):
component = models.CharField(max_length=30, blank=True)
booked = models.DateTimeField(auto_now_add=True,blank=True)
objects = models.Manager()
serializer = UpdateManager.from_queryset(UpdateQuerySet)()
Now you can do in your views:
json_data = Tools_booked.serializer.serialize()
I guess you have an error because your serialize method is not defined inside the manager
In your models
class UpdateManager(models.Manager):
def get_queryset(self):
return UpdateQuerySet(self.model, self._db)
# Here for you to call to your views
def serialize(self):
return self.get_queryset().serialize()
In your views
json_data = Tools_booked.objects.all().serialize()
Django has changed a little bit.
Here is this document for Django update version.
Overview: need to generate a codename value for a hidden field in order to send it to an external API (1) and after that include the generated codename field in database (2).
Issue: How can I send the generated codename (HiddenField) to database?
models.py
class Category(Model):
name = models.CharField(max_length=45)
class Animal(Model):
name = models.CharField(max_length=45)
codename = models.CharField(max_length=45)
categories = models.ManyToManyField(Category)
serializers.py
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = models.Category
fields = '__all__'
class AnimalSerializer(serializers.ModelSerializer):
codename = serializers.HiddenField(default="auto_replace_me")
class Meta:
model = models.Animal
fields = '__all__'
views.py
class CategoryViewSet(ModelViewSet):
queryset = models.Category.objects.all()
serializer_class = serializers.CategorySerializer
class AnimalViewSet(ModelViewSet, CreateModelMixin):
queryset = models.Animal.objects.all()
serializer_class = serializers.AnimalSerializer
def create(self, request, *args, **kwargs):
codename = generate_codename()
# (1) external API request (with codename included on request) and returns a boolean `result`
if result:
# will call create method from parent class BUT
# (2) it needs to save the codename in database
return super(AnimalViewSet, self).create(request, *args, **kwargs)
else:
return HttpResponseServerError()
def generate_codename():
return ''.join([random.choice(string.ascii_letters) for n in range(10)])
Following code should do the job:
class AnimalViewSet(ModelViewSet, CreateModelMixin):
queryset = models.Animal.objects.all()
serializer_class = serializers.AnimalSerializer
def perform_create(serializer, codename):
serializer.save(codename=codename)
def create_with_codename(self, request, codename, *args, **kwargs):
# this is almost the same as CreateModelMixin 'create'
# but with one change: passing codename to 'perform_create' method
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
instance = self.perform_create(serializer, codename)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
def create(self, request, *args, **kwargs):
codename = generate_codename()
# (1) external API request (with codename included on request) and returns a boolean `result`
if result:
# will call create method from parent class BUT
# (2) it needs to save the codename in database
return self.create_with_codename(request, codename, *args, **kwargs)
else:
return HttpResponseServerError()
So basically, you should write your own function create_with_codename to change default behaviour of CreateModelMixin def create(self, request, *args, **kwargs)
Most important thing was to pass codename argument to perform_create. According to docs, everytime when you need to save serializer with appending additional values to it, you should use serializer.save(extra_field=extra_value)
After learn from you guys, I got this solution (only changing views.py):
views.py
class CategoryViewSet(ModelViewSet):
queryset = models.Category.objects.all()
serializer_class = serializers.CategorySerializer
class AnimalViewSet(ModelViewSet, CreateModelMixin):
queryset = models.Animal.objects.all()
serializer_class = serializers.AnimalSerializer
codename = None
def perform_create(self, serializer):
serializer.save(codename=self.codename)
def create(self, request, *args, **kwargs):
self.codename = generate_codename()
# (1) external API request (with codename included on request) and returns a boolean `result`
if result:
# will call create method from parent class BUT
# (2) it needs to save the codename in database
return super(AnimalViewSet, self).create(request, *args, **kwargs)
else:
return HttpResponseServerError()
def generate_codename():
return ''.join([random.choice(string.ascii_letters) for n in range(10)])
I would like to return to the User related record.
Somebody can help me?
part of my view
class UserProfileDetailView(DetailView):
model = get_user_model()
slug_field = "username"
template_name = "perfil.html"
def get_object(self, queryset=None):
user = super(UserProfileDetailView, self).get_object(queryset)
UserProfile.objects.get_or_create(user=user)
return user
Something like a old way>
def my_view(request, slug):
var = get_object_or_404(Model, slug=slug)
xxx = AnotherModel.objects.filter(var=var)
...
how can i perfome this in the first view UserProfileDetailView,
show related data?
What I do in this case is add the related object into the context data. It would be something like this:
class UserProfileDetailView(DetailView):
model = get_user_model()
slug_field = "username"
template_name = "perfil.html"
def get_context_data(self, **kwargs):
# xxx will be available in the template as the related objects
context = super(UserProfileDetailView, self).get_context_data(**kwargs)
context['xxx'] = AnotherModel.objects.filter(var=self.get_object())
return context
Another approach is to extend DetailView with MultipleObjectMixin, as in this example:
from django.views.generic import DetailView
from django.views.generic.list import MultipleObjectMixin
from django.contrib.auth import get_user_model
class DetailListView(MultipleObjectMixin, DetailView):
related_model_name = None
def get_queryset(self):
# a bit of safety checks
if not hasattr(self, "related_model_name"):
raise AttributeError(
"%s.related_model_name is missing." % (
self.__class__.__name,))
if not self.related_object_name:
raise NotImplementedError(
"%s.related_model_name must not be None." % (
self.__class__.__name,))
# get the object
obj = self.get_object()
# get the related model attached to the object
related_model = getattr(obj, "%s_set" % self.related_model_name, None)
# safety check if related model doesn't exist
if not related_model:
raise AttributeError(
"%s instance has no attribute \"%s_set\"" % (
obj.__class__.__name__, self.related_model_name)
# return the related model queryset
return related_model.all()
def get(self, request, *args, **kwargs):
self.object_list = self.get_queryset()
return super(DetailListView, self).get(request, *args, **kwargs)
class UserProfileDetailView(DetailListView):
template_name = "perfil.html"
model = get_user_model()
slug_field = "username"
related_model_name = "anothermodel"
def get_object(self, queryset=None):
user = super(UserProfileDetailView, self).get_object(queryset)
UserProfile.objects.get_or_create(user=user)
return user
In my opinion this approach is a little less cleaner and understandable, but it has a huge advantage in reusability. It definitely has one downside: if you are using the class variable context_object_name, it will refer to the related objects list and not to the object itself (this has to do with how the inheritance chain is set up when constructing the class).
I have a model like so:
class GiveAbsolute(serializers.Field):
def to_native(self,value):
# this where it give an error (self doesn't have request)
# what i want it to give full url
# like: http://www.blabla.com/othermodel/1
return reverse('link_to_othermodel',
args=[value],
request=self.request)
class SomethingSerializer(serializers.ModelSerializer):
# field with foreign key
othermodel = GiveAbsolute(source="othermodel.id")
class Meta:
model=Something
fields("fields1","othermodel")
is there a way to achieve this ?
thanks
From the source
The request object is an entry of the context dictionary. ie.
request = self.context.get('request')
In your case, just do:
self.request = self.context.get('request')
then build the url
self.request.build_absolute_uri(reverse('some_url_name'))
Based on the answer of mariodev, here is a reusable solution for Models ; I use it to provide URLs to service (see them as metheds) on django models.
Reusable components
serializers.py
class RequestAwareSerializer(serializers.ModelSerializer):
"""
A serializer which fields can access the request object.
"""
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
super(RequestAwareSerializer, self).__init__(*args, **kwargs)
class APIMethodField(serializers.Field):
""" To get the absolute URL of a method accessible via the API
"""
def __init__(self, url_action_name, *args, **kwargs):
self._url_name = url_action_name
super(APIMethodField, self).__init__(source='*', *args, **kwargs)
def to_native(self, obj):
"""
#param objid the ID of the object
#param method_url_name, the name of the url, as in urls.py
"""
return reverse_lazy(self._url_name, args=[obj.id],
request=self.parent.request)
views.py
class ChattyModelViewSet(ModelViewSet):
""" ModelViewSet which informs the serializer about the request
(abstract)
"""
def get_serializer(self, instance=None, data=None,
files=None, many=False, partial=False):
serializer_class = self.get_serializer_class()
context = self.get_serializer_context()
return serializer_class(instance, data=data, files=files, many=many,
partial=partial, context=context,
request=self.request)
Example use
urls.py
url(r'^v1/maildomain/(?P<maildomain_id>\d+)/check/$',
views.MailDomainDetail.as_view(), name='maildomain_dns_check')
serializers.py
class MailDomainSerializer(RequestAwareSerializer):
checkdns_url = APIMethodField(url_action_name='maildomain_dns_check')
class Meta:
model = MailDomain()
fields = ('name', 'checkdns_url')
views.py
class MailDomainView(ChattyModelViewSet):
model = MailDomain
serializer_class = MailDomainSerializer
The only thing in DRF, that has an access to request object is the view, so you need to figure out how to pass your request from view to serializer, for example in generic ListView you can use get_serializer.
Then, when you already have it in your serializer, you can use self.parent (which is a parent serializer) to capture it from the field itself:
class GiveAbsolute(serializers.Field):
def to_native(self,value):
return reverse('link_to_othermodel',
args=[value],
request=self.parent.request)
class SomethingSerializer(serializers.ModelSerializer):
# field with foreign key
othermodel = GiveAbsolute(source="othermodel.id")
class Meta:
model=Something
fields=("fields1","othermodel")
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
super(SomethingSerializer, self).__init__(*args, **kwargs)
class SomethingView(generics.ListAPIView):
model = Something
serializer_class = SomethingSerializer
def get_serializer(self, instance=None, data=None,
files=None, many=False, partial=False):
serializer_class = self.get_serializer_class()
context = self.get_serializer_context()
return serializer_class(instance, data=data, files=files, many=many,
partial=partial, context=context, request=self.request)