Нужно отредактировать запрос django get, чтобы включить список моделей, заданных списком идентификаторов
В настоящее время я создаю бэкенд для сайта, на котором пользователи могут добавлять публичные мероприятия/собрания в список избранного. В настоящее время я создаю модель в Django, которая моделирует созданный пользователем аккаунт под названием Account. Я хочу реализовать это так, чтобы аккаунт включал поле под названием "избранное", которое хранит id событий, которые конкретный аккаунт добавил в избранное.
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)
В настоящее время я могу отправить запрос на почту этой формы, для данного примера этот конкретный аккаунт благоприятствовал событиям с id 15 и 17.
{
"username": "Name",
"first_name": "John",
"last_name": "Doe",
"email": "Johndoe@gmail.com",
"phone_number": "6666666666"
"favorites": [{favorite: "15"}, {favorite: "17"}]
}
Однако после отправки такого запроса post я хочу, чтобы мой запрос get имел такую форму
{
"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",
}
]
}
Я пытаюсь реализовать это таким образом, чтобы после отправки запроса post, когда я вызываю запрос get для определенного аккаунта, вместо того, чтобы вернуть список id для избранных, он вместо этого вернет список вложенных моделей, которым принадлежат эти id. Мне интересно, как приступить к этой реализации, поскольку я не слишком уверен в том, как ее реализовать. Я пытаюсь сделать так, чтобы мой запрос get был такой формы.
Прежде чем ответить на вопрос, я хотел бы поговорить о моделях. Во-первых, хорошей практикой является расширение или замещение модели пользователя. И, во-вторых, отношения many-to-many были бы более адекватными (у одного пользователя много любимых событий, а одно событие любимо многими пользователями).
Пример замены модели, используя приложение с именем 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)
Теперь, связанное с вопросом. Метод реализации будет зависеть от вида service
, если это обычный веб-сервис или API.
Например, для простого web service
вы можете построить ответ самостоятельно, используя списки и словари Python, в данном случае список, содержащий всех пользователей с их любимыми событиями:
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)
С другой стороны, если это API-сервис и вы используете DRF, то это будет что-то похожее на:
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
Обс..: Я реализовал только GET
запросы для обоих сценариев. Вам все равно придется писать POST
(для простого сервиса) или иметь ListCreateAPIView и прикреплять событие к счету, например, account.favorites.add(event)
Эта таблица избранного должна быть таблицей отношений "многие ко многим", особенно если у вас нет дополнительных полей, но то, что вы сделали, это только связать ее с моделью счета, и я немного смущен полем избранного, которое является просто положительным целым числом? Что вы должны были сделать вместо этого:
class Account(models.Model):
username = models.CharField(max_length=20, null=True)
.....
favorites = models.ManyToManyField(Event)
Таким образом, если у вас есть объект счета, вы можете получить доступ к его избранным событиям следующим образом
// 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()
Вы также должны быть последовательны в именовании своих моделей и всегда использовать существительные единственного числа