0

I am trying to create a rest api which gives the weather data for a particular city and n days. I've created a model which specifies all the required fields. I've populated the database using management commands.

I've tried using Q method to query the database. but I am making error somewhere and I am unable to identify it.

#views.py

from django.shortcuts import render


from django.shortcuts import get_object_or_404
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import weatherdata
from .serializers import weatherdataserializer
from django.http import Http404

from django.db.models import Q


# Create your views here.


class weatherList(APIView):
    def get(self, request):
        weather = weatherdata.objects.all()
        serializer = weatherdataserializer(weather,  many=True)
        return Response(serializer.data)

    def post(self, request):
        serializer = weatherdataserializer(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 weatherDetail(APIView):
    def get_queryset(self,*args , **kwargs):
        queryset_list = weatherdata.objects.all()
        query = self.request.GET.get("q")
        if query:
            queryset_list = queryset_list.filter(
                Q(city_name__icontains = query) |
                Q(city_id__icontains = query)
            ).distinct()
        return queryset_list

#serialisers.py

from rest_framework import serializers

from .models import weatherdata

class weatherdataserializer(serializers.ModelSerializer):

    class Meta:
        model  = weatherdata
        # fields = '__all__'
        fields = (
            'city_name',
            'city_id',
            'latitude',
            'longitude',
            'dt_txt',
            'temp',
            'temp_min',
            'temp_max',
            'pressure',
            'sea_level',
            'grnd_level',
            'humidity',
            'main',
            'description',
            'clouds',
            'wind_speed',
            'wind_degree',
        )


#models.py

from django.db import models

# Create your models here.

from django.db import models

class weatherdata(models.Model):
    city_name   = models.CharField(max_length = 80)
    city_id     = models.IntegerField(default=0)
    latitude    = models.FloatField(null=True , blank=True)
    longitude   = models.FloatField(null=True , blank=True)
    dt_txt      = models.DateTimeField()
    temp        = models.FloatField(null = False)
    temp_min    = models.FloatField(null = False)
    temp_max    = models.FloatField(null = False)
    pressure    = models.FloatField(null = False) 
    sea_level   = models.FloatField(null = False)
    grnd_level  = models.FloatField(null = False)
    humidity    = models.FloatField(null = False)
    main        = models.CharField(max_length=200)
    description = models.CharField(max_length=30)
    clouds      = models.IntegerField(null=False)
    wind_speed  = models.FloatField(null = False)
    wind_degree = models.FloatField(null = False)


    def __str__(self):
        return self.city_name

#urls.py


from django.contrib import admin
from django.urls import path

from django.conf.urls import url, include
from django.contrib.auth.models import User
from rest_framework import routers, serializers, viewsets

# Serializers define the API representation.
from importweather import views
from rest_framework.urlpatterns import format_suffix_patterns

urlpatterns = [
    path('admin/', admin.site.urls),
    url(r'^weatherdata', views.weatherList.as_view()),
    url(r'^weatherdata/(?P<pk>[0-9]+)/', views.weatherDetail.as_view()),
]

urlpatterns = format_suffix_patterns(urlpatterns)

http://127.0.0.1:8000/weatherdata/Chennai/5 should fetch only the weather in Chennai for the past 5 days(note.the DateTime field is as follows: "2019-08-12T12:00:00Z" , i.e Date-Time)

3
  • 1
    You don't seem to have said what is going wrong. Commented Aug 15, 2019 at 10:58
  • @DanielRoseman the API is showing all the values stored in by database. It is not showing only the required cities. I don't know how to make the QuerySet work correctly Commented Aug 15, 2019 at 11:01
  • 1
    But your URLs don't match what you claim you are doing. You say you are going to "/weatherdata/Chennai/5", but your URL only accepts "/weatherdata/5". And again your view is filtering on a "q" value; where is that provided? You need to explain your problem consistently. Commented Aug 15, 2019 at 11:13

2 Answers 2

1

How does this URL http://127.0.0.1:8000/weatherdata/Chennai/5 map to your weatherDetail view? There's no GET request parameter q in it.

Your detail view only filters based on the q parameter, so your above URL cannot return filtered results.

With your URL pattern, pk needs to be digits, so it doesn't match but it matches the weatherdata general list view because you don't specify a $ to terminate it.

Change your URL pattern to:

url(r'^weatherdata/(?P<city>.+)/(?P<days>[0-9]+)', views.weatherDetail.as_view()

and then in your view you can use kwargs['city'] and kwargs['days'] to retrieve the URL parameters.

Note also that APIView does not have a get_queryset() method, so your method won't be called. You need to make it also a ListAPIView.

Sign up to request clarification or add additional context in comments.

4 Comments

I could modify the 5 later on, my first task is to show the particular city given. what I mean is, once the city is classified, I could use the same logic to sort the number of date also
how should I modify url in url patterns? should it be url(r'^weatherdata/city/', views.weatherDetail.as_view())
I’ve written it in my answer
Read the docs to understand how these url patterns work. I've linked to the 1.11 docs as you're apparently not using Django 2.x
0

In your serializer Meta class fields should be in list but you put them on an array. I think this may solve your problem.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.