Need to edit django get request to include list of models given a list of id's
I'm currently creating the backend for a website in which users can add public events/gatherings to their favorites list. I'm currently creating a model in Django which models a user created account named Account. I want to implement it so that Account includes a field called "favorites" which stores the id's of the Events that the specific account added to their favorites.
class Account(models.Model):
username = models.CharField(max_length=20, null=True)
first_name = models.CharField(max_length=30, null=True)
last_name = models.CharField(max_length=30, null=True)
email = models.EmailField(max_length=254, null=True)
phone_number = models.CharField(max_length=254, null=True)
class Favorites(models.Model):
favorite = models.PositiveIntegerField(null=True)
account = models.ForeignKey(Account, related_name='favorites', on_delete=models.CASCADE, null=True)
def __str__(self):
return f"{self.favorite}"
class Events(models.Model):
event_image = models.ImageField(null=True) # will have to figure out where this image is uploaded to
event_name = models.CharField(max_length=50, null=True)
event_date_time = models.DateTimeField(max_length=50, null=True)
event_location = models.CharField(max_length=50, null=True)
event_description = models.TextField(null=True)
Currently I can send a post request of this form, for this example this specific account favorited Events with id of 15 and 17.
{
"username": "Name",
"first_name": "John",
"last_name": "Doe",
"email": "Johndoe@gmail.com",
"phone_number": "6666666666"
"favorites": [{favorite: "15"}, {favorite: "17"}]
}
However after sending a post request like that I want to have my get request be of this form
{
"username": "Name",
"first_name": "John",
"last_name": "Doe",
"email": "Johndoe@gmail.com",
"phone_number": "6666666666"
"favorites": [
{
"id": 15,
"event_image": "http://127.0.0.1:8000/",
"event_name": "bbq",
"event_date_time": null,
"event_location": "portland",
"event_description": "barbeque time",
},
{
"id": 17,
"event_image": "http://127.0.0.1:8000/",
"event_name": "bbq2",
"event_date_time": null,
"event_location": "Toronto",
"event_description": "barbeque time",
}
]
}
I'm trying to implement it such that after I send a post request, when I call a get request for a specific account instead of returning the list of id's for favorites, it'll instead return a list of the nested models that those id's belong to. I was wondering on how to get started on this implementation, as I'm not too sure how to go about this implementation. I'm trying to make my get request be of this form.
Before answering the question, I would like to talk about the models. First, a good practice is to extend or substitute an User model. And, secondly a many-to-many relationship would be more adequate (one user has many favorite events, and one event is favorited by many users).
An example substituting the model, using an app named core
:
settings.py
AUTH_USER_MODEL = 'core.Account'
models.py
class Account(AbstractUser):
phone_number = models.CharField(max_length=255, null=True)
favorites = models.ManyToManyField('Event')
class Event(models.Model):
image = models.ImageField(null=True) # will have to figure out where this image is uploaded to
name = models.CharField(max_length=50, null=True)
date = models.DateTimeField(max_length=50, null=True)
location = models.CharField(max_length=50, null=True)
description = models.TextField(null=True)
Now, related to the question. The implementation method will depend on the kind of service
, if it is either a plain web service or an API.
For instance, for a plain web service
you can build the response yourself using Python lists and dictionaries, in this case a list containing all users with their favorite events:
views.py
from django.forms.models import model_to_dict
from .models import Event, Account
def favorites(request):
data = []
accounts = Account.objects.all()
for account in accounts:
obj = model_to_dict(account, fields=('username', 'first_name', 'last_name', 'email', 'phone_number'))
obj['favorites'] = []
for favorite in account.favorites.all():
obj['favorites'].append(model_to_dict(favorite, fields=('id', 'name', 'data', 'location', 'description')))
data.append(obj)
return HttpResponse(data)
On the other hand, if it is an API service and you are using DRF, then it would be something similar to:
serializers.py
from rest_framework import serializers
from django.contrib.auth import get_user_model
from .models import Event
class EventSerializer(serializers.ModelSerializer):
class Meta:
model = Event
fields = ['id', 'image', 'name', 'date', 'location', 'description']
class AccountSerializer(serializers.ModelSerializer):
favorites = serializers.SerializerMethodField()
class Meta:
model = get_user_model()
fields = ['username', 'first_name', 'last_name', 'email', 'phone_number', 'favorites']
def get_favorites(self, obj):
return EventSerializer(obj.favorites.all(), many=True).data
views.py
from rest_framework import generics
from .serializers import AccountSerializer
from django.contrib.auth import get_user_model
class UserListAPIView(generics.ListAPIView):
queryset = get_user_model().objects.all()
serializer_class = AccountSerializer
Obs.: I only implemented GET
requests for both scenarios. You would still have to write POST
(for plain service) or have a ListCreateAPIView and attach an event to an account e.g. account.favorites.add(event)
That favorites table is supposed to be a many to many relationship table especially that you have no additional fields, but what you have done is only link it to the account model, and I m a little bit confused by that favorite field which is just a positive integer? what you should have done instead is
class Account(models.Model):
username = models.CharField(max_length=20, null=True)
.....
favorites = models.ManyToManyField(Event)
this way if you have an account object you can access its favorite events just like this
// create an account
account = new Account(username='foo', firstname....)
account.save()
// create an event
event = new Event(event_name='bar',...)
event.save()
// add an event to an account's favorite events list
account.favorites.add(event)
// access an account's favorite events
account.favorites.all()
You should also be consistent with naming your models and always use singular nouns