why i am getting this error KeyError at /evaluationtest/? 'request' - django

hi i have create an Crud function for evaluation Test but i am getting keyerror 'request' this kind of strange to me i have not seen this error before i am new to django can somebody help me to fix it?
def validate(self, data, *args, **kwargs):
questions = self.context['request'].data.get("questions")
if not questions:
raise serializers.ValidationError("questions are required")
if self.context["request"].method == "POST":
self.questions = QuestionSerializer(data=questions, many=True)
self.questions.is_valid(raise_exception=True)
elif self.context["request"].method == "PUT":
self.questions = questions
self.new_questions = self.context["request"].data.get(
"new_questions")
if self.new_questions:
self.new_questions = QuestionSerializer(
data=self.new_questions, many=True)
self.new_questions.is_valid(raise_exception=True)
return data
def create(self, data):
evaluation_test = EvaluationTest()
evaluation_test.category = data['category']
evaluation_test.admin = data['admin']
evaluation_test.title = data['title']
evaluation_test.type = data['type']
evaluation_test.save()
for question in data['questions']:
question.evaluationtest = evaluation_test
question.save()
return evaluation_test
def update(self, instance, validated_data):
instance.title = validated_data.get["title", instance.title]
instance.type = validated_data.get["type", instance.type]
instance.category = validated_data.get["category", instance.category]
instance.admin = validated_data.get["admin", instance.admin]
for question in self.questions:
q = QuestionSerializer(instance=question["id"], data=question)
q.is_valid(raise_exception=True)
q.save()
if self.new_questions:
new_questions = self.new_questions.save()
for question in new_questions:
question.save()
return instance
views.py
Here is my view.py code when i am implementing the whole crud application you can see and please give me how can i modify to make it work
class EvaluationTestViewSet(viewsets.ModelViewSet):
permission_classes = (IsAuthenticated, )
serializer_class = EvaluationTestSerializer
queryset = EvaluationTest.objects.all()
#action(methods=['get'], detail=False, url_path='by-category/(?P<category_id>\d+)', url_name='by_category')
def by_category(self, request, *args, **kwargs):
evaluationtest = EvaluationTestSerializer.by_category(
kwargs['category_id'])
if evaluationtest:
return Response(evaluationtest)
return Response(status=HTTP_404_NOT_FOUND)
def create(self, request):
serializer = EvaluationTestSerializer(data=request.data)
if serializer.is_valid():
evaluationtest = serializer.create(request)
print(evaluationtest)
if evaluationtest:
return Response(status=HTTP_201_CREATED)
return Response(status=HTTP_400_BAD_REQUEST)

you have to set the request in the serializer context.
change your create method:
def create(self, request):
serializer = EvaluationTestSerializer(data=request.data, context={'request': request})
if serializer.is_valid():
# call save() instead of create
evaluationtest = serializer.save()
print(evaluationtest)
# ideally you should also return serializer.data
return Response(status=HTTP_201_CREATED)
# ideally you should also return serializer.errors
return Response(status=HTTP_400_BAD_REQUEST)

Related

Need to get existing data and save if available in the create method of nested serializers using django

serializers.py
class Product_Serializers(serializers.ModelSerializer):
product_id = serializers.CharField(required=False)
class Meta:
model = Product
fields = ('product_id','product_name',)
class Clientpost_Serializers(serializers.ModelSerializer):
billing_method = Billingmethod_Serializers()
product = Product_Serializers(many=True)
def create(self, validated_data):
billing_method_data = validated_data.pop('billing_method')
product_data = validated_data.pop('product')
billing_method = Billing_Method.objects.create(**billing_method_data)
validated_data['billing_method'] = billing_method
client = Client.objects.create(**validated_data)
product = [Product.objects.create(**product_data) for product_data in product_data]
client.product.set(product)
return client
def update(self, instance, validated_data):
billing_method_data = validated_data.pop('billing_method')
billing_method = instance.billing_method
instance.currency = validated_data.get('currency', instance.currency)
instance.currency_type = validated_data.get('currency_type', instance.currency_type)
instance.first_name = validated_data.get('first_name', instance.first_name)
instance.last_name = validated_data.get('last_name', instance.last_name)
instance.description = validated_data.get('description', instance.description)
instance.street_address = validated_data.get('street_address', instance.street_address)
instance.city = validated_data.get('city', instance.city)
instance.state = validated_data.get('state', instance.state)
instance.country = validated_data.get('country', instance.country)
instance.pincode = validated_data.get('pincode', instance.pincode)
instance.industry = validated_data.get('industry', instance.industry)
instance.company_size = validated_data.get('company_size', instance.company_size)
instance.client_name = validated_data.get('client_name', instance.client_name)
instance.contact_no = validated_data.get('contact_no', instance.contact_no)
instance.mobile_no = validated_data.get('mobile_no', instance.mobile_no)
instance.email_id = validated_data.get('email_id', instance.email_id)
instance.client_logo = validated_data.get('client_logo', instance.client_logo)
instance.client_code = validated_data.get('client_code', instance.client_code)
instance.save()
billing_method.billing_name = billing_method_data.get('billing_name', billing_method.billing_name)
billing_method.save()
product = validated_data.get('product')
for prod in product:
product_id = prod.get('product_id', None)
if product_id:
product_data = Product.objects.get(product_id=product_id, product=instance)
product_data.product_name = prod.get('product_name', product_data.product_name)
product_data.save()
else:
Product.objects.create(product=instance, **prod)
return instance
class Meta:
model = Client
fields = ('client_id','currency','currency_type','billing_method','first_name',...)
When I Tired to do POST and PUT method it is getting posted and updated successfully. But it is getting created everytime when I do POST, as I have given unique=True so it is throwing the product is already exist. But I dont need to create each time, if it is already available it need to be saved in the nested model field. If that is possible ?
I tried and I couldn't able to figure it out, please help me to solve the issue. It would be a life saver if I could get any answer.
Views.py
class Clientlist(APIView):
renderer_classes = (CustomRenderer,)
parser_classes = [parsers.MultiPartParser, parsers.FormParser]
"""
List all snippets, or create a new snippet.
"""
def get(self, request, format=None):
clients = models.Client.objects.all()
serializer = serializers.Clientpost_Serializers(clients, many=True)
return Response(serializer.data)
def post(self, request, format=None):
serializer = serializers.Clientpost_Serializers(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class ClientDetail(APIView):
renderer_classes = (CustomRenderer,)
parser_classes = [parsers.MultiPartParser, parsers.FormParser]
def get_object(self, pk):
try:
return models.Client.objects.get(pk=pk)
except models.Client.DoesNotExist:
raise Http404
def get(self, request, pk, format=None):
client = self.get_object(pk)
serializer = serializers.Client_Serializers(client)
return Response(serializer.data)
def put(self, request, pk, format=None):
client = self.get_object(pk)
serializer = serializers.Clientpost_Serializers(client, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, pk, format=None):
client = self.get_object(pk)
client.delete()
return Response(status=status.HTTP_204_NO_CONTENT)

prepoluate a generec createview

i want that a form is prepoluate with data
my model:
TYPE = (("S",'Swing'),
("R","Rapide"))
class valuation(models.Model):
stock = models.ForeignKey("stock",on_delete=models.CASCADE,related_name='valuation',)
date = models.DateField(auto_created=True)
val_type = models.CharField(choices=TYPE, max_length=1,default='R')
user = models.ForeignKey("users.User", on_delete=models.CASCADE)
def __str__(self):
return f"{self.stock} - {self.date} - {self.val_type}"
my view:
class valuationCreateviewSwing(CreateView):
template_name = "evaluation/evaluation_create.html"
form_class = valuationModeform
def get_form_kwargs(self): # prepopulate form
kwargs = super(valuationCreateviewSwing, self).get_form_kwargs()
stck = get_object_or_404(stock, pk=self.kwargs['pk'])
kwargs['user'] = self.request.user
kwargs['val_type'] = "S"
kwargs['stock'] = stck
return kwargs
def get_context_data(self, **kwargs):
# we need to overwrite get_context_data
# to make sure that our formset is rendered
data = super().get_context_data(**kwargs)
if self.request.POST:
data["val_detail"] = ChildFormset1(self.request.POST)
else:
data["val_detail"] = ChildFormset1()
data.update({
"typeVal": "Swing",})
return data
def form_valid(self, form):
context = self.get_context_data()
val_detail_Swing = context["val_detail_Swing"]
self.object = form.save(commit=False)
# add data info neede about valuation model
self.object = form.save()
if val_detail_Swing.is_valid():
val_detail_Swing.instance = self.object
val_detail_Swing.save()
return super().form_valid(form)
def get_success_url(self):
return reverse("stock:stock-list")
I've a child form in my view (this part works ok):
ChildFormset1 = inlineformset_factory(
valuation, val_detail_Swing, form=valuationSwingModelform, can_delete=False)
I tried to use ge_for_kwargs but it seems not working as I've an error message :
init() got an unexpected keyword argument 'user'
You can use get_initial() method:
class valuationCreateviewSwing(CreateView):
template_name = "evaluation/evaluation_create.html"
form_class = valuationModeform
def get_initial(self):
query = self.request.GET
return {
'user': self.request.user.pk
'val_type': "S",
'stock': self.kwargs.get('pk')
}
...
Or you should override __init__() method and stay to use get_form_kwargs()
class valuationModeform(ModelForm):
class Meta:
model = Valuation
fields = '__all__'
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None)
val_type = kwargs('val_type', None)
stock = kwargs.pop('stock', None)
super().__init__(*args, **kwargs)
# assign initial values
self.fields['user'].initial = user
self.fields['val_type'].initial = val_type
self.fields['stock'].initial = stock

super(type, obj): obj must be an instance or subtype of type Django

I work on a small Django App and get an error tells me: super(type, obj): obj must be an instance or subtype of type.I am trying to save the details of the sale in the database but I get this error.
Views
class VentaCreateView(LoginRequiredMixin, ValidatePermissionRequiredMixin, CreateView):
model = Venta
form_class = nueva_venta_form
template_name = 'venta/venta_form.html'
success_url = reverse_lazy('Index')
permission_required = 'store_project_app.change_categoria'
url_redirect = success_url
#method_decorator(csrf_exempt)
def dispatch(self, request, *args, **kwargs):
return super().dispatch(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
data = {}
try:
action = request.POST['action']
if action == 'autocomplete':
elif action == 'add':
#ventas = request.POST['action']
#ventas = request.POST['ventas']
ventas = json.loads(request.POST['ventas'])
#print(ventas)
venta = Venta()
venta.id_cliente = Cliente.objects.get(id_cliente = ventas['id_cliente'])
venta.id_empleado = Empleado.objects.get(id_empleado = ventas['id_empleado'])
venta.fecha_venta = ventas['fecha_venta']
venta.forma_pago = Metodo_Pago.objects.get(id_metodo_pago = ventas['forma_pago'])
venta.precio_total = float(ventas['precio_total'])
venta.save()
for i in ventas['productos']:
detalle_venta = Detalle_Venta()
detalle_venta.id_venta = venta.id_venta
detalle_venta.id_producto = i['id_producto']
detalle_venta.cantidad = int(i['cantidad'])
detalle_venta.subtotal = float(i['subtotal'])
detalle_venta.save()
else:
data['error'] = 'No ha ingresado a ninguna opciĆ³n'
except Exception as e:
data['error'] = str(e)
return JsonResponse(data, safe=False)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['title'] = 'Crear una Venta'
context['entity'] = 'Venta'
context['list_url'] = self.success_url
context['action'] = 'add'
return context

DRF local variable 'msg_data' referenced before assignment

This is my serializers.py
class UserProfileSerializer(serializers.ModelSerializer):
img_count = serializers.SerializerMethodField('get_img_count')
post_count = serializers.SerializerMethodField('get_post_count')
msg_count = serializers.SerializerMethodField('get_msg_count')
class Meta:
model = User
fields = ('id', 'username', 'img_count', 'post_count', 'msg_count')
def get_img_count(self, obj):
try:
img_data = ImgSerializer(Img.objects.filter(author=obj.id), many=True)
except img_data.DoesNotExist:
return 0
return img_data
def get_post_count(self, obj):
try:
post_data = PostSerializer(Post.objects.filter(author=obj.id), many=True)
except post_data.DoesNotExist:
return 0
return post_data
def get_msg_count(self, obj):
try:
msg_data = Smessage(Msg.objects.filter(author=obj.id), many=True)
except msg_data.DoesNotExist:
return 0
return msg_data
This is my views.py
class UserProfile(APIView):
permission_classes = [AllowAny]
def get(self, request):
query = User.objects.all()
serializer = UserProfileSerializer(query, many=True)
return Response(serializer.data)
This is the Error Snippet
I want to get this
{
"id": 9,
"username": "emil#gmail.com",
"img_count:3,
"post_count":5,
"msg_count":50,
}
also getting error after using img_count.count().
You should change the exceptions to:
img_data.DoesNotExist --> Img.DoesNotExist
post_data.DoesNotExist --> Post.DoesNotExist
msg_data.DoesNotExist --> Msg.DoesNotExist
Because, instances does not have any exception object, rather the model classes has them. More information can be found in documentation.
Update
If you just want the count, then you don't need to use such extensive implementation. You can simply try:
def get_img_count(self, obj):
return Img.objects.filter(author=obj.id).count()
def get_post_count(self, obj):
return Post.objects.filter(author=obj.id).count()
def get_msg_count(self, obj):
return Msg.objects.filter(author=obj.id).count()
You should set default value of each variable because in case of error other than DoesNotExist, you will face this error.
class UserProfileSerializer(serializers.ModelSerializer):
img_count = serializers.SerializerMethodField('get_img_count')
post_count = serializers.SerializerMethodField('get_post_count')
msg_count = serializers.SerializerMethodField('get_msg_count')
class Meta:
model = User
fields = ('id', 'username', 'img_count', 'post_count', 'msg_count')
def get_img_count(self, obj):
img_data = 0
try:
img_data = ImgSerializer(Img.objects.filter(author=obj.id), many=True).data
except Img.DoesNotExist:
pass
return img_data
def get_post_count(self, obj):
post_data = 0
try:
post_data = PostSerializer(Post.objects.filter(author=obj.id), many=True).data
except Post.DoesNotExist:
pass
return post_data
def get_msg_count(self, obj):
msg_data = 0
try:
msg_data = Smessage(Msg.objects.filter(author=obj.id), many=True).data
except Msg.DoesNotExist:
pass
return msg_data

Django. Pass variable from view to template

I want to pass variable appuser to template and I don't understand how to do it.
I have tried to use kwargs.update but it still doesn't work.
I have a view:
class CausesView(AjaxFormView):
appuser = None
causes = []
cause_allocation_set = None
def prepare_request(self, request, *args, **kwargs):
self.causes = Cause.objects.filter(is_main_cause = True)
self.appuser = AppUser.get_login_user(request)
self.cause_allocation_set = set([r.cause_id for r in self.appuser.current_cause_save_point.cause_allocations_list])
def prepare_context(self, request, context, initial):
initial.update(
causes = self.cause_allocation_set,
appuser = self.appuser,
)
def prepare_form(self, request, form):
form._set_choices("causes", [(r.id, r.title) for r in self.causes])
def custom_context_data(self, request, **kwargs):
kwargs.update(
special_test = "dsf"
)
return kwargs
def process_form(self, request, form):
data = form.cleaned_data
try:
with transaction.atomic():
if self.cause_allocation_set != set(data.get('causes')):
self.appuser.save_causes(data.get('causes'))
except Exception as e:
message = "There was an error with saving the data: " + str(e.args)
return AjaxErrorResponse({'title':"Error", 'message':message})
return AjaxSuccessResponse('Causes Saved')
And I have a form:
class CauseForm(AjaxForm):
causes = forms.TypedMultipleChoiceField(label="Select Causes", choices = (), required = False, coerce = int,
widget = forms.CheckboxSelectMultiple())
def clean(self):
cleaned_data = super(CauseForm, self).clean()
causes = cleaned_data.get('causes')
validation_errors = []
if not causes is None and not len(causes):
validation_errors.append(forms.ValidationError("At least one Cause is required"))
if len(validation_errors):
raise forms.ValidationError(validation_errors)
return cleaned_data
How can I get variable appuser in temlpate?
For example:
{{ appuser.name }}
doesn't work.
Read How to use get_context_data in django
and
https://docs.djangoproject.com/en/1.9/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin.get_context_data
Here is example of how you can do this
class CausesView(AjaxFormView):
...
def get_context_data(self, **kwargs):
context_data = super(CausesView, self).get_context_data(**kwargs)
context_data['appuser'] = self.appuser
return context_data