I'm working on my Django web application and I'm beginning API part.
I have a Create Serializer class like this :
class IndividuCreateSerializer(serializers.ModelSerializer) :
class Meta :
model = Individu
fields = [
'Etat',
'Civilite',
'Nom',
'Prenom',
'Sexe',
'Statut',
'DateNaissance',
'VilleNaissance',
'PaysNaissance',
'Nationalite1',
'Nationalite2',
'Profession',
'Adresse',
'Ville',
'Zip',
'Pays',
'Mail',
'Telephone',
'Image',
'CarteIdentite',
]
def create(self, validated_data):
obj = Individu.objects.create(**validated_data)
IdentityIndividuResumeView.get_context_data(obj.id)
return obj
In this class, I have my create function which should redirect to IdentityIndividuResumeView class when my person is created.
class IdentityIndividuResumeView(LoginRequiredMixin, TemplateView) :
template_name = 'Identity_Individu_Resume.html'
model = Individu
def get_context_data(self, **kwargs) :
context_data = super(IdentityIndividuResumeView, self).get_context_data(**kwargs)
id = self.kwargs['id']
personne = get_object_or_404(Individu, pk=id)
NIU = lib.Individu_Recherche.NIUGeneratorIndividu(personne)
personne.NumeroIdentification = NIU
...
But I don't overcome to pass argument in my function get_context_data. I'm getting this issue :
File "/Users/valentin/Desktop/Identity/api/serializers.py" in create
80. IdentityIndividuResumeView.get_context_data(obj.id)
File "/Users/valentin/Desktop/Identity/views.py" in get_context_data
228. context_data = super(IdentityIndividuResumeView, self).get_context_data(**kwargs)
Exception Type: TypeError at /Api/Identification/create/
Exception Value: super(type, obj): obj must be an instance or subtype of type
EDIT :
It works with FBV model, but I would like to convert this to CBV :
#login_required
def Identity_Individu_Resume(request, id) :
personne = get_object_or_404(Individu, pk=id)
NIU = lib.Individu_Recherche.NIUGeneratorIndividu(personne)
personne.NumeroIdentification = NIU
...
and serializers.py file :
def create(self, validated_data):
obj = Individu.objects.create(**validated_data)
Identity_Individu_Resume(self.context.get('request'), obj.id)
return obj
The create function of the serializer is calling using the class object IdentityIndividuResumeView.get_context_data(obj.id) and not the instance of the class. While in the function based view, you are passing all the required arguments. That's why it is working for it.
Check for your self object at /Users/valentin/Desktop/Identity/views.py line 228 self object is wrong.
I mean Content in the self object is of not proper type.
Related
In the following code, I don't understand something about the object.
class SingleObjectMixin(ContextMixin):
"""
Provide the ability to retrieve a single object for further manipulation.
"""
model = None
queryset = None
slug_field = 'slug'
context_object_name = None
slug_url_kwarg = 'slug'
pk_url_kwarg = 'pk'
query_pk_and_slug = False
...
...
def get_context_data(self, **kwargs):
"""Insert the single object into the context dict."""
context = {}
if self.object:
context['object'] = self.object
context_object_name = self.get_context_object_name(self.object)
if context_object_name:
context[context_object_name] = self.object
context.update(kwargs)
return super().get_context_data(**context)
There is an attribute self.object'in the method get_context_data. I would like to figure out where the attribute `object' is created from.
SingleObjectMixin is a mixin normally used by views. E.g. BaseDetailView uses this mixin where its method get sets the object:
https://github.com/django/django/blob/c8eb9a7c451f7935a9eaafbb195acf2aa9fa867d/django/views/generic/detail.py#L108
The following website gives you a great overview and description of all class based views and some mixins:
https://ccbv.co.uk/projects/Django/4.1/django.views.generic.detail/BaseDetailView/
can I return a list in the to_representation method in Django Rest Framework
I need to modify the output in the serializer here is a recent output
{
"id": 1,
"display_sequence": 2
}
I need to modify the recent output to
[
{
"id": 1
"display_sequence": 2
},
{
"id" : 2
"display_sequence": 1
}
]
so the second data I got from the query filter based on the container id and target_container_id
instance = Container.objects.filter(id__in=[self.container_id, self.target_container_id])
if I return to serializer I got this error
Got AttributeError when attempting to get a value for field `display_sequence` on serializer `ContainerSequenceSwapSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `list` instance.
Original exception text was: 'list' object has no attribute 'display_sequence'.
how to I can return yo expected output?
here are my views
Views
class ContainerViewSet(viewsets.ModelViewSet):
"""Container ViewSet for CRUD operations."""
queryset = Container.objects.all()
def get_serializer_class(self):
return ContainerSerializerV1
#action(methods=["patch"], detail=True, url_path="swap-sequence")
def swap_sequence(self, request, pk):
# serializer = ContainerSequenceSwapSerializer(data=request.data)
container = self.get_object()
serializer = ContainerSequenceSwapSerializer(container, data=request.data, context={'container': container})
if serializer.is_valid(raise_exception=True):
# display data here
content = serializer.data
return Response(data=content, status=status.HTTP_200_OK)
Serializer
class ContainerSequenceSwapSerializer(serializers.ModelSerializer):
"""Serializer for Container sequence swap detail action."""
display_sequence = serializers.IntegerField()
# add class meta here to display id, swap sequence
class Meta:
model = Container
fields = (
"id",
"display_sequence",
)
read_only_fields = ("id", "display_sequence")
# sorting data
def to_representation(self, instance):
instance = Container.objects.filter(id__in=[self.container_id, self.target_container_id])
# data = super().to_representation(instance)
return instance
# custom validation
def validate(self, attrs):
display_sequence = super().validate(attrs)
container = self.context.get("container")
if not container:
return display_sequence
target_display_sequence = display_sequence["display_sequence"]
try:
target_container = Container.objects.get(
module=container.module, display_sequence=target_display_sequence
)
except Container.DoesNotExist:
raise serializers.ValidationError(
{"display_sequence": ["Invalid swap target"]}
)
else:
# switching
container.display_sequence, target_container.display_sequence = (
target_container.display_sequence,
container.display_sequence,
)
container.save()
target_container.save()
# datas
self.container_id = container.id
self.target_container_id = target_container.id
return display_sequence
how do I can return the expected output without modifying the views.py
Some consider model as an object, some consider as an instance. Can anyone tell me what is the difference between these two examples?
model.py:
class ToDo(models.Model):
name = models.CharField(max_length=100)
due_date = models.DateField()
def __str__(self):
return self.name
forms.py:
class ToDoForm(forms.ModelForm):
class Meta:
model = ToDo
fields = ['name', 'due_date']
views.py:
def todo_list(request):
todos = ToDo.objects.all()
context = {'todo_list': todos}
return render(request, 'todoApp/todo_list.html', context)
Considering the code below, what is form instance?
class PostDetailView(DetailView):
model = Post
def post(self, *args, **kwargs):
form = CommentForm(self.request.POST)
if form.is_valid():
post = self.get_object()
comment = form.instance
comment.user = self.request.user
comment.post = post
comment.save()
return redirect('detail', slug=post.slug)
return redirect('detail', slug=self.get_object().slug)
So in object-oriented programming, an object is an instance of a class. So model instance and model object are the same.
Let's do an example for that:
# This is your class
class ToDo(models.Model):
name = models.CharField(max_length=100)
due_date = models.DateField()
# If somewhere I call
my_var = ToDo() # my_var contain an object or an instance of my model ToDo
As for your question about the form, each form in Django may or may not contain an instance. This instance is the object modified by the form. When you create an empty form, this form.instance is None, because your form is not bound to an object. But if you build a form taking an object to modify as its parameter or after filling it, this object is the instance.
Example:
form = CommentForm()
print(form.instance) # This will return None, there is no instance bound to the form
comment = Comment.objects.get(pk=1)
form2 = CommentForm(instance=comment)
print(form2.instance) # Now the instance contain an object Comment or said an other way, an instance of Comment. When you display your form, the fields will be filled with the value of this instance
I hope that it's a little bit more clear.
CommentForm is ModelForm and ModelForm has instance attribute (which you can set (update scenario) or __init__ method of CommentForm will instantiate new model instance of model that you set to Metaclass
from BaseModelForm source:
if instance is None:
# if we didn't get an instance, instantiate a new one
self.instance = opts.model()
object_data = {}
I am trying to use a ListSerializer so that I can create/de-serialize multiple objects in a list on a POST. I followed the guide at https://www.django-rest-framework.org/api-guide/serializers/#listserializer but seem to be running into this error when i visit the endpoint.
assert self.child is not None, '``child`` is a required argument.'
python3.7/site-packages/rest_framework/serializers.py in __init__, line 592
My serializers are as follows:
class PredictionListSerializer(serializers.ListSerializer):
def update(self, instance, validated_data):
pass
def create(self, validated_data):
predictions = [Prediction(**item) for item in validated_data]
return Prediction.objects.bulk_create(predictions)
class NestedPredictionSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(read_only=True)
# Nested Serializer
data = DataSerializer()
class Meta:
model = Prediction
list_serializer_class = PredictionListSerializer
fields = ('id', 'specimen_id', 'data' 'date_added',)
extra_kwargs = {
'slug': {'validators': []},
}
datatables_always_serialize = ('id',)
The assertion error is being thrown in the initialization of the ListSerializer, however, the serializer is being initialized in a ViewSet like so.
class BulkPredictionViewSet(viewsets.ModelViewSet):
queryset = Prediction.objects.all()
serializer_class = PredictionListSerializer
Anyone familiar with this issue? I am wondering if my lack o control around initialization of the serializer (because I am using a ViewSet) is affecting this. If I try to pass the NestedPredictionSerializer into the ViewSet I get "Invalid data. Expected a dictionary, but got list."
EDIT:
I was able to overwrite the get_serializer method in my ViewSet to set many=True and pass the serializer as my NestedPredictionSerializer which recognizes the list on a POST. Howeber, on a get now I receive the error When a serializer is passed a ``data`` keyword argument you must call ``.is_valid()`` before attempting to access the serialized ``.data`` representation.
You should either call ``.is_valid()`` first, or access ``.initial_data`` instead.
I was able to get both the POST and GET working when the following the advice on this read combined with this answer: https://stackoverflow.com/a/45651309/3439441
My overridden ViewSet.get_serializer now looks like this:
def get_serializer(self, *args, **kwargs):
if self.request.method.lower() == 'post':
data = kwargs.get('data')
kwargs['many'] = isinstance(data, list)
return super(BulkPredictionViewSet, self).get_serializer(*args, **kwargs)
Just use many=True only for create action:
class BulkPredictionViewSet(viewsets.ModelViewSet):
queryset = Prediction.objects.all()
serializer_class = NestedPredictionSerializer
def get_serializer(self, *args, **kwargs):
serializer_class = self.get_serializer_class()
kwargs['context'] = self.get_serializer_context()
if self.action == 'create':
kwargs['many'] = True
return serializer_class(*args, **kwargs)
You don't need to use PredictionListSerializer since many=True will create ListSerializer automatically.
Can Anyone please explain me what this error means??
I have done this in my views.py:
class FormListView(FormMixin, ListView):
def get(self, request, *args, **kwargs):
# From ProcessFormMixin
form_class = self.get_form_class()
self.form = self.get_form(form_class)
# From BaseListView
self.object_list = self.get_queryset()
allow_empty = self.get_allow_empty()
if not allow_empty and len(self.object_list) == 0:
raise Http404(_(u"Empty list and '%(class_name)s.allow_empty' is False.")
% {'class_name': self.__class__.__name__})
context = self.get_context_data(object_list=self.object_list, form=self.form)
return self.render_to_response(context)
def post(self, request, *args, **kwargs):
return self.get(request, *args, **kwargs)
class CompanyListView(LoginRequiredMixin,FormListView):
model = Company
form_class = daterangeform
paginate_by = 10
def get_queryset(self):
return company.objects.filter(User=self.request.user)
def get_context_data(self, **kwargs):
context = super(companyListView, self).get_context_data(**kwargs)
context['selectdate_list'] = selectdate.objects.filter(User=self.request.user).latest()
return context
And I am getting this error:
ValueError: earliest() and latest() require either fields as positional arguments or 'get_latest_by' in the model's Meta.
Can anyone please explain me what is wrong in my code and possible solution for doing it in correct way...
Thank you
As specified in the documentation for latest(*fields) [Django-doc]:
Returns the latest object in the table based on the given
field(s).
This example returns the latest Entry in the table, according to the
pub_date field:
Entry.objects.latest('pub_date')
So if you want to obtain the latest object with respect to a field (for example updated_date), you can write this as:
selectdate.objects.filter(
User=self.request.user
).latest('updated_date')
You can however use the latest() without parameters, given you specified the order for this in the Meta class of the model, like:
class Foo(models.Model):
name = models.CharField(max_length=20)
class Meta:
get_latest_by = ['name']
In that case
Foo.objects.latest()
will give the Foo object with the maximum name (if we here compare the names lexicographically).