Нужно отредактировать запрос 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()

Вы также должны быть последовательны в именовании своих моделей и всегда использовать существительные единственного числа

Вернуться на верх