H
H
habrocut2018-02-19 14:41:09
Django
habrocut, 2018-02-19 14:41:09

How to fix error when writing to DB (linked tables)?

Good afternoon!
Please tell me what I'm doing wrong.
Project on python 3.6 + django 2.0 + rest_framework.
The database is sqlite3.
There are 2 related models in the project (respectively 2 related tables in the database): Event (meetings) + Place (places where the meetings will take place).
The Event table has a place field - it must contain the id from the Place table.
Code from models.py file:

class Place(models.Model):
    title_p = models.CharField(max_length=100)
    type_p = models.CharField(max_length=100)
    adress_p = models.CharField(max_length=200)
    link_p = models.CharField(max_length=255)

    class Meta:
        ordering = ('title_p',)
        
class Event(models.Model):
    title = models.CharField(max_length=100)
    description = models.CharField(max_length=200)
    price = models.CharField(max_length=100)
    place = models.ForeignKey(Place, on_delete=models.PROTECT)
    link = models.CharField(max_length=255)
    tags = models.CharField(max_length=200)
    date = models.DateField()
    time = models.TimeField()
    created_at = models.DateTimeField(auto_now_add=True)
    modified_at = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ('created_at',)

Code from serializers.py:
class PlaceSerializer(serializers.ModelSerializer):
    class Meta:
        model = Place
        fields = ('id', 'title_p', 'type_p', 'adress_p', 'link_p')
        
class EventSerializer(serializers.ModelSerializer):
    place = PlaceSerializer(read_only=True)
    class Meta:
        model = Event
        fields = ('id', 'title', 'description', 'price', 'place', 'link', 'date', 'time')

With this approach, it turns out to get GET data from the Event table (with nested values ​​from the Place table):
HTTP 200 OK
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 1,
    "title": "Встреча1",
    "description": "Описание1",
    "price": "100",
    "place": {
        "id": 1,
        "title_p": "Место1",
        "type_p": "ТипМеста1",
        "adress_p": "Адрес1",
        "link_p": "http://vk.com/111/"
    },
    "link": "http://vk.com/11111/",
    "date": null,
    "time": "23:00:00"
}

But if we try to add a new entry to the Event (for example, via httpie), an error appears:
http -a admin:???????? POST http://localhost:8000/events/ title=Встреча2 description=Описание2 price=200 place=1 link=http://vk.com/22222/ date=2018-01-23 time=23:00

Exception Type: IntegrityError at /events/
Exception Value: NOT NULL constraint failed: events_event.place_id

How to fix this error?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
J
javedimka, 2018-02-19
@habrocut

Unfortunately it didn't work, same error:

Пишешь два сериалайзера, один для GET, с твоим, расширенным представлением для связанного Place, другой для POST/PUT с стандартной реализацией которая сериализует связанный объект как его id, потом во вью возвращаешь либо первый либо второй, т.е.:
class EventGETSerializer(serializers.ModelSerializer):
    place = PlaceSerializer(read_only=True)
    class Meta:
        model = Event
        fields = ('id', 'title', 'description', 'price', 'place', 'link', 'date', 'time')

class EventSerializer(serializers.ModelSerializer):
    class Meta:
        model = Event
        fields = ('id', 'title', 'description', 'price', 'place', 'link', 'date', 'time')

В вью переопределяешь get_serializer_class метод:
from rest_framework import permissions


class EventList(generics.ListCreateAPIView):
    queryset = Event.objects.all()

    def get_serializer_class(self):
        if self.request.method in permissions.SAFE_METHODS:
            return EventGETSerializer
        else:
            return EventSerializer

update:
Развивая тему с depth, решил попробовать:
Без блока else не корректно себя ведет, не знаю почему.
Необходимо использовать дженерики/вьюсеты или самому передавать объект запроса в сериалайзер.
from rest_framework.permissions import SAFE_METHODS


class EventSerializer(serializers.ModelSerializer):

    def __init__(self, *args, **kwargs):
        request = kwargs.get('context', {}).get('request')
        if request is not None and request.method not in SAFE_METHODS:
            self.Meta.depth = 0
        else:
            self.Meta.depth = 1
        super().__init__(*args, **kwargs)

    class Meta:
        model = Event
        fields = ('id', 'title', 'description', 'price', 'place', 'link',
                  'date', 'time')

Similar questions

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question