How to store users location in django using GeoDjango
Tags: django, python, beginners, programming
Published: 2024-01-31 09:19:02

Hello devs, In this blog we'll learn about storing user location in django with the longitude and latitude and for that we will use GeoDjango, Django provides a framework called GeoDjango, and with the help of GeoDjango we can store the user location parameters (Latitude and Longitude), and point the user location on map in django admin.

So, basically I'm storing the user location and the parameter in django while signup or user creation, and with the help of that we can know the user exact location.

and for storing the user location with django, we are using Postgresql database, which provides postgis extension, and supports the user location functionality, and I'm using Mac, so, please manage the Postgis path and extension according to your OS, so let's start code now:-

# Post link for source code
```
How To Store Users Location In Django Using Geodjango pythondjangogeek.com
```

### Geo Django and Postgresql Installation

```
brew install postgres
brew install postgis
```
or

#### download the postgres app from this link:-

```
https://postgresapp.com/downloads.html
```

### Installing Geospatial Libraries

```
brew install gdal
brew install geos
brew install libgeoip
```
add library path in django setting.py file

```
GDAL_LIBRARY_PATH = '/opt/homebrew/Cellar/gdal/3.8.3/lib/libgdal.dylib'
GEOS_LIBRARY_PATH = '/opt/homebrew/Cellar/geos/3.12.1/lib/libgeos_c.dylib'

```

## Setting up Django project

```
django-admin startproject userlocation
```

## and now mention postgis in settings.py

```
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.gis',
    'rest_framework.authtoken',
    'rest_framework',
    'users'
]

```

## Now, we will create models.py

```
from django.contrib.auth.models import User
from django.contrib.gis.db import models


class Customer(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='user_profile')
    name = models.CharField(max_length=100)
    location = models.PointField(blank=True, null=True)
    longitude = models.FloatField()
    latitude = models.FloatField()

    def __str__(self):
        return self.name
    
    
```

ww'll store user longitude and latitude and also location with the PointField, this field will show the map on Django admin like this:- 


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ix83zg1zra307zqw3mgd.png)


## Admin.py file

```
from django.contrib import admin
from .models import Customer
from django.contrib.gis.admin import OSMGeoAdmin


@admin.register(Customer)
class CustomerAdmin(OSMGeoAdmin):
    list_display = ['id', 'name', 'user', 'location', 'longitude', 'latitude']
    search_fields = ['name', 'user__username']
```

## Serializers.py file

```
from rest_framework import serializers
from django.contrib.auth.models import User
from .models import Customer

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ['username', 'password', 'email']

class CustomerSerializer(serializers.ModelSerializer):
    user = UserSerializer()

    class Meta:
        model = Customer
        fields = ['id', 'user', 'name', 'location', 'longitude', 'latitude']
```


## Views.py file

```
from rest_framework import generics
from rest_framework.response import Response
from rest_framework import status
from django.contrib.auth.models import User
from django.contrib.auth import authenticate, login
from rest_framework.authtoken.models import Token
from django.contrib.gis.geos import Point
from .models import Customer
from .serializers import CustomerSerializer, UserSerializer

class CustomerListCreateView(generics.ListCreateAPIView):
    queryset = Customer.objects.all()
    serializer_class = CustomerSerializer

    def create(self, request, *args, **kwargs):
        user_serializer = UserSerializer(data=request.data.get('user'))
        customer_serializer = self.get_serializer(data=request.data)

        user_serializer.is_valid(raise_exception=True)
        customer_serializer.is_valid(raise_exception=True)

        # Create User instance
        user = User.objects.create_user(**user_serializer.validated_data)

        # Extract latitude and longitude from the request data
        latitude = request.data.get('latitude', None)
        longitude = request.data.get('longitude', None)

        # Check if both latitude and longitude are present
        if latitude is not None and longitude is not None:
            # Create a Point object with the given latitude and longitude
            location = Point(float(longitude), float(latitude))
            customer_serializer.validated_data['location'] = location

        # Create Customer instance
        customer_serializer.validated_data['user'] = user
        self.perform_create(customer_serializer)

        # Create and return token
        token, created = Token.objects.get_or_create(user=user)


        headers = self.get_success_headers(customer_serializer.data)
        return Response({'token': token.key, **customer_serializer.data}, status=status.HTTP_201_CREATED, headers=headers)

class CustomerDetailView(generics.RetrieveUpdateDestroyAPIView):
    queryset = Customer.objects.all()
    serializer_class = CustomerSerializer

class UserLoginView(generics.CreateAPIView):
    serializer_class = UserSerializer

    def create(self, request, *args, **kwargs):
        username = request.data.get('username', '')
        password = request.data.get('password', '')

        user = authenticate(request, username=username, password=password)

        if user is not None:
            login(request, user)
            token, created = Token.objects.get_or_create(user=user)
            serializer = UserSerializer(user)
            return Response({'token': token.key, **serializer.data})
        else:
            return Response({'detail': 'Invalid credentials'}, status=status.HTTP_401_UNAUTHORIZED)

```

## URLs.py file

```
from django.urls import path
from .views import CustomerListCreateView, CustomerDetailView, UserLoginView

urlpatterns = [
    path('customers/', CustomerListCreateView.as_view(), name='customer-list-create'),
    path('customers/<int:pk>/', CustomerDetailView.as_view(), name='customer-detail'),
    path('login/', UserLoginView.as_view(), name='user-login'),
]
```


so, that's how you can implement the user location in django using GeoDjango, and you can connect with me.

Thank You.
Shivam Rohilla | Python Developer